diff --git a/aio.c b/aio.c index f164a478c5..2f086557b6 100644 --- a/aio.c +++ b/aio.c @@ -113,7 +113,9 @@ void qemu_aio_flush(void) qemu_aio_wait(); QLIST_FOREACH(node, &aio_handlers, node) { - ret |= node->io_flush(node->opaque); + if (node->io_flush) { + ret |= node->io_flush(node->opaque); + } } } while (qemu_bh_poll() || ret > 0); } diff --git a/block.c b/block.c index bfe46e3765..0b0966c571 100644 --- a/block.c +++ b/block.c @@ -329,6 +329,11 @@ static BlockDriver *find_image_format(const char *filename) ret = bdrv_file_open(&bs, filename, 0); if (ret < 0) return NULL; + + /* Return the raw BlockDriver * to scsi-generic devices */ + if (bs->sg) + return bdrv_find_format("raw"); + ret = bdrv_pread(bs, 0, buf, sizeof(buf)); bdrv_delete(bs); if (ret < 0) { @@ -356,6 +361,10 @@ static int refresh_total_sectors(BlockDriverState *bs, int64_t hint) { BlockDriver *drv = bs->drv; + /* Do not attempt drv->bdrv_getlength() on scsi-generic devices */ + if (bs->sg) + return 0; + /* query actual device if possible, otherwise just trust the hint */ if (drv->bdrv_getlength) { int64_t length = drv->bdrv_getlength(bs); @@ -1929,7 +1938,19 @@ static void multiwrite_cb(void *opaque, int ret) static int multiwrite_req_compare(const void *a, const void *b) { - return (((BlockRequest*) a)->sector - ((BlockRequest*) b)->sector); + const BlockRequest *req1 = a, *req2 = b; + + /* + * Note that we can't simply subtract req2->sector from req1->sector + * here as that could overflow the return value. + */ + if (req1->sector > req2->sector) { + return 1; + } else if (req1->sector < req2->sector) { + return -1; + } else { + return 0; + } } /* diff --git a/block/vvfat.c b/block/vvfat.c index ce16bbd8c4..6d61c2e6c3 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -1244,7 +1244,7 @@ static void print_direntry(const direntry_t* direntry) int j = 0; char buffer[1024]; - fprintf(stderr, "direntry 0x%x: ", (int)direntry); + fprintf(stderr, "direntry %p: ", direntry); if(!direntry) return; if(is_long_name(direntry)) { @@ -1273,7 +1273,11 @@ static void print_direntry(const direntry_t* direntry) static void print_mapping(const mapping_t* mapping) { - fprintf(stderr, "mapping (0x%x): begin, end = %d, %d, dir_index = %d, first_mapping_index = %d, name = %s, mode = 0x%x, " , (int)mapping, mapping->begin, mapping->end, mapping->dir_index, mapping->first_mapping_index, mapping->path, mapping->mode); + fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, " + "first_mapping_index = %d, name = %s, mode = 0x%x, " , + mapping, mapping->begin, mapping->end, mapping->dir_index, + mapping->first_mapping_index, mapping->path, mapping->mode); + if (mapping->mode & MODE_DIRECTORY) fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index); else @@ -2865,7 +2869,7 @@ static void checkpoint(void) { return; /* avoid compiler warnings: */ hexdump(NULL, 100); - remove_mapping(vvv, NULL); + remove_mapping(vvv, 0); print_mapping(NULL); print_direntry(NULL); } diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index b05d15ecdd..5d7f1a2200 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -105,8 +105,10 @@ static void virtio_blk_flush_complete(void *opaque, int ret) static VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s) { - VirtIOBlockReq *req = qemu_mallocz(sizeof(*req)); + VirtIOBlockReq *req = qemu_malloc(sizeof(*req)); req->dev = s; + req->qiov.size = 0; + req->next = NULL; return req; } @@ -238,10 +240,20 @@ static void do_multiwrite(BlockDriverState *bs, BlockRequest *blkreq, } } -static void virtio_blk_handle_flush(VirtIOBlockReq *req) +static void virtio_blk_handle_flush(BlockRequest *blkreq, int *num_writes, + VirtIOBlockReq *req, BlockDriverState **old_bs) { BlockDriverAIOCB *acb; + /* + * Make sure all outstanding writes are posted to the backing device. + */ + if (*old_bs != NULL) { + do_multiwrite(*old_bs, blkreq, *num_writes); + } + *num_writes = 0; + *old_bs = req->dev->bs; + acb = bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req); if (!acb) { virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR); @@ -314,7 +326,8 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req, req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base; if (req->out->type & VIRTIO_BLK_T_FLUSH) { - virtio_blk_handle_flush(req); + virtio_blk_handle_flush(mrb->blkreq, &mrb->num_writes, + req, &mrb->old_bs); } else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) { virtio_blk_handle_scsi(req); } else if (req->out->type & VIRTIO_BLK_T_OUT) {