This patch add a new parameter to "-drive" Using "directio=on" with "-drive" will open the disk image file using "O_DIRECT".
By default, "directio" is set to "off". example: "-drive file=my_disk.qcow2,directio=on" --- block-raw.c | 4 ++++ block.c | 2 +- block.h | 1 + hw/fdc.c | 6 +++++- hw/ide.c | 8 ++++++-- hw/scsi-disk.c | 3 ++- hw/sd.c | 10 +++++++++- vl.c | 26 +++++++++++++++++++++++--- 8 files changed, 51 insertions(+), 9 deletions(-) Index: qemu/block-raw.c =================================================================== --- qemu.orig/block-raw.c 2007-11-25 18:10:07.000000000 +0100 +++ qemu/block-raw.c 2007-11-25 18:21:04.000000000 +0100 @@ -107,6 +107,8 @@ static int raw_open(BlockDriverState *bs } if (flags & BDRV_O_CREAT) open_flags |= O_CREAT | O_TRUNC; + if (flags & BDRV_O_DIRECT) + open_flags |= O_DIRECT; s->type = FTYPE_FILE; @@ -660,6 +662,8 @@ static int hdev_open(BlockDriverState *b open_flags |= O_RDONLY; bs->read_only = 1; } + if (flags & BDRV_O_DIRECT) + open_flags |= O_DIRECT; s->type = FTYPE_FILE; #if defined(__linux__) Index: qemu/block.h =================================================================== --- qemu.orig/block.h 2007-11-25 18:10:07.000000000 +0100 +++ qemu/block.h 2007-11-25 18:21:04.000000000 +0100 @@ -44,6 +44,7 @@ typedef struct QEMUSnapshotInfo { use a disk image format on top of it (default for bdrv_file_open()) */ +#define BDRV_O_DIRECT 0x0020 #ifndef QEMU_IMG void bdrv_info(void); Index: qemu/vl.c =================================================================== --- qemu.orig/vl.c 2007-11-25 18:10:07.000000000 +0100 +++ qemu/vl.c 2007-11-25 18:21:04.000000000 +0100 @@ -4847,8 +4847,11 @@ static int drive_init(const char *str, i BlockDriverState *bdrv; int max_devs; int index; + int directio; + int bdrv_flags; char *params[] = { "bus", "unit", "if", "index", "cyls", "heads", - "secs", "trans", "media", "snapshot", "file", NULL }; + "secs", "trans", "media", "snapshot", "file", + "directio", NULL }; if (check_params(buf, sizeof(buf), params, str) < 0) { fprintf(stderr, "qemu: unknowm parameter '%s' in '%s'\n", @@ -4862,6 +4865,7 @@ static int drive_init(const char *str, i unit_id = -1; translation = BIOS_ATA_TRANSLATION_AUTO; index = -1; + directio = 0; if (!strcmp(machine->name, "realview") || !strcmp(machine->name, "SS-5") || @@ -5001,6 +5005,17 @@ static int drive_init(const char *str, i } } + if (get_param_value(buf, sizeof(buf), "directio", str)) { + if (!strcmp(buf, "off")) + directio = 0; + else if (!strcmp(buf, "on")) + directio = 1; + else { + fprintf(stderr, "qemu: invalid directio option\n"); + return -1; + } + } + get_param_value(file, sizeof(file), "file", str); /* compute bus and unit according index */ @@ -5088,8 +5103,12 @@ static int drive_init(const char *str, i } if (!file[0]) return 0; - if (bdrv_open(bdrv, file, snapshot ? BDRV_O_SNAPSHOT : 0) < 0 || - qemu_key_check(bdrv, file)) { + bdrv_flags = 0; + if (snapshot) + bdrv_flags |= BDRV_O_SNAPSHOT; + if (directio) + bdrv_flags |= BDRV_O_DIRECT; + if (bdrv_open(bdrv, file, bdrv_flags) < 0 || qemu_key_check(bdrv, file)) { fprintf(stderr, "qemu: could not open disk image %s\n", file); return -1; @@ -7434,6 +7453,7 @@ static void help(int exitcode) "-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n" "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][index=i]\n" " [,cyls=c,heads=h,secs=s[,trans=t]][snapshot=on|off]\n" + " [directio=on|off]\n" " use 'file' as a drive image\n" "-mtdblock file use 'file' as on-board Flash memory image\n" "-sd file use 'file' as SecureDigital card image\n" Index: qemu/hw/ide.c =================================================================== --- qemu.orig/hw/ide.c 2007-11-25 18:10:07.000000000 +0100 +++ qemu/hw/ide.c 2007-11-25 18:21:04.000000000 +0100 @@ -365,7 +365,7 @@ typedef struct IDEState { EndTransferFunc *end_transfer_func; uint8_t *data_ptr; uint8_t *data_end; - uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4]; + uint8_t *io_buffer; QEMUTimer *sector_write_timer; /* only used for win2k install hack */ uint32_t irq_count; /* counts IRQs when using win2k install hack */ /* CF-ATA extended error */ @@ -2372,11 +2372,14 @@ struct partition { static int guess_disk_lchs(IDEState *s, int *pcylinders, int *pheads, int *psectors) { - uint8_t buf[512]; + uint8_t *buf; int ret, i, heads, sectors, cylinders; struct partition *p; uint32_t nr_sects; + ret = posix_memalign((void**)&buf, 0x200, 512); + if (ret < 0) + return -1; ret = bdrv_read(s->bs, 0, buf, 1); if (ret < 0) return -1; @@ -2420,6 +2423,7 @@ static void ide_init2(IDEState *ide_stat for(i = 0; i < 2; i++) { s = ide_state + i; + posix_memalign((void**)&s->io_buffer, 0x200, MAX_MULT_SECTORS*512 + 4); if (i == 0) s->bs = hd0; else Index: qemu/block.c =================================================================== --- qemu.orig/block.c 2007-11-25 18:10:07.000000000 +0100 +++ qemu/block.c 2007-11-25 18:21:04.000000000 +0100 @@ -380,7 +380,7 @@ int bdrv_open2(BlockDriverState *bs, con /* Note: for compatibility, we open disk image files as RDWR, and RDONLY as fallback */ if (!(flags & BDRV_O_FILE)) - open_flags = BDRV_O_RDWR; + open_flags = BDRV_O_RDWR | (flags & BDRV_O_DIRECT); else open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT); ret = drv->bdrv_open(bs, filename, open_flags); Index: qemu/hw/scsi-disk.c =================================================================== --- qemu.orig/hw/scsi-disk.c 2007-11-25 18:10:07.000000000 +0100 +++ qemu/hw/scsi-disk.c 2007-11-25 18:21:04.000000000 +0100 @@ -46,7 +46,7 @@ typedef struct SCSIRequest { int sector_count; /* The amounnt of data in the buffer. */ int buf_len; - uint8_t dma_buf[SCSI_DMA_BUF_SIZE]; + uint8_t *dma_buf; BlockDriverAIOCB *aiocb; struct SCSIRequest *next; } SCSIRequest; @@ -78,6 +78,7 @@ static SCSIRequest *scsi_new_request(SCS free_requests = r->next; } else { r = qemu_malloc(sizeof(SCSIRequest)); + posix_memalign(&r->dma_buf, 0x200, SCSI_DMA_BUF_SIZE); } r->dev = s; r->tag = tag; Index: qemu/hw/sd.c =================================================================== --- qemu.orig/hw/sd.c 2007-11-25 18:10:07.000000000 +0100 +++ qemu/hw/sd.c 2007-11-25 18:21:04.000000000 +0100 @@ -1284,10 +1284,16 @@ int sd_do_command(SDState *sd, struct sd static void sd_blk_read(BlockDriverState *bdrv, void *data, uint32_t addr, uint32_t len) { - uint8_t buf[512]; + uint8_t *buf; uint32_t end = addr + len; + if (posix_memalign(&buf, 512, 512) < 0) { + printf("sd_blk_read: cannot allocate memory\n"); + return; + } + if (!bdrv || bdrv_read(bdrv, addr >> 9, buf, 1) == -1) { + free(buf); printf("sd_blk_read: read error on host side\n"); return; } @@ -1297,11 +1303,13 @@ static void sd_blk_read(BlockDriverState if (bdrv_read(bdrv, end >> 9, buf, 1) == -1) { printf("sd_blk_read: read error on host side\n"); + free(buf); return; } memcpy(data + 512 - (addr & 511), buf, end & 511); } else memcpy(data, buf + (addr & 511), len); + free(buf); } static void sd_blk_write(BlockDriverState *bdrv, Index: qemu/hw/fdc.c =================================================================== --- qemu.orig/hw/fdc.c 2007-11-25 18:10:07.000000000 +0100 +++ qemu/hw/fdc.c 2007-11-25 18:21:04.000000000 +0100 @@ -382,7 +382,7 @@ struct fdctrl_t { uint8_t cur_drv; uint8_t bootsel; /* Command FIFO */ - uint8_t fifo[FD_SECTOR_LEN]; + uint8_t *fifo; uint32_t data_pos; uint32_t data_len; uint8_t data_state; @@ -598,6 +598,10 @@ fdctrl_t *fdctrl_init (qemu_irq irq, int fdctrl = qemu_mallocz(sizeof(fdctrl_t)); if (!fdctrl) return NULL; + if (posix_memalign((void**)&fdctrl->fifo, 512, FD_SECTOR_LEN) <0) { + free(fdctrl); + return NULL; + } fdctrl->result_timer = qemu_new_timer(vm_clock, fdctrl_result_timer, fdctrl);