From 3a395142ba99197429a2378930d3c1551fc053cc Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 18 Nov 2011 16:31:59 +0100 Subject: [PATCH 01/12] virtio-blk: fix cross-endian config space Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- hw/virtio-blk.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 19e89e71e..d6d1f87cd 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -485,6 +485,7 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config) struct virtio_blk_config blkcfg; uint64_t capacity; int cylinders, heads, secs; + int blk_size = s->conf->logical_block_size; bdrv_get_geometry(s->bs, &capacity); bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs); @@ -492,14 +493,14 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config) stq_raw(&blkcfg.capacity, capacity); stl_raw(&blkcfg.seg_max, 128 - 2); stw_raw(&blkcfg.cylinders, cylinders); + stl_raw(&blkcfg.blk_size, blk_size); + stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size); + stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size); blkcfg.heads = heads; blkcfg.sectors = secs & ~s->sector_mask; - blkcfg.blk_size = s->conf->logical_block_size; blkcfg.size_max = 0; blkcfg.physical_block_exp = get_physical_block_exp(s->conf); blkcfg.alignment_offset = 0; - blkcfg.min_io_size = s->conf->min_io_size / blkcfg.blk_size; - blkcfg.opt_io_size = s->conf->opt_io_size / blkcfg.blk_size; memcpy(config, &blkcfg, sizeof(struct virtio_blk_config)); } From ce4e7e4661af433674f349ccdd5709b4b7a8b2fd Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 18 Nov 2011 16:32:00 +0100 Subject: [PATCH 02/12] usb-msd: do not register twice in the boot order USB mass storage devices are registered twice in the boot order. To avoid having to keep the two paths in sync, pass the bootindex property down to the scsi-disk device and let it register itself. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- hw/pci-hotplug.c | 3 ++- hw/scsi-bus.c | 7 +++++-- hw/scsi.h | 2 +- hw/usb-msd.c | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c index b59be2a59..12f61fea6 100644 --- a/hw/pci-hotplug.c +++ b/hw/pci-hotplug.c @@ -91,7 +91,8 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter, */ dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1); dinfo->bus = scsibus->busnr; - scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, false); + scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, + false, -1); if (!scsidev) { return -1; } diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 3a2a7bb72..2feeaa299 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -162,7 +162,7 @@ void scsi_qdev_register(SCSIDeviceInfo *info) /* handle legacy '-drive if=scsi,...' cmd line args */ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, - int unit, bool removable) + int unit, bool removable, int bootindex) { const char *driver; DeviceState *dev; @@ -170,6 +170,9 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, driver = bdrv_is_sg(bdrv) ? "scsi-generic" : "scsi-disk"; dev = qdev_create(&bus->qbus, driver); qdev_prop_set_uint32(dev, "scsi-id", unit); + if (bootindex >= 0) { + qdev_prop_set_int32(dev, "bootindex", bootindex); + } if (qdev_prop_exists(dev, "removable")) { qdev_prop_set_bit(dev, "removable", removable); } @@ -195,7 +198,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus) continue; } qemu_opts_loc_restore(dinfo->opts); - if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false)) { + if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1)) { res = -1; break; } diff --git a/hw/scsi.h b/hw/scsi.h index 61c64d5c7..ab6e95232 100644 --- a/hw/scsi.h +++ b/hw/scsi.h @@ -128,7 +128,7 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d) } SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, - int unit, bool removable); + int unit, bool removable, int bootindex); int scsi_bus_legacy_handle_cmdline(SCSIBus *bus); /* diff --git a/hw/usb-msd.c b/hw/usb-msd.c index 68e375678..4c0695012 100644 --- a/hw/usb-msd.c +++ b/hw/usb-msd.c @@ -546,7 +546,8 @@ static int usb_msd_initfn(USBDevice *dev) usb_desc_init(dev); scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info); - s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable); + s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable, + s->conf.bootindex); if (!s->scsi_dev) { return -1; } @@ -562,7 +563,6 @@ static int usb_msd_initfn(USBDevice *dev) } } - add_boot_device_path(s->conf.bootindex, &dev->qdev, "/disk@0,0"); return 0; } From 795928f61daff10b06bb21e837bc5bf0227cf076 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 18 Nov 2011 17:03:45 +0100 Subject: [PATCH 03/12] scsi: fix fw path The pre-1.0 firmware path for SCSI devices already included the LUN using the suffix argument to add_boot_device_path. Avoid that it is included twice, and convert the colons to commas for consistency with other kinds of devices Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- hw/scsi-bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 2feeaa299..64e709ee9 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -1370,8 +1370,8 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev) SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev); char path[100]; - snprintf(path, sizeof(path), "%s@%d,%d,%d", qdev_fw_name(dev), - d->channel, d->id, d->lun); + snprintf(path, sizeof(path), "channel@%x/%s@%x,%x", d->channel, + qdev_fw_name(dev), d->id, d->lun); return strdup(path); } From 28b77657cfb44cdcc379997340701d73432b9007 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 18 Nov 2011 16:32:02 +0100 Subject: [PATCH 04/12] scsi-generic: add as boot device There is no reason why a scsi-generic device cannot boot if it has the right type, and indeed it provides already a bootindex property. So register those devices too. Signed-off-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- hw/scsi-generic.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index 9594cc127..e62044f39 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -413,6 +413,10 @@ static int scsi_generic_initfn(SCSIDevice *s) /* define device state */ s->type = scsiid.scsi_type; DPRINTF("device type %d\n", s->type); + if (s->type == TYPE_DISK || s->type == TYPE_ROM) { + add_boot_device_path(s->conf.bootindex, &s->qdev, NULL); + } + switch (s->type) { case TYPE_TAPE: s->blocksize = get_stream_blocksize(s->conf.bs); @@ -459,6 +463,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun, static SCSIDeviceInfo scsi_generic_info = { .qdev.name = "scsi-generic", + .qdev.fw_name = "disk", .qdev.desc = "pass through generic scsi device (/dev/sg*)", .qdev.size = sizeof(SCSIDevice), .qdev.reset = scsi_generic_reset, From c3fecea50dc0f27198b8658a0c9c4fbfdd0f95db Mon Sep 17 00:00:00 2001 From: Dong Xu Wang Date: Tue, 22 Nov 2011 10:56:58 +0800 Subject: [PATCH 05/12] sheepdog: Avoid deadlock in error path s->lock should be unlocked before leaving add_aio_request. Signed-off-by: Dong Xu Wang Signed-off-by: Kevin Wolf --- block/sheepdog.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/block/sheepdog.c b/block/sheepdog.c index 9f8060960..62f1f3a0c 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1116,6 +1116,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, /* send a header */ ret = do_write(s->fd, &hdr, sizeof(hdr)); if (ret) { + qemu_co_mutex_unlock(&s->lock); error_report("failed to send a req, %s", strerror(errno)); return -EIO; } @@ -1123,6 +1124,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req, if (wlen) { ret = do_writev(s->fd, iov, wlen, aio_req->iov_offset); if (ret) { + qemu_co_mutex_unlock(&s->lock); error_report("failed to send a data, %s", strerror(errno)); return -EIO; } From fd9f102c3e38ac606ef8ee2a5ba0130f7c87422f Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 22 Nov 2011 16:44:45 +0100 Subject: [PATCH 06/12] qcow: Add migration blocker qcow caches L2 tables. For migration to work, they would have to be invalidated. Block migration for now. Signed-off-by: Kevin Wolf --- block/qcow.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/block/qcow.c b/block/qcow.c index adecee06c..4814ed0ce 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -26,6 +26,7 @@ #include "module.h" #include #include "aes.h" +#include "migration.h" /**************************************************************/ /* QEMU COW block driver with compression and encryption support */ @@ -74,6 +75,7 @@ typedef struct BDRVQcowState { AES_KEY aes_encrypt_key; AES_KEY aes_decrypt_key; CoMutex lock; + Error *migration_blocker; } BDRVQcowState; static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset); @@ -160,6 +162,12 @@ static int qcow_open(BlockDriverState *bs, int flags) bs->backing_file[len] = '\0'; } + /* Disable migration when qcow images are used */ + error_set(&s->migration_blocker, + QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, + "qcow", bs->device_name, "live migration"); + migrate_add_blocker(s->migration_blocker); + qemu_co_mutex_init(&s->lock); return 0; @@ -604,10 +612,14 @@ static int qcow_co_writev(BlockDriverState *bs, int64_t sector_num, static void qcow_close(BlockDriverState *bs) { BDRVQcowState *s = bs->opaque; + g_free(s->l1_table); g_free(s->l2_cache); g_free(s->cluster_cache); g_free(s->cluster_data); + + migrate_del_blocker(s->migration_blocker); + error_free(s->migration_blocker); } static int qcow_create(const char *filename, QEMUOptionParameter *options) From fc9d106c8dfe1c4afe0e127dfcd2764e63f0efb0 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 22 Nov 2011 16:46:26 +0100 Subject: [PATCH 07/12] vdi: Add migration blocker vdi caches the block map. For migration to work, it would have to be invalidated. Block migration for now. Signed-off-by: Kevin Wolf --- block/vdi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/block/vdi.c b/block/vdi.c index 684a4a87b..7dda5222e 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -52,6 +52,7 @@ #include "qemu-common.h" #include "block_int.h" #include "module.h" +#include "migration.h" #if defined(CONFIG_UUID) #include @@ -203,6 +204,8 @@ typedef struct { uint32_t bmap_sector; /* VDI header (converted to host endianness). */ VdiHeader header; + + Error *migration_blocker; } BDRVVdiState; /* Change UUID from little endian (IPRT = VirtualBox format) to big endian @@ -454,6 +457,12 @@ static int vdi_open(BlockDriverState *bs, int flags) goto fail_free_bmap; } + /* Disable migration when vdi images are used */ + error_set(&s->migration_blocker, + QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, + "vdi", bs->device_name, "live migration"); + migrate_add_blocker(s->migration_blocker); + return 0; fail_free_bmap: @@ -939,6 +948,9 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options) static void vdi_close(BlockDriverState *bs) { + BDRVVdiState *s = bs->opaque; + migrate_del_blocker(s->migration_blocker); + error_free(s->migration_blocker); } static coroutine_fn int vdi_co_flush(BlockDriverState *bs) From 2bc3166c22aeeb5cd7b8f21104f4744f08c7a288 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 22 Nov 2011 16:50:27 +0100 Subject: [PATCH 08/12] vmdk: Add migration blocker VMDK caches L2 tables. For migration to work, they would have to be invalidated. Block migration for now. Signed-off-by: Kevin Wolf --- block/vmdk.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/block/vmdk.c b/block/vmdk.c index 96f7d5d90..f5441591d 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -26,6 +26,7 @@ #include "qemu-common.h" #include "block_int.h" #include "module.h" +#include "migration.h" #include #define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D') @@ -97,6 +98,7 @@ typedef struct BDRVVmdkState { int num_extents; /* Extent array with num_extents entries, ascend ordered by address */ VmdkExtent *extents; + Error *migration_blocker; } BDRVVmdkState; typedef struct VmdkMetaData { @@ -659,7 +661,14 @@ static int vmdk_open(BlockDriverState *bs, int flags) } s->parent_cid = vmdk_read_cid(bs, 1); qemu_co_mutex_init(&s->lock); - return ret; + + /* Disable migration when VMDK images are used */ + error_set(&s->migration_blocker, + QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, + "vmdk", bs->device_name, "live migration"); + migrate_add_blocker(s->migration_blocker); + + return 0; fail: vmdk_free_extents(bs); @@ -1504,7 +1513,12 @@ exit: static void vmdk_close(BlockDriverState *bs) { + BDRVVmdkState *s = bs->opaque; + vmdk_free_extents(bs); + + migrate_del_blocker(s->migration_blocker); + error_free(s->migration_blocker); } static coroutine_fn int vmdk_co_flush(BlockDriverState *bs) From 612ff3d8876a6df0484aa6ebb5cae4575f7514c5 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 22 Nov 2011 16:51:12 +0100 Subject: [PATCH 09/12] vpc: Add migration blocker vpc caches the BAT. For migration to work, it would have to be invalidated. Block migration for now. Signed-off-by: Kevin Wolf --- block/vpc.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/block/vpc.c b/block/vpc.c index 39a324705..75d7d4ac7 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -25,6 +25,7 @@ #include "qemu-common.h" #include "block_int.h" #include "module.h" +#include "migration.h" /**************************************************************/ @@ -128,6 +129,8 @@ typedef struct BDRVVPCState { uint64_t last_bitmap; #endif + + Error *migration_blocker; } BDRVVPCState; static uint32_t vpc_checksum(uint8_t* buf, size_t size) @@ -228,6 +231,13 @@ static int vpc_open(BlockDriverState *bs, int flags) #endif qemu_co_mutex_init(&s->lock); + + /* Disable migration when VHD images are used */ + error_set(&s->migration_blocker, + QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, + "vpc", bs->device_name, "live migration"); + migrate_add_blocker(s->migration_blocker); + return 0; fail: return err; @@ -651,6 +661,9 @@ static void vpc_close(BlockDriverState *bs) #ifdef CACHE g_free(s->pageentry_u8); #endif + + migrate_del_blocker(s->migration_blocker); + error_free(s->migration_blocker); } static QEMUOptionParameter vpc_create_options[] = { From 3397f0cb483b40785678d2328da584c8a35c358c Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 22 Nov 2011 16:52:13 +0100 Subject: [PATCH 10/12] vvfat: Add migration blocker vvfat caches more or less everything when in writable mode. For migration to work, it would have to be invalidated. Block migration for now when in writable mode (default is readonly). Signed-off-by: Kevin Wolf --- block/vvfat.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/block/vvfat.c b/block/vvfat.c index 131680f6f..a310ce8c3 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -27,6 +27,7 @@ #include "qemu-common.h" #include "block_int.h" #include "module.h" +#include "migration.h" #ifndef S_IWGRP #define S_IWGRP 0 @@ -350,6 +351,8 @@ typedef struct BDRVVVFATState { array_t commits; const char* path; int downcase_short_names; + + Error *migration_blocker; } BDRVVVFATState; /* take the sector position spos and convert it to Cylinder/Head/Sector position @@ -1073,6 +1076,15 @@ DLOG(if (stderr == NULL) { // assert(is_consistent(s)); qemu_co_mutex_init(&s->lock); + + /* Disable migration when vvfat is used rw */ + if (s->qcow) { + error_set(&s->migration_blocker, + QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED, + "vvfat (rw)", bs->device_name, "live migration"); + migrate_add_blocker(s->migration_blocker); + } + return 0; } @@ -2829,6 +2841,11 @@ static void vvfat_close(BlockDriverState *bs) array_free(&(s->directory)); array_free(&(s->mapping)); g_free(s->cluster_buffer); + + if (s->qcow) { + migrate_del_blocker(s->migration_blocker); + error_free(s->migration_blocker); + } } static BlockDriver bdrv_vvfat = { From 6ac5f3881fd9880f55e30c5f5bd9984d9d47fd62 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 22 Nov 2011 16:57:34 +0100 Subject: [PATCH 11/12] vdi: Fix memory leak The block map is allocated in vdi_open, but was never freed. Signed-off-by: Kevin Wolf --- block/vdi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/block/vdi.c b/block/vdi.c index 7dda5222e..02da6b44d 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -949,6 +949,9 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options) static void vdi_close(BlockDriverState *bs) { BDRVVdiState *s = bs->opaque; + + g_free(s->bmap); + migrate_del_blocker(s->migration_blocker); error_free(s->migration_blocker); } From 5bb1cbac4fdb1ca28f33c8d68538d03e3db7c160 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 23 Nov 2011 11:38:01 +0100 Subject: [PATCH 12/12] vpc: Add missing error handling in alloc_block Signed-off-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi --- block/vpc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/block/vpc.c b/block/vpc.c index 75d7d4ac7..89a5ee266 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -362,8 +362,11 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num) // Initialize the block's bitmap memset(bitmap, 0xff, s->bitmap_size); - bdrv_pwrite_sync(bs->file, s->free_data_block_offset, bitmap, + ret = bdrv_pwrite_sync(bs->file, s->free_data_block_offset, bitmap, s->bitmap_size); + if (ret < 0) { + return ret; + } // Write new footer (the old one will be overwritten) s->free_data_block_offset += s->block_size + s->bitmap_size;