On Fri, Dec 16, 2016 at 4:44 PM, Greg Kurz <gr...@kaod.org> wrote: > On Fri, 16 Dec 2016 15:23:44 +0530 > Ashijeet Acharya <ashijeetacha...@gmail.com> wrote: > >> migrate_add_blocker should rightly fail if the '--only-migratable' >> option was specified and the device in use should not be able to >> perform the action which results in an unmigratable VM. >> >> Make migrate_add_blocker return -EACCES in this case. >> >> Signed-off-by: Ashijeet Acharya <ashijeetacha...@gmail.com> >> --- >> block/qcow.c | 7 +++++-- >> block/vdi.c | 7 +++++-- >> block/vhdx.c | 8 +++++--- >> block/vmdk.c | 7 +++++-- >> block/vpc.c | 7 +++++-- >> block/vvfat.c | 8 +++++--- >> hw/9pfs/9p.c | 9 +++++++-- >> hw/display/virtio-gpu.c | 9 +++++++-- >> hw/intc/arm_gic_kvm.c | 7 +++++-- >> hw/intc/arm_gicv3_its_kvm.c | 5 ++++- >> hw/intc/arm_gicv3_kvm.c | 5 ++++- >> hw/misc/ivshmem.c | 10 ++++++++-- >> hw/scsi/vhost-scsi.c | 10 ++++++---- >> hw/virtio/vhost.c | 8 +++++--- >> migration/migration.c | 7 +++++++ >> target-i386/kvm.c | 7 +++++-- >> 16 files changed, 88 insertions(+), 33 deletions(-) >> >> diff --git a/block/qcow.c b/block/qcow.c >> index 11526a1..7e5003ac 100644 >> --- a/block/qcow.c >> +++ b/block/qcow.c >> @@ -253,8 +253,11 @@ static int qcow_open(BlockDriverState *bs, QDict >> *options, int flags, >> "does not support live migration", >> bdrv_get_device_or_node_name(bs)); >> ret = migrate_add_blocker(s->migration_blocker, errp); >> - if (ret < 0) { >> - error_free(s->migration_blocker); >> + if (ret) { >> + if (ret == -EACCES) { >> + error_append_hint(errp, "Cannot use a node with qcow format as " >> + "it does not support live migration"); >> + } >> goto fail; >> } >> >> diff --git a/block/vdi.c b/block/vdi.c >> index 2b56f52..df45df4 100644 >> --- a/block/vdi.c >> +++ b/block/vdi.c >> @@ -472,8 +472,11 @@ static int vdi_open(BlockDriverState *bs, QDict >> *options, int flags, >> "does not support live migration", >> bdrv_get_device_or_node_name(bs)); >> ret = migrate_add_blocker(s->migration_blocker, errp); >> - if (ret < 0) { >> - error_free(s->migration_blocker); >> + if (ret) { >> + if (ret == -EACCES) { >> + error_append_hint(errp, "Cannot use a node with vdi format as " >> + "it does not support live migration"); >> + } >> goto fail_free_bmap; >> } >> >> diff --git a/block/vhdx.c b/block/vhdx.c >> index d81941b..118134e 100644 >> --- a/block/vhdx.c >> +++ b/block/vhdx.c >> @@ -996,11 +996,13 @@ static int vhdx_open(BlockDriverState *bs, QDict >> *options, int flags, >> "does not support live migration", >> bdrv_get_device_or_node_name(bs)); >> ret = migrate_add_blocker(s->migration_blocker, errp); >> - if (ret < 0) { >> - error_free(s->migration_blocker); >> + if (ret) { >> + if (ret == -EACCES) { >> + error_append_hint(errp, "Cannot use a node with vhdx format as " >> + "it does not support live migration"); >> + } >> goto fail; >> } >> - >> if (flags & BDRV_O_RDWR) { >> ret = vhdx_update_headers(bs, s, false, NULL); >> if (ret < 0) { >> diff --git a/block/vmdk.c b/block/vmdk.c >> index 4a45a83..cd6a641 100644 >> --- a/block/vmdk.c >> +++ b/block/vmdk.c >> @@ -977,8 +977,11 @@ static int vmdk_open(BlockDriverState *bs, QDict >> *options, int flags, >> "does not support live migration", >> bdrv_get_device_or_node_name(bs)); >> ret = migrate_add_blocker(s->migration_blocker, errp); >> - if (ret < 0) { >> - error_free(s->migration_blocker); >> + if (ret) { >> + if (ret == -EACCES) { >> + error_append_hint(errp, "Cannot use a node with vmdk format as " >> + "it does not support live migration"); >> + } >> goto fail; >> } >> >> diff --git a/block/vpc.c b/block/vpc.c >> index 299a8c8..c935962 100644 >> --- a/block/vpc.c >> +++ b/block/vpc.c >> @@ -427,8 +427,11 @@ static int vpc_open(BlockDriverState *bs, QDict >> *options, int flags, >> "does not support live migration", >> bdrv_get_device_or_node_name(bs)); >> ret = migrate_add_blocker(s->migration_blocker, errp); >> - if (ret < 0) { >> - error_free(s->migration_blocker); >> + if (ret) { >> + if (ret == -EACCES) { >> + error_append_hint(errp, "Cannot use a node with vpc format as " >> + "it does not support live migration"); >> + } >> goto fail; >> } >> >> diff --git a/block/vvfat.c b/block/vvfat.c >> index 3de3320..f9a5f9b 100644 >> --- a/block/vvfat.c >> +++ b/block/vvfat.c >> @@ -1192,8 +1192,11 @@ static int vvfat_open(BlockDriverState *bs, QDict >> *options, int flags, >> "does not support live migration", >> bdrv_get_device_or_node_name(bs)); >> ret = migrate_add_blocker(s->migration_blocker, errp); >> - if (ret < 0) { >> - error_free(s->migration_blocker); >> + if (ret) { >> + if (ret == -EACCES) { >> + error_append_hint(errp, "Cannot use a node with vvfat >> format " >> + "as it does not support live migration"); >> + } >> goto fail; >> } >> } >> @@ -1202,7 +1205,6 @@ static int vvfat_open(BlockDriverState *bs, QDict >> *options, int flags, >> init_mbr(s, cyls, heads, secs); >> } >> >> - // assert(is_consistent(s)); >> qemu_co_mutex_init(&s->lock); >> >> ret = 0; >> diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c >> index e72ef43..01dd67f 100644 >> --- a/hw/9pfs/9p.c >> +++ b/hw/9pfs/9p.c >> @@ -1020,12 +1020,17 @@ static void coroutine_fn v9fs_attach(void *opaque) >> */ >> if (!s->migration_blocker) { >> int ret; >> + Error *local_err; >> s->root_fid = fid; >> error_setg(&s->migration_blocker, >> "Migration is disabled when VirtFS export path '%s' is >> mounted in the guest using mount_tag '%s'", >> s->ctx.fs_root ? s->ctx.fs_root : "NULL", s->tag); >> - ret = migrate_add_blocker(s->migration_blocker, NULL); >> - if (ret < 0) { >> + ret = migrate_add_blocker(s->migration_blocker, &local_err); >> + if (ret) { > > Why s/ret < 0/ret/ ? The migrate_add_blocker() function in this v2 only > returns 0 or a negative errno...
No reason, maybe I forgot to change it back because I got no logical error after compiling but I have fixed this at all occurrences. > >> + if (ret == -EACCES) { >> + error_append_hint(&local_err, "Failed to mount VirtFS as it >> " >> + "does not support live migration"); > > And then local_err is leaked... Yes, I have freed it with error_free(). > > BTW, I'm not even sure if this useful since this is a guest originated action. > >> + } > > This errno will be ultimately be returned to the mount(2) caller in the guest. > > When reading the manpage, it looks like EBUSY definitely makes more sense than > EACCES: > > EACCES A component of a path was not searchable. (See also path_reso‐ > lution(7).) Or, mounting a read-only filesystem was attempted > without giving the MS_RDONLY flag. Or, the block device source > is located on a filesystem mounted with the MS_NODEV option. > > EBUSY source is already mounted. Or, it cannot be remounted read- > only, because it still holds files open for writing. Or, it > cannot be mounted on target because target is still busy (it is > the working directory of some thread, the mount point of another > device, has open files, etc.). > Reading the manpages definitely make your argument stronger but I am not sure if I will be able to differentiate between what caused the migrate_add_blocker to fail if I get -EBUSY for both the cases. Ashijeet >> err = ret; >> clunk_fid(s, fid); >> goto out; >> diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c >> index 6e60b8c..1b02f4b 100644 >> --- a/hw/display/virtio-gpu.c >> +++ b/hw/display/virtio-gpu.c >> @@ -1102,6 +1102,7 @@ static void virtio_gpu_device_realize(DeviceState >> *qdev, Error **errp) >> VirtIOGPU *g = VIRTIO_GPU(qdev); >> bool have_virgl; >> int i; >> + int ret; >> >> if (g->conf.max_outputs > VIRTIO_GPU_MAX_SCANOUTS) { >> error_setg(errp, "invalid max_outputs > %d", >> VIRTIO_GPU_MAX_SCANOUTS); >> @@ -1120,8 +1121,12 @@ static void virtio_gpu_device_realize(DeviceState >> *qdev, Error **errp) >> >> if (virtio_gpu_virgl_enabled(g->conf)) { >> error_setg(&g->migration_blocker, "virgl is not yet migratable"); >> - if (migrate_add_blocker(g->migration_blocker, errp) < 0) { >> - error_free(g->migration_blocker); >> + ret = migrate_add_blocker(g->migration_blocker, errp); >> + if (ret) { >> + if (ret == -EACCES) { >> + error_append_hint(errp, "Cannot use virgl as it does not " >> + "support live migration yet"); >> + } >> return; >> } >> } >> diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c >> index 3614daa..b40ad5f 100644 >> --- a/hw/intc/arm_gic_kvm.c >> +++ b/hw/intc/arm_gic_kvm.c >> @@ -514,8 +514,11 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error >> **errp) >> error_setg(&s->migration_blocker, "This operating system kernel >> does " >> "not support vGICv2 migration"); >> ret = migrate_add_blocker(s->migration_blocker, errp); >> - if (ret < 0) { >> - error_free(s->migration_blocker); >> + if (ret) { >> + if (ret == -EACCES) { >> + error_append_hint(errp, "Failed to realize vGICv2 as its" >> + " migrataion is not implemented yet"); >> + } >> return; >> } >> } >> diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c >> index 950a02f..3474642 100644 >> --- a/hw/intc/arm_gicv3_its_kvm.c >> +++ b/hw/intc/arm_gicv3_its_kvm.c >> @@ -70,7 +70,10 @@ static void kvm_arm_its_realize(DeviceState *dev, Error >> **errp) >> error_setg(&s->migration_blocker, "vITS migration is not implemented"); >> ret = migrate_add_blocker(s->migration_blocker, errp); >> if (ret < 0) { >> - error_free(s->migration_blocker); >> + if (ret == -EACCES) { >> + error_append_hint(errp, "Failed to realize vITS as its >> migration " >> + "is not implemented yet"); >> + } >> return; >> } >> >> diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c >> index 06f6f30..be7b97c 100644 >> --- a/hw/intc/arm_gicv3_kvm.c >> +++ b/hw/intc/arm_gicv3_kvm.c >> @@ -118,7 +118,10 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, >> Error **errp) >> error_setg(&s->migration_blocker, "vGICv3 migration is not >> implemented"); >> ret = migrate_add_blocker(s->migration_blocker, errp); >> if (ret < 0) { >> - error_free(s->migration_blocker); >> + if (ret == -EACCES) { >> + error_append_hint(errp, "Failed to realize vGICv3 as its >> migration" >> + "is not implemented yet"); >> + } >> return; >> } >> >> diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c >> index 585cc5b..58f27b1 100644 >> --- a/hw/misc/ivshmem.c >> +++ b/hw/misc/ivshmem.c >> @@ -837,6 +837,7 @@ static void ivshmem_common_realize(PCIDevice *dev, Error >> **errp) >> { >> IVShmemState *s = IVSHMEM_COMMON(dev); >> Error *err = NULL; >> + int ret; >> uint8_t *pci_conf; >> uint8_t attr = PCI_BASE_ADDRESS_SPACE_MEMORY | >> PCI_BASE_ADDRESS_MEM_PREFETCH; >> @@ -910,8 +911,13 @@ static void ivshmem_common_realize(PCIDevice *dev, >> Error **errp) >> if (!ivshmem_is_master(s)) { >> error_setg(&s->migration_blocker, >> "Migration is disabled when using feature 'peer mode' in >> device 'ivshmem'"); >> - if (migrate_add_blocker(s->migration_blocker, errp) < 0) { >> - error_free(s->migration_blocker); >> + ret = migrate_add_blocker(s->migration_blocker, errp); >> + if (ret) { >> + if (ret == -EACCES) { >> + error_append_hint(errp, "Cannot use the 'peer mode' feature >> " >> + "in device 'ivshmem' as it does not " >> + "support live migration"); >> + } >> return; >> } >> } >> diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c >> index ff503d0..0c571f8 100644 >> --- a/hw/scsi/vhost-scsi.c >> +++ b/hw/scsi/vhost-scsi.c >> @@ -244,8 +244,12 @@ static void vhost_scsi_realize(DeviceState *dev, Error >> **errp) >> error_setg(&s->migration_blocker, >> "vhost-scsi does not support migration"); >> ret = migrate_add_blocker(s->migration_blocker, errp); >> - if (ret < 0) { >> - goto free_blocker; >> + if (ret) { >> + if (ret == -EACCES) { >> + error_append_hint(errp, "Cannot use vhost-scsi as it does not " >> + "support live migration"); >> + } >> + goto close_fd; >> } >> >> s->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues; >> @@ -272,8 +276,6 @@ static void vhost_scsi_realize(DeviceState *dev, Error >> **errp) >> free_vqs: >> migrate_del_blocker(s->migration_blocker); >> g_free(s->dev.vqs); >> - free_blocker: >> - error_free(s->migration_blocker); >> close_fd: >> close(vhostfd); >> return; >> diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c >> index 416fada..1c4a4f9 100644 >> --- a/hw/virtio/vhost.c >> +++ b/hw/virtio/vhost.c >> @@ -1159,9 +1159,11 @@ int vhost_dev_init(struct vhost_dev *hdev, void >> *opaque, >> if (hdev->migration_blocker != NULL) { >> Error *local_err; >> r = migrate_add_blocker(hdev->migration_blocker, &local_err); >> - if (r < 0) { >> - error_report_err(local_err); >> - error_free(hdev->migration_blocker); >> + if (r) { >> + if (r == -EACCES) { >> + error_append_hint(&local_err, "Cannot use vhost drivers as " >> + "it does not support live migration"); >> + } >> goto fail_busyloop; >> } >> } >> diff --git a/migration/migration.c b/migration/migration.c >> index 713e012..ab34328 100644 >> --- a/migration/migration.c >> +++ b/migration/migration.c >> @@ -1115,9 +1115,16 @@ int migrate_add_blocker(Error *reason, Error **errp) >> { >> if (migration_is_idle(NULL)) { >> migration_blockers = g_slist_prepend(migration_blockers, reason); >> + error_free(reason); >> return 0; >> } >> >> + if (only_migratable) { >> + error_setg(errp, "Failed to add migration blocker: >> --only-migratable " >> + "was specified"); >> + return -EACCES; >> + } >> + >> error_setg(errp, "Cannot block a migration already in-progress"); >> return -EBUSY; >> } >> diff --git a/target-i386/kvm.c b/target-i386/kvm.c >> index 6031a1c..05c8365 100644 >> --- a/target-i386/kvm.c >> +++ b/target-i386/kvm.c >> @@ -962,7 +962,11 @@ int kvm_arch_init_vcpu(CPUState *cs) >> "State blocked by non-migratable CPU device" >> " (invtsc flag)"); >> r = migrate_add_blocker(invtsc_mig_blocker, NULL); >> - if (r < 0) { >> + if (r) { >> + if (r == -EACCES) { >> + error_report("kvm: non-migratable CPU device but" >> + " --only-migratable was specified"); >> + } >> error_report("kvm: migrate_add_blocker failed"); >> goto efail; >> } >> @@ -1009,7 +1013,6 @@ int kvm_arch_init_vcpu(CPUState *cs) >> fail: >> migrate_del_blocker(invtsc_mig_blocker); >> efail: >> - error_free(invtsc_mig_blocker); >> return r; >> } >> >