[PATCH 00/10] To make <transient/> disk sharable for qemu

This patch series has two parts; the first part is trying to support for hotplugging disks with <transient/> option for qemu, and make the disk shareable when <shareable/> disk option is set as well. The second part is trying to make shareable the disks with <transient/> disk option which is described on the domain xml. The second part is marked as Work In Progress (WIP) because the design may be modified by the first part changes. Reference: - RFC PATCH: https://listman.redhat.com/archives/libvir-list/2021-January/msg01035.html Masayoshi Mizuma (10): qemu_hotplug: Add transient disk hotplug support qemu_hotplug: make transient disk sharable virsh: Add transient flag for disk hotplug tests/qemuhotplugtest: Add qemu caps flags to the argument of DO_TEST tests/qemumonitortestutils: Add JobStatusChange to update progress of blockdev-create tests/qemuhotplugtest: Add transient disk hotplug test WIP: qemu_snapshot: Add the guest name to the transient disk path WIP: qemu_hotplug: Add asynJob to disk hotplug utilities WIP: qemu_hotplug: make transient disk sharable WIP: tests/qemuxml2argvdata: Add shareable transient disk test src/qemu/qemu_command.c | 11 + src/qemu/qemu_hotplug.c | 262 ++++++++++++++++-- src/qemu/qemu_hotplug.h | 3 + src/qemu/qemu_process.c | 23 +- src/qemu/qemu_process.h | 7 + src/qemu/qemu_snapshot.c | 12 +- src/qemu/qemu_validate.c | 21 +- tests/qemuhotplugtest.c | 199 ++++++++----- .../qemuhotplug-disk-scsi-transient.xml | 7 + .../qemuhotplug-disk-virtio-transient.xml | 7 + ...lug-transient-live+disk-scsi-transient.xml | 65 +++++ ...g-transient-live+disk-virtio-transient.xml | 65 +++++ .../qemuhotplug-transient-live.xml | 51 ++++ tests/qemumonitortestutils.c | 22 +- ...isk-transient-shareable.x86_64-latest.args | 41 +++ .../disk-transient-shareable.xml | 26 ++ tests/qemuxml2argvtest.c | 1 + tools/virsh-domain.c | 8 + 18 files changed, 738 insertions(+), 93 deletions(-) create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-disk-scsi-transient.xml create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-disk-virtio-transient.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-transient-live+disk-scsi-transient.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-transient-live+disk-virtio-transient.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-transient-live.xml create mode 100644 tests/qemuxml2argvdata/disk-transient-shareable.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/disk-transient-shareable.xml -- 2.27.0

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> Enable <transient/> disk option for qemuDomainAttachDeviceDiskLive(). The disk hotplug works for virtio or scsi bus. Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_hotplug.c | 135 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 128 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 58d2abb862..138645260f 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1025,6 +1025,111 @@ qemuDomainAttachUSBMassStorageDevice(virQEMUDriverPtr driver, return 0; } +static int +qemuHotplugDiskPrepareOneBlockdev(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virQEMUDriverConfigPtr cfg, + virDomainDiskDefPtr disk, + virStorageSourcePtr transrc, + qemuDomainAsyncJob asyncJob, + bool *created) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + g_autoptr(qemuBlockStorageSourceChainData) data = NULL; + g_autoptr(virStorageSource) terminator = NULL; + + terminator = virStorageSourceNew(); + + if (qemuDomainPrepareStorageSourceBlockdev(disk, transrc, + priv, cfg) < 0) + return -1; + + if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdevTop(transrc, + terminator, + priv->qemuCaps))) + return -1; + + transrc->capacity = disk->src->capacity; + + if (qemuBlockStorageSourceCreate(vm, transrc, disk->src, + NULL, data->srcdata[0], + asyncJob) < 0) + goto error; + + if (qemuBlockStorageSourceDetachOneBlockdev(driver, vm, + asyncJob, transrc) < 0) + goto error; + + *created = true; + + return 0; + + error: + qemuBlockStorageSourceAttachRollback(priv->mon, data->srcdata[0]); + virStorageSourceUnlink(transrc); + + return -1; +} + + +static int +qemuHotplugDiskPrepareOneDiskTransient(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainDeviceDefPtr dev, + bool *created) +{ + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + virDomainDiskDefPtr disk = dev->data.disk; + virStorageSourcePtr origsrc = disk->src; + virStorageSourcePtr transrc; + bool supportsCreate; + + transrc = virStorageSourceNew(); + transrc->type = VIR_STORAGE_TYPE_FILE; + transrc->format = VIR_STORAGE_FILE_QCOW2; + transrc->path = g_strdup_printf("%s.TRANSIENT-%s", + disk->src->path, vm->def->name); + + if (virFileExists(transrc->path)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, + _("Overlay file '%s' for transient disk '%s' already exists"), + transrc->path, disk->dst); + return -1; + } + + if (qemuDomainStorageSourceValidateDepth(transrc, 1, disk->dst) < 0) + return -1; + + if (virStorageSourceInitChainElement(transrc, disk->src, false) < 0) + return -1; + + supportsCreate = virStorageSourceSupportsCreate(transrc); + + if (supportsCreate) { + if (qemuDomainStorageFileInit(driver, vm, transrc, NULL) < 0) + return -1; + + if (virStorageSourceCreate(transrc) < 0) { + virReportSystemError(errno, _("failed to create image file '%s'"), + NULLSTR(transrc->path)); + return -1; + } + } + + if (qemuDomainStorageSourceAccessAllow(driver, vm, transrc, + false, true, true) < 0) + return -1; + + if (qemuHotplugDiskPrepareOneBlockdev(driver, vm, cfg, disk, transrc, + QEMU_ASYNC_JOB_NONE, created) < 0) + return -1; + + transrc->backingStore = origsrc; + disk->src = transrc; + + return 0; +} + static int qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriverPtr driver, @@ -1033,7 +1138,9 @@ qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriverPtr driver, { size_t i; virDomainDiskDefPtr disk = dev->data.disk; + virDomainDiskBus bus; int ret = -1; + bool transientDiskCreated = false; if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM || disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { @@ -1042,12 +1149,6 @@ qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriverPtr driver, return -1; } - if (disk->transient) { - virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", - _("transient disk hotplug isn't supported")); - return -1; - } - if (virDomainDiskTranslateSourcePool(disk) < 0) goto cleanup; @@ -1060,6 +1161,21 @@ qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriverPtr driver, if (qemuDomainDetermineDiskChain(driver, vm, disk, NULL, true) < 0) goto cleanup; + if (disk->transient) { + bus = (virDomainDiskBus) disk->bus; + + if ((bus != VIR_DOMAIN_DISK_BUS_VIRTIO) && + (bus != VIR_DOMAIN_DISK_BUS_SCSI)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("transient disk hotplug isn't supported")); + goto cleanup; + } + + if (qemuHotplugDiskPrepareOneDiskTransient(driver, vm, dev, + &transientDiskCreated) < 0) + goto cleanup; + } + for (i = 0; i < vm->def->ndisks; i++) { if (virDomainDiskDefCheckDuplicateInfo(vm->def->disks[i], disk) < 0) goto cleanup; @@ -1099,8 +1215,13 @@ qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriverPtr driver, } cleanup: - if (ret != 0) + if (ret != 0) { ignore_value(qemuRemoveSharedDevice(driver, dev, vm->def->name)); + if (transientDiskCreated) { + VIR_DEBUG("Removing transient disk %s", disk->src->path); + virStorageSourceUnlink(disk->src); + } + } return ret; } -- 2.27.0

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> Enable <shareable/> disk option for transient disk hotplug. Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_hotplug.c | 3 +++ src/qemu/qemu_validate.c | 21 +++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 138645260f..04b76db5e3 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1124,6 +1124,9 @@ qemuHotplugDiskPrepareOneDiskTransient(virQEMUDriverPtr driver, QEMU_ASYNC_JOB_NONE, created) < 0) return -1; + if (origsrc->shared) + origsrc->readonly = true; + transrc->backingStore = origsrc; disk->src = transrc; diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 6043f974ce..5426e7a784 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -2907,6 +2907,23 @@ qemuValidateDomainDeviceDefDiskTransient(const virDomainDiskDef *disk, } +static bool +qemuValidateDomainDeviceDefDiskShareable(const virDomainDiskDef *disk) +{ + virDomainDiskBus bus = (virDomainDiskBus) disk->bus; + + if (!disk->src->readonly && !disk->transient && + !qemuBlockStorageSourceSupportsConcurrentAccess(disk->src)) + return false; + else if (disk->transient && + (bus != VIR_DOMAIN_DISK_BUS_VIRTIO) && + (bus != VIR_DOMAIN_DISK_BUS_SCSI)) + return false; + else + return true; +} + + int qemuValidateDomainDeviceDefDisk(const virDomainDiskDef *disk, const virDomainDef *def, @@ -2927,8 +2944,8 @@ qemuValidateDomainDeviceDefDisk(const virDomainDiskDef *disk, if (qemuValidateDomainDeviceDefDiskTransient(disk, qemuCaps) < 0) return -1; - if (disk->src->shared && !disk->src->readonly && - !qemuBlockStorageSourceSupportsConcurrentAccess(disk->src)) { + if (disk->src->shared && + !qemuValidateDomainDeviceDefDiskShareable(disk)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("shared access for disk '%s' requires use of " "supported storage format"), disk->dst); -- 2.27.0

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> Enable <transient/> disk option for the xml to hotplug disks. And <shareable/> disk option is also available for the disk to share the disk with multiple guests. For example: # cat disk.xml <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='/var/lib/libvirt/images/disk.qcow2'/> <target dev='vdf' bus='virtio'/> <shareable/> <transient/> </disk> # # virsh attach-device Guest1 disk.xml Device attached successfully # # virsh attach-device Guest2 disk.xml Device attached successfully # Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- tools/virsh-domain.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index a778421b66..7246260673 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -486,6 +486,10 @@ static const vshCmdOptDef opts_attach_disk[] = { .type = VSH_OT_STRING, .help = N_("host socket for source of disk device") }, + {.name = "transient", + .type = VSH_OT_BOOL, + .help = N_("mark the disk as transient") + }, VIRSH_COMMON_OPT_DOMAIN_PERSISTENT, VIRSH_COMMON_OPT_DOMAIN_CONFIG, VIRSH_COMMON_OPT_DOMAIN_LIVE, @@ -593,6 +597,7 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd) bool live = vshCommandOptBool(cmd, "live"); bool persistent = vshCommandOptBool(cmd, "persistent"); bool multifunction = vshCommandOptBool(cmd, "multifunction"); + bool transient = vshCommandOptBool(cmd, "transient"); VSH_EXCLUSIVE_OPTIONS_VAR(persistent, current); @@ -739,6 +744,9 @@ cmdAttachDisk(vshControl *ctl, const vshCmd *cmd) cmdAttachDiskFormatAddress(ctl, &diskChildBuf, straddr, target, multifunction) < 0) return false; + if (transient) + virBufferAddLit(&diskChildBuf, "<transient/>\n"); + virXMLFormatElement(&buf, "disk", &diskAttrBuf, &diskChildBuf); xml = virBufferContentAndReset(&buf); -- 2.27.0

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> Add additional qemu cap flags to the argument of DO_TEST*() so that we can test with specific qemu caps, for example, QEMU_CAPS_BLOCKDEV. Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- tests/qemuhotplugtest.c | 133 +++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 62 deletions(-) diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index df5c9c9059..6750b33d51 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -31,6 +31,7 @@ #include "virstring.h" #include "virthread.h" #include "virfile.h" +#include "qemu/qemu_block.h" #define VIR_FROM_THIS VIR_FROM_NONE @@ -53,12 +54,14 @@ struct qemuHotplugTestData { bool keep; virDomainObjPtr vm; bool deviceDeletedEvent; + virQEMUCapsFlags flags; }; static int qemuHotplugCreateObjects(virDomainXMLOptionPtr xmlopt, virDomainObjPtr *vm, - const char *domxml) + const char *domxml, + virQEMUCapsFlags additionalFlags) { qemuDomainObjPrivatePtr priv = NULL; const unsigned int parseFlags = 0; @@ -92,6 +95,9 @@ qemuHotplugCreateObjects(virDomainXMLOptionPtr xmlopt, virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_DEVICE_USB_KBD); virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_NETDEV_VHOST_VDPA); + if (additionalFlags) + virQEMUCapsSet(priv->qemuCaps, additionalFlags); + if (qemuTestCapsCacheInsert(driver.qemuCapsCache, priv->qemuCaps) < 0) return -1; @@ -253,6 +259,7 @@ testQemuHotplug(const void *data) g_autoptr(virCaps) caps = NULL; qemuMonitorTestPtr test_mon = NULL; qemuDomainObjPrivatePtr priv = NULL; + virQEMUCapsFlags additionalFlags = test->flags; domain_filename = g_strdup_printf("%s/qemuhotplugtestdomains/qemuhotplug-%s.xml", abs_srcdir, test->domain_filename); @@ -280,7 +287,8 @@ testQemuHotplug(const void *data) goto cleanup; } } else { - if (qemuHotplugCreateObjects(driver.xmlopt, &vm, domain_xml) < 0) + if (qemuHotplugCreateObjects(driver.xmlopt, &vm, + domain_xml, additionalFlags) < 0) goto cleanup; } @@ -431,7 +439,7 @@ testQemuHotplugCpuPrepare(const char *test, if (virTestLoadFile(data->file_xml_dom, &data->xml_dom) < 0) goto error; - if (qemuHotplugCreateObjects(driver.xmlopt, &data->vm, data->xml_dom) < 0) + if (qemuHotplugCreateObjects(driver.xmlopt, &data->vm, data->xml_dom, 0) < 0) goto error; if (!(caps = virQEMUDriverGetCapabilities(&driver, false))) @@ -646,7 +654,7 @@ mymain(void) } -#define DO_TEST(file, ACTION, dev, fail_, keep_, ...) \ +#define DO_TEST(file, ACTION, dev, fail_, keep_, flags_, ...) \ do { \ const char *my_mon[] = { __VA_ARGS__, NULL}; \ const char *name = file " " #ACTION " " dev; \ @@ -656,19 +664,19 @@ mymain(void) data.fail = fail_; \ data.mon = my_mon; \ data.keep = keep_; \ + data.flags = flags_; \ if (virTestRun(name, testQemuHotplug, &data) < 0) \ ret = -1; \ } while (0) -#define DO_TEST_ATTACH(file, dev, fail, keep, ...) \ - DO_TEST(file, ATTACH, dev, fail, keep, __VA_ARGS__) - -#define DO_TEST_DETACH(file, dev, fail, keep, ...) \ - DO_TEST(file, DETACH, dev, fail, keep, __VA_ARGS__) +#define DO_TEST_ATTACH(file, dev, fail, keep, flags, ...) \ + DO_TEST(file, ATTACH, dev, fail, keep, flags, __VA_ARGS__) -#define DO_TEST_UPDATE(file, dev, fail, keep, ...) \ - DO_TEST(file, UPDATE, dev, fail, keep, __VA_ARGS__) +#define DO_TEST_DETACH(file, dev, fail, keep, flags, ...) \ + DO_TEST(file, DETACH, dev, fail, keep, flags, __VA_ARGS__) +#define DO_TEST_UPDATE(file, dev, fail, keep, flags, ...) \ + DO_TEST(file, UPDATE, dev, fail, keep, flags, __VA_ARGS__) #define QMP_OK "{\"return\": {}}" #define HMP(msg) "{\"return\": \"" msg "\"}" @@ -687,54 +695,55 @@ mymain(void) "}\r\n" cfg->spiceTLS = true; - DO_TEST_UPDATE("graphics-spice", "graphics-spice-nochange", false, false, NULL); - DO_TEST_UPDATE("graphics-spice-timeout", "graphics-spice-timeout-nochange", false, false, + DO_TEST_UPDATE("graphics-spice", "graphics-spice-nochange", false, false, 0, NULL); + DO_TEST_UPDATE("graphics-spice-timeout", "graphics-spice-timeout-nochange", false, false, 0, "set_password", QMP_OK, "expire_password", QMP_OK); - DO_TEST_UPDATE("graphics-spice-timeout", "graphics-spice-timeout-password", false, false, + DO_TEST_UPDATE("graphics-spice-timeout", "graphics-spice-timeout-password", false, false, 0, "set_password", QMP_OK, "expire_password", QMP_OK); - DO_TEST_UPDATE("graphics-spice", "graphics-spice-listen", true, false, NULL); - DO_TEST_UPDATE("graphics-spice-listen-network", "graphics-spice-listen-network-password", false, false, + DO_TEST_UPDATE("graphics-spice", "graphics-spice-listen", true, false, 0, NULL); + DO_TEST_UPDATE("graphics-spice-listen-network", "graphics-spice-listen-network-password", + false, false, 0, "set_password", QMP_OK, "expire_password", QMP_OK); cfg->spiceTLS = false; /* Strange huh? Currently, only graphics can be updated :-P */ - DO_TEST_UPDATE("disk-cdrom", "disk-cdrom-nochange", true, false, NULL); + DO_TEST_UPDATE("disk-cdrom", "disk-cdrom-nochange", true, false, 0, NULL); - DO_TEST_ATTACH("console-compat-2-live", "console-virtio", false, true, + DO_TEST_ATTACH("console-compat-2-live", "console-virtio", false, true, 0, "chardev-add", "{\"return\": {\"pty\": \"/dev/pts/26\"}}", "device_add", QMP_OK); - DO_TEST_DETACH("console-compat-2-live", "console-virtio", false, false, + DO_TEST_DETACH("console-compat-2-live", "console-virtio", false, false, 0, "device_del", QMP_DEVICE_DELETED("console1") QMP_OK, "chardev-remove", QMP_OK); - DO_TEST_ATTACH("base-live", "disk-virtio", false, true, + DO_TEST_ATTACH("base-live", "disk-virtio", false, true, 0, "human-monitor-command", HMP("OK\\r\\n"), "device_add", QMP_OK); - DO_TEST_DETACH("base-live", "disk-virtio", true, true, + DO_TEST_DETACH("base-live", "disk-virtio", true, true, 0, "device_del", QMP_OK); - DO_TEST_DETACH("base-live", "disk-virtio", false, false, + DO_TEST_DETACH("base-live", "disk-virtio", false, false, 0, "device_del", QMP_DEVICE_DELETED("virtio-disk4") QMP_OK, "human-monitor-command", HMP("")); - DO_TEST_ATTACH("base-live", "disk-usb", false, true, + DO_TEST_ATTACH("base-live", "disk-usb", false, true, 0, "human-monitor-command", HMP("OK\\r\\n"), "device_add", QMP_OK); - DO_TEST_DETACH("base-live", "disk-usb", true, true, + DO_TEST_DETACH("base-live", "disk-usb", true, true, 0, "device_del", QMP_OK); - DO_TEST_DETACH("base-live", "disk-usb", false, false, + DO_TEST_DETACH("base-live", "disk-usb", false, false, 0, "device_del", QMP_DEVICE_DELETED("usb-disk16") QMP_OK, "human-monitor-command", HMP("")); - DO_TEST_ATTACH("base-live", "disk-scsi", false, true, + DO_TEST_ATTACH("base-live", "disk-scsi", false, true, 0, "human-monitor-command", HMP("OK\\r\\n"), "device_add", QMP_OK); - DO_TEST_DETACH("base-live", "disk-scsi", true, true, + DO_TEST_DETACH("base-live", "disk-scsi", true, true, 0, "device_del", QMP_OK); - DO_TEST_DETACH("base-live", "disk-scsi", false, false, + DO_TEST_DETACH("base-live", "disk-scsi", false, false, 0, "device_del", QMP_DEVICE_DELETED("scsi0-0-0-5") QMP_OK, "human-monitor-command", HMP("")); - DO_TEST_ATTACH("base-without-scsi-controller-live", "disk-scsi-2", false, true, + DO_TEST_ATTACH("base-without-scsi-controller-live", "disk-scsi-2", false, true, 0, /* Four controllers added */ "device_add", QMP_OK, "device_add", QMP_OK, @@ -743,96 +752,96 @@ mymain(void) "human-monitor-command", HMP("OK\\r\\n"), /* Disk added */ "device_add", QMP_OK); - DO_TEST_DETACH("base-with-scsi-controller-live", "disk-scsi-2", true, true, + DO_TEST_DETACH("base-with-scsi-controller-live", "disk-scsi-2", true, true, 0, "device_del", QMP_OK); - DO_TEST_DETACH("base-with-scsi-controller-live", "disk-scsi-2", false, false, + DO_TEST_DETACH("base-with-scsi-controller-live", "disk-scsi-2", false, false, 0, "device_del", QMP_DEVICE_DELETED("scsi3-0-5-6") QMP_OK, "human-monitor-command", HMP("")); - DO_TEST_ATTACH("base-live", "disk-scsi-multipath", false, true, + DO_TEST_ATTACH("base-live", "disk-scsi-multipath", false, true, 0, "object-add", QMP_OK, "human-monitor-command", HMP("OK\\r\\n"), "device_add", QMP_OK); - DO_TEST_DETACH("base-live", "disk-scsi-multipath", true, true, + DO_TEST_DETACH("base-live", "disk-scsi-multipath", true, true, 0, "device_del", QMP_OK); - DO_TEST_DETACH("base-live", "disk-scsi-multipath", false, false, + DO_TEST_DETACH("base-live", "disk-scsi-multipath", false, false, 0, "device_del", QMP_DEVICE_DELETED("scsi0-0-0-0") QMP_OK, "human-monitor-command", HMP(""), "object-del", QMP_OK); - DO_TEST_ATTACH("base-live", "qemu-agent", false, true, + DO_TEST_ATTACH("base-live", "qemu-agent", false, true, 0, "chardev-add", QMP_OK, "device_add", QMP_OK); - DO_TEST_DETACH("base-live", "qemu-agent-detach", false, false, + DO_TEST_DETACH("base-live", "qemu-agent-detach", false, false, 0, "device_del", QMP_DEVICE_DELETED("channel0") QMP_OK, "chardev-remove", QMP_OK); - DO_TEST_ATTACH("base-ccw-live", "ccw-virtio", false, true, + DO_TEST_ATTACH("base-ccw-live", "ccw-virtio", false, true, 0, "human-monitor-command", HMP("OK\\r\\n"), "device_add", QMP_OK); - DO_TEST_DETACH("base-ccw-live", "ccw-virtio", false, false, + DO_TEST_DETACH("base-ccw-live", "ccw-virtio", false, false, 0, "device_del", QMP_DEVICE_DELETED("virtio-disk4") QMP_OK, "human-monitor-command", HMP("")); - DO_TEST_ATTACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2", false, true, + DO_TEST_ATTACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2", false, true, 0, "human-monitor-command", HMP("OK\\r\\n"), "device_add", QMP_OK); - DO_TEST_DETACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2", false, false, + DO_TEST_DETACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2", false, false, 0, "device_del", QMP_DEVICE_DELETED("virtio-disk0") QMP_OK, "human-monitor-command", HMP("")); - DO_TEST_ATTACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2-explicit", false, true, + DO_TEST_ATTACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2-explicit", false, true, 0, "human-monitor-command", HMP("OK\\r\\n"), "device_add", QMP_OK); - DO_TEST_DETACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2-explicit", false, false, + DO_TEST_DETACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2-explicit", false, false, 0, "device_del", QMP_DEVICE_DELETED("virtio-disk0") QMP_OK, "human-monitor-command", HMP("")); /* Attach a second device, then detach the first one. Then attach the first one again. */ - DO_TEST_ATTACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2-explicit", false, true, + DO_TEST_ATTACH("base-ccw-live-with-ccw-virtio", "ccw-virtio-2-explicit", false, true, 0, "human-monitor-command", HMP("OK\\r\\n"), "device_add", QMP_OK); - DO_TEST_DETACH("base-ccw-live-with-2-ccw-virtio", "ccw-virtio-1-explicit", false, true, + DO_TEST_DETACH("base-ccw-live-with-2-ccw-virtio", "ccw-virtio-1-explicit", false, true, 0, "device_del", QMP_DEVICE_DELETED("virtio-disk4") QMP_OK, "human-monitor-command", HMP("")); - DO_TEST_ATTACH("base-ccw-live-with-2-ccw-virtio", "ccw-virtio-1-reverse", false, false, + DO_TEST_ATTACH("base-ccw-live-with-2-ccw-virtio", "ccw-virtio-1-reverse", false, false, 0, "human-monitor-command", HMP("OK\\r\\n"), "device_add", QMP_OK); - DO_TEST_ATTACH("base-live", "ivshmem-plain", false, true, + DO_TEST_ATTACH("base-live", "ivshmem-plain", false, true, 0, "object-add", QMP_OK, "device_add", QMP_OK); - DO_TEST_ATTACH("base-live", "ivshmem-doorbell", false, true, + DO_TEST_ATTACH("base-live", "ivshmem-doorbell", false, true, 0, "chardev-add", QMP_OK, "device_add", QMP_OK); - DO_TEST_DETACH("base-live+ivshmem-plain", "ivshmem-doorbell-detach", false, true, + DO_TEST_DETACH("base-live+ivshmem-plain", "ivshmem-doorbell-detach", false, true, 0, "device_del", QMP_DEVICE_DELETED("shmem1") QMP_OK, "chardev-remove", QMP_OK); - DO_TEST_DETACH("base-live", "ivshmem-plain-detach", false, false, + DO_TEST_DETACH("base-live", "ivshmem-plain-detach", false, false, 0, "device_del", QMP_DEVICE_DELETED("shmem0") QMP_OK, "object-del", QMP_OK); DO_TEST_ATTACH("base-live+disk-scsi-wwn", - "disk-scsi-duplicate-wwn", false, false, + "disk-scsi-duplicate-wwn", false, false, 0, "human-monitor-command", HMP("OK\\r\\n"), "device_add", QMP_OK); - DO_TEST_ATTACH("base-live", "hostdev-pci", false, true, + DO_TEST_ATTACH("base-live", "hostdev-pci", false, true, 0, "device_add", QMP_OK); - DO_TEST_DETACH("base-live", "hostdev-pci", false, false, + DO_TEST_DETACH("base-live", "hostdev-pci", false, false, 0, "device_del", QMP_DEVICE_DELETED("hostdev0") QMP_OK); - DO_TEST_ATTACH("pseries-base-live", "hostdev-pci", false, true, + DO_TEST_ATTACH("pseries-base-live", "hostdev-pci", false, true, 0, "device_add", QMP_OK); - DO_TEST_DETACH("pseries-base-live", "hostdev-pci", false, false, + DO_TEST_DETACH("pseries-base-live", "hostdev-pci", false, false, 0, "device_del", QMP_DEVICE_DELETED("hostdev0") QMP_OK); - DO_TEST_ATTACH("base-live", "interface-vdpa", false, true, + DO_TEST_ATTACH("base-live", "interface-vdpa", false, true, 0, "add-fd", "{ \"return\": { \"fdset-id\": 1, \"fd\": 95 }}", "netdev_add", QMP_OK, "device_add", QMP_OK); - DO_TEST_DETACH("base-live", "interface-vdpa", false, false, + DO_TEST_DETACH("base-live", "interface-vdpa", false, false, 0, "device_del", QMP_DEVICE_DELETED("net0") QMP_OK, "netdev_del", QMP_OK, "query-fdsets", @@ -840,22 +849,22 @@ mymain(void) "remove-fd", QMP_OK ); - DO_TEST_ATTACH("base-live", "watchdog", false, true, + DO_TEST_ATTACH("base-live", "watchdog", false, true, 0, "watchdog-set-action", QMP_OK, "device_add", QMP_OK); - DO_TEST_DETACH("base-live", "watchdog-full", false, false, + DO_TEST_DETACH("base-live", "watchdog-full", false, false, 0, "device_del", QMP_DEVICE_DELETED("watchdog0") QMP_OK); - DO_TEST_ATTACH("base-live", "watchdog-user-alias", false, true, + DO_TEST_ATTACH("base-live", "watchdog-user-alias", false, true, 0, "watchdog-set-action", QMP_OK, "device_add", QMP_OK); - DO_TEST_DETACH("base-live", "watchdog-user-alias-full", false, false, + DO_TEST_DETACH("base-live", "watchdog-user-alias-full", false, false, 0, "device_del", QMP_DEVICE_DELETED("ua-UserWatchdog") QMP_OK); - DO_TEST_ATTACH("base-live", "guestfwd", false, true, + DO_TEST_ATTACH("base-live", "guestfwd", false, true, 0, "chardev-add", QMP_OK, "netdev_add", QMP_OK); - DO_TEST_DETACH("base-live", "guestfwd", false, false, + DO_TEST_DETACH("base-live", "guestfwd", false, false, 0, "netdev_del", QMP_OK); #define DO_TEST_CPU_GROUP(prefix, vcpus, modernhp, expectfail) \ -- 2.27.0

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> Add qemuProcessHandleJobStatusChange to .jobStatusChange handler to update the progress of blockdev-create. Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_process.c | 2 +- src/qemu/qemu_process.h | 7 +++++++ tests/qemumonitortestutils.c | 22 +++++++++++++++++++++- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index fedd1f56b1..4ba634dfc5 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -992,7 +992,7 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon G_GNUC_UNUSED, } -static int +int qemuProcessHandleJobStatusChange(qemuMonitorPtr mon G_GNUC_UNUSED, virDomainObjPtr vm, const char *jobname, diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h index f4feeaa68f..579564a905 100644 --- a/src/qemu/qemu_process.h +++ b/src/qemu/qemu_process.h @@ -244,3 +244,10 @@ void qemuProcessQMPFree(qemuProcessQMPPtr proc); G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuProcessQMP, qemuProcessQMPFree); int qemuProcessQMPStart(qemuProcessQMPPtr proc); + +int +qemuProcessHandleJobStatusChange(qemuMonitorPtr mon, + virDomainObjPtr vm, + const char *jobname, + int status, + void *opaque); diff --git a/tests/qemumonitortestutils.c b/tests/qemumonitortestutils.c index 227b78d527..98fc5a9e9b 100644 --- a/tests/qemumonitortestutils.c +++ b/tests/qemumonitortestutils.c @@ -37,6 +37,7 @@ #include "virerror.h" #include "virstring.h" #include "vireventthread.h" +#include "qemu/qemu_process.h" #define VIR_FROM_THIS VIR_FROM_NONE @@ -575,6 +576,18 @@ qemuMonitorTestProcessCommandDefaultValidate(qemuMonitorTestPtr test, return 0; } +#define QEMU_BLOCKDEV_CREATE_CONCLUDED(id) \ + "{"\ + " \"timestamp\": {"\ + " \"seconds\": 1616361602,"\ + " \"microseconds\": 893848"\ + " },"\ + " \"event\": \"JOB_STATUS_CHANGE\","\ + " \"data\": {"\ + " \"status\": \"concluded\","\ + " \"id\": \"" id "\""\ + " }"\ + "}" static int qemuMonitorTestProcessCommandDefault(qemuMonitorTestPtr test, @@ -585,6 +598,7 @@ qemuMonitorTestProcessCommandDefault(qemuMonitorTestPtr test, g_autoptr(virJSONValue) val = NULL; virJSONValuePtr cmdargs = NULL; const char *cmdname; + int ret; if (!(val = virJSONValueFromString(cmdstr))) return -1; @@ -602,7 +616,12 @@ qemuMonitorTestProcessCommandDefault(qemuMonitorTestPtr test, qemuMonitorTestErrorInvalidCommand(data->command_name, cmdname); return -1; } else { - return qemuMonitorTestAddResponse(test, data->response); + ret = qemuMonitorTestAddResponse(test, data->response); + if (data->command_name && STREQ(data->command_name, "blockdev-create")) { + qemuMonitorTestAddResponse(test, + QEMU_BLOCKDEV_CREATE_CONCLUDED("create-libvirt-1-format")); + } + return ret; } } @@ -995,6 +1014,7 @@ qemuMonitorTestErrorNotify(qemuMonitorPtr mon G_GNUC_UNUSED, static qemuMonitorCallbacks qemuMonitorTestCallbacks = { .eofNotify = qemuMonitorTestEOFNotify, .errorNotify = qemuMonitorTestErrorNotify, + .jobStatusChange = qemuProcessHandleJobStatusChange, .domainDeviceDeleted = qemuProcessHandleDeviceDeleted, }; -- 2.27.0

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> Add disk hotplug test for <transient/> disk option. The tests check virtio and scsi bus disk hotplug. Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- tests/qemuhotplugtest.c | 66 +++++++++++++++++++ .../qemuhotplug-disk-scsi-transient.xml | 7 ++ .../qemuhotplug-disk-virtio-transient.xml | 7 ++ ...lug-transient-live+disk-scsi-transient.xml | 65 ++++++++++++++++++ ...g-transient-live+disk-virtio-transient.xml | 65 ++++++++++++++++++ .../qemuhotplug-transient-live.xml | 51 ++++++++++++++ 6 files changed, 261 insertions(+) create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-disk-scsi-transient.xml create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-disk-virtio-transient.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-transient-live+disk-scsi-transient.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-transient-live+disk-virtio-transient.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-transient-live.xml diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index 6750b33d51..0668a11da5 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -694,6 +694,18 @@ mymain(void) " }" \ "}\r\n" + +#define QMP_JOB_CONCLUDED(id) \ + "{"\ + " \"return\": [{"\ + " \"current-progress\": 1,"\ + " \"status\": \"concluded\","\ + " \"total-progress\": 1,"\ + " \"type\": \"create\","\ + " \"id\": \"" id "\""\ + " }]"\ + "}" + cfg->spiceTLS = true; DO_TEST_UPDATE("graphics-spice", "graphics-spice-nochange", false, false, 0, NULL); DO_TEST_UPDATE("graphics-spice-timeout", "graphics-spice-timeout-nochange", false, false, 0, @@ -867,6 +879,60 @@ mymain(void) DO_TEST_DETACH("base-live", "guestfwd", false, false, 0, "netdev_del", QMP_OK); + DO_TEST_ATTACH("transient-live", "disk-virtio-transient", false, true, + QEMU_CAPS_BLOCKDEV, + "blockdev-add", QMP_OK, + "blockdev-create", QMP_OK, + "query-jobs", QMP_JOB_CONCLUDED("create-libvirt-1-format"), + "job-dismiss", QMP_OK, + "blockdev-add", QMP_OK, + "blockdev-del", QMP_OK, + "blockdev-del", QMP_OK, + "blockdev-add", QMP_OK, + "blockdev-add", QMP_OK, + "blockdev-add", QMP_OK, + "blockdev-add", QMP_OK, + "device_add", QMP_OK); + + DO_TEST_DETACH("transient-live", "disk-virtio-transient", true, true, + QEMU_CAPS_BLOCKDEV, + "device_del", QMP_OK); + + DO_TEST_DETACH("transient-live", "disk-virtio-transient", false, false, + QEMU_CAPS_BLOCKDEV, + "device_del", QMP_DEVICE_DELETED("virtio-disk4") QMP_OK, + "blockdev-del", QMP_OK, + "blockdev-del", QMP_OK, + "blockdev-del", QMP_OK, + "blockdev-del", QMP_OK); + + DO_TEST_ATTACH("transient-live", "disk-scsi-transient", false, true, + QEMU_CAPS_BLOCKDEV, + "blockdev-add", QMP_OK, + "blockdev-create", QMP_OK, + "query-jobs", QMP_JOB_CONCLUDED("create-libvirt-1-format"), + "job-dismiss", QMP_OK, + "blockdev-add", QMP_OK, + "blockdev-del", QMP_OK, + "blockdev-del", QMP_OK, + "blockdev-add", QMP_OK, + "blockdev-add", QMP_OK, + "blockdev-add", QMP_OK, + "blockdev-add", QMP_OK, + "device_add", QMP_OK); + + DO_TEST_DETACH("transient-live", "disk-scsi-transient", true, true, + QEMU_CAPS_BLOCKDEV, + "device_del", QMP_OK); + + DO_TEST_DETACH("transient-live", "disk-scsi-transient", false, false, + QEMU_CAPS_BLOCKDEV, + "device_del", QMP_DEVICE_DELETED("scsi0-0-0-5") QMP_OK, + "blockdev-del", QMP_OK, + "blockdev-del", QMP_OK, + "blockdev-del", QMP_OK, + "blockdev-del", QMP_OK); + #define DO_TEST_CPU_GROUP(prefix, vcpus, modernhp, expectfail) \ do { \ cpudata.test = prefix; \ diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-disk-scsi-transient.xml b/tests/qemuhotplugtestdevices/qemuhotplug-disk-scsi-transient.xml new file mode 100644 index 0000000000..5ef2a63016 --- /dev/null +++ b/tests/qemuhotplugtestdevices/qemuhotplug-disk-scsi-transient.xml @@ -0,0 +1,7 @@ +<disk type='file' device='disk'> + <driver name='qemu' type='raw' cache='none'/> + <source file='/dev/null'/> + <target dev='sdf' bus='scsi'/> + <shareable/> + <transient/> +</disk> diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-disk-virtio-transient.xml b/tests/qemuhotplugtestdevices/qemuhotplug-disk-virtio-transient.xml new file mode 100644 index 0000000000..76be133d84 --- /dev/null +++ b/tests/qemuhotplugtestdevices/qemuhotplug-disk-virtio-transient.xml @@ -0,0 +1,7 @@ +<disk type='file' device='disk'> + <driver name='qemu' type='qcow2' cache='none'/> + <source file='/dev/null'/> + <target dev='vde' bus='virtio'/> + <shareable/> + <transient/> +</disk> diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-transient-live+disk-scsi-transient.xml b/tests/qemuhotplugtestdomains/qemuhotplug-transient-live+disk-scsi-transient.xml new file mode 100644 index 0000000000..a007dc992e --- /dev/null +++ b/tests/qemuhotplugtestdomains/qemuhotplug-transient-live+disk-scsi-transient.xml @@ -0,0 +1,65 @@ +<domain type='kvm' id='7'> + <name>hotplug</name> + <uuid>d091ea82-29e6-2e34-3005-f02617b36e87</uuid> + <memory unit='KiB'>4194304</memory> + <currentMemory unit='KiB'>4194304</currentMemory> + <vcpu placement='static'>4</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2' cache='none'/> + <source file='/dev/null.TRANSIENT-hotplug' index='2'/> + <backingStore type='file' index='3'> + <format type='raw'/> + <source file='/dev/null'/> + <backingStore/> + </backingStore> + <target dev='sdf' bus='scsi'/> + <shareable/> + <transient/> + <alias name='scsi0-0-0-5'/> + <address type='drive' controller='0' bus='0' target='0' unit='5'/> + </disk> + <controller type='usb' index='0'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <alias name='ide'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='scsi' index='0' model='virtio-scsi'> + <alias name='scsi0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <alias name='pci'/> + </controller> + <controller type='virtio-serial' index='0'> + <alias name='virtio-serial0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </controller> + <input type='mouse' bus='ps2'> + <alias name='input0'/> + </input> + <input type='keyboard' bus='ps2'> + <alias name='input1'/> + </input> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> + <seclabel type='none' model='none'/> +</domain> diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-transient-live+disk-virtio-transient.xml b/tests/qemuhotplugtestdomains/qemuhotplug-transient-live+disk-virtio-transient.xml new file mode 100644 index 0000000000..221a293878 --- /dev/null +++ b/tests/qemuhotplugtestdomains/qemuhotplug-transient-live+disk-virtio-transient.xml @@ -0,0 +1,65 @@ +<domain type='kvm' id='7'> + <name>hotplug</name> + <uuid>d091ea82-29e6-2e34-3005-f02617b36e87</uuid> + <memory unit='KiB'>4194304</memory> + <currentMemory unit='KiB'>4194304</currentMemory> + <vcpu placement='static'>4</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2' cache='none'/> + <source file='/dev/null.TRANSIENT-hotplug' index='2'/> + <backingStore type='file' index='3'> + <format type='qcow2'/> + <source file='/dev/null'/> + <backingStore/> + </backingStore> + <target dev='vde' bus='virtio'/> + <shareable/> + <transient/> + <alias name='virtio-disk4'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </disk> + <controller type='usb' index='0'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <alias name='ide'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='scsi' index='0' model='virtio-scsi'> + <alias name='scsi0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <alias name='pci'/> + </controller> + <controller type='virtio-serial' index='0'> + <alias name='virtio-serial0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </controller> + <input type='mouse' bus='ps2'> + <alias name='input0'/> + </input> + <input type='keyboard' bus='ps2'> + <alias name='input1'/> + </input> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> + <seclabel type='none' model='none'/> +</domain> diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-transient-live.xml b/tests/qemuhotplugtestdomains/qemuhotplug-transient-live.xml new file mode 100644 index 0000000000..a02bc39663 --- /dev/null +++ b/tests/qemuhotplugtestdomains/qemuhotplug-transient-live.xml @@ -0,0 +1,51 @@ +<domain type='kvm' id='7'> + <name>hotplug</name> + <uuid>d091ea82-29e6-2e34-3005-f02617b36e87</uuid> + <memory unit='KiB'>4194304</memory> + <currentMemory unit='KiB'>4194304</currentMemory> + <vcpu placement='static'>4</vcpu> + <os> + <type arch='x86_64' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <features> + <acpi/> + <apic/> + <pae/> + </features> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-x86_64</emulator> + <controller type='usb' index='0'> + <alias name='usb'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <alias name='ide'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='scsi' index='0' model='virtio-scsi'> + <alias name='scsi0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </controller> + <controller type='pci' index='0' model='pci-root'> + <alias name='pci'/> + </controller> + <controller type='virtio-serial' index='0'> + <alias name='virtio-serial0'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </controller> + <input type='mouse' bus='ps2'> + <alias name='input0'/> + </input> + <input type='keyboard' bus='ps2'> + <alias name='input1'/> + </input> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> + <seclabel type='none' model='none'/> +</domain> -- 2.27.0

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> Add the guest name to the transient disk path name to match the path of transient disks for hotplugging. Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_snapshot.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index 93b74b035a..a5cc0d47f2 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -1195,7 +1195,8 @@ qemuSnapshotDiskPrepareDisksTransient(virDomainObjPtr vm, snapdisk->src = virStorageSourceNew(); snapdisk->src->type = VIR_STORAGE_TYPE_FILE; snapdisk->src->format = VIR_STORAGE_FILE_QCOW2; - snapdisk->src->path = g_strdup_printf("%s.TRANSIENT", domdisk->src->path); + snapdisk->src->path = g_strdup_printf("%s.TRANSIENT-%s", + domdisk->src->path, vm->def->name); if (virFileExists(snapdisk->src->path)) { virReportError(VIR_ERR_OPERATION_UNSUPPORTED, -- 2.27.0

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> Add asynJob argument to some disk hotplug utilities so that they can work before CPUs start. Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_hotplug.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 04b76db5e3..366ebeaa7c 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -693,7 +693,8 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver, static int qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver, virDomainObjPtr vm, - virDomainDiskDefPtr disk) + virDomainDiskDefPtr disk, + qemuDomainAsyncJob asyncJob) { g_autoptr(qemuBlockStorageSourceChainData) data = NULL; int ret = -1; @@ -742,7 +743,8 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver, if (qemuHotplugAttachManagedPR(driver, vm, disk->src, QEMU_ASYNC_JOB_NONE) < 0) goto cleanup; - qemuDomainObjEnterMonitor(driver, vm); + if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) + goto cleanup; if (qemuBlockStorageSourceChainAttach(priv->mon, data) < 0) goto exit_monitor; @@ -813,7 +815,8 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver, static int qemuDomainAttachVirtioDiskDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, - virDomainDiskDefPtr disk) + virDomainDiskDefPtr disk, + qemuDomainAsyncJob asyncJob) { virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_DISK, { .disk = disk } }; bool releaseaddr = false; @@ -822,7 +825,7 @@ qemuDomainAttachVirtioDiskDevice(virQEMUDriverPtr driver, if (qemuDomainEnsureVirtioAddress(&releaseaddr, vm, &dev, disk->dst) < 0) return -1; - if ((rv = qemuDomainAttachDiskGeneric(driver, vm, disk)) < 0) { + if ((rv = qemuDomainAttachDiskGeneric(driver, vm, disk, asyncJob)) < 0) { if (rv == -1 && releaseaddr) qemuDomainReleaseDeviceAddress(vm, &disk->info); @@ -970,7 +973,8 @@ qemuDomainFindOrCreateSCSIDiskController(virQEMUDriverPtr driver, static int qemuDomainAttachSCSIDisk(virQEMUDriverPtr driver, virDomainObjPtr vm, - virDomainDiskDefPtr disk) + virDomainDiskDefPtr disk, + qemuDomainAsyncJob asyncJob) { size_t i; @@ -1000,7 +1004,7 @@ qemuDomainAttachSCSIDisk(virQEMUDriverPtr driver, return -1; } - if (qemuDomainAttachDiskGeneric(driver, vm, disk) < 0) + if (qemuDomainAttachDiskGeneric(driver, vm, disk, asyncJob) < 0) return -1; return 0; @@ -1017,7 +1021,7 @@ qemuDomainAttachUSBMassStorageDevice(virQEMUDriverPtr driver, if (virDomainUSBAddressEnsure(priv->usbaddrs, &disk->info) < 0) return -1; - if (qemuDomainAttachDiskGeneric(driver, vm, disk) < 0) { + if (qemuDomainAttachDiskGeneric(driver, vm, disk, QEMU_ASYNC_JOB_NONE) < 0) { virDomainUSBAddressRelease(priv->usbaddrs, &disk->info); return -1; } @@ -1076,6 +1080,7 @@ static int qemuHotplugDiskPrepareOneDiskTransient(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainDeviceDefPtr dev, + qemuDomainAsyncJob asyncJob, bool *created) { g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); @@ -1121,7 +1126,7 @@ qemuHotplugDiskPrepareOneDiskTransient(virQEMUDriverPtr driver, return -1; if (qemuHotplugDiskPrepareOneBlockdev(driver, vm, cfg, disk, transrc, - QEMU_ASYNC_JOB_NONE, created) < 0) + asyncJob, created) < 0) return -1; if (origsrc->shared) @@ -1137,7 +1142,8 @@ qemuHotplugDiskPrepareOneDiskTransient(virQEMUDriverPtr driver, static int qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriverPtr driver, virDomainObjPtr vm, - virDomainDeviceDefPtr dev) + virDomainDeviceDefPtr dev, + qemuDomainAsyncJob asyncJob) { size_t i; virDomainDiskDefPtr disk = dev->data.disk; @@ -1175,6 +1181,7 @@ qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriverPtr driver, } if (qemuHotplugDiskPrepareOneDiskTransient(driver, vm, dev, + asyncJob, &transientDiskCreated) < 0) goto cleanup; } @@ -1195,11 +1202,11 @@ qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriverPtr driver, break; case VIR_DOMAIN_DISK_BUS_VIRTIO: - ret = qemuDomainAttachVirtioDiskDevice(driver, vm, disk); + ret = qemuDomainAttachVirtioDiskDevice(driver, vm, disk, asyncJob); break; case VIR_DOMAIN_DISK_BUS_SCSI: - ret = qemuDomainAttachSCSIDisk(driver, vm, disk); + ret = qemuDomainAttachSCSIDisk(driver, vm, disk, asyncJob); break; case VIR_DOMAIN_DISK_BUS_IDE: @@ -1261,7 +1268,7 @@ qemuDomainAttachDeviceDiskLive(virQEMUDriverPtr driver, return 0; } - return qemuDomainAttachDeviceDiskLiveInternal(driver, vm, dev); + return qemuDomainAttachDeviceDiskLiveInternal(driver, vm, dev, QEMU_ASYNC_JOB_NONE); } @@ -4416,7 +4423,8 @@ static bool qemuIsMultiFunctionDevice(virDomainDefPtr def, static int qemuDomainRemoveDiskDevice(virQEMUDriverPtr driver, virDomainObjPtr vm, - virDomainDiskDefPtr disk) + virDomainDiskDefPtr disk, + qemuDomainAsyncJob asyncJob) { qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); g_autoptr(qemuBlockStorageSourceChainData) diskBackend = NULL; @@ -4466,7 +4474,8 @@ qemuDomainRemoveDiskDevice(virQEMUDriverPtr driver, } } - qemuDomainObjEnterMonitor(driver, vm); + if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) + goto cleanup; if (corAlias) ignore_value(qemuMonitorBlockdevDel(priv->mon, corAlias)); @@ -5214,7 +5223,8 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver, * into this function. */ case VIR_DOMAIN_DEVICE_DISK: - if (qemuDomainRemoveDiskDevice(driver, vm, dev->data.disk) < 0) + if (qemuDomainRemoveDiskDevice(driver, vm, dev->data.disk, + QEMU_ASYNC_JOB_NONE) < 0) return -1; break; case VIR_DOMAIN_DEVICE_CONTROLLER: -- 2.27.0

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> Enable <transient/> and <shareable/> disk option for virtio and scsi bus. When both options are set to the disk, qemu runs with 'blockdev' options for the original disk which is marked as readonly, and without the 'device' option. Then an overlay disk is created and attached to the guest. Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- src/qemu/qemu_command.c | 11 +++++ src/qemu/qemu_hotplug.c | 86 +++++++++++++++++++++++++++++++++++++++- src/qemu/qemu_hotplug.h | 3 ++ src/qemu/qemu_process.c | 21 +++++++++- src/qemu/qemu_snapshot.c | 9 +++-- 5 files changed, 125 insertions(+), 5 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 1b4fa77867..b48e06d3da 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2142,6 +2142,11 @@ qemuBuildDiskCommandLine(virCommandPtr cmd, { g_autofree char *optstr = NULL; + /* The disk which has transient and sharable disk option + * doesn't need write lock, so mark readonly */ + if (disk->transient && disk->src->shared) + disk->src->readonly = true; + if (qemuBuildDiskSourceCommandLine(cmd, disk, qemuCaps) < 0) return -1; @@ -2159,6 +2164,12 @@ qemuBuildDiskCommandLine(virCommandPtr cmd, if (qemuCommandAddExtDevice(cmd, &disk->info) < 0) return -1; + if (disk->transient && disk->src->shared) { + VIR_DEBUG("%s has transient and shareable disk option, so it's hot-added later.", + disk->src->path); + return 0; + } + virCommandAddArg(cmd, "-device"); if (!(optstr = qemuBuildDiskDeviceStr(def, disk, bootindex, diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 366ebeaa7c..99fc5fca5f 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -4502,7 +4502,7 @@ qemuDomainRemoveDiskDevice(virQEMUDriverPtr driver, qemuHotplugRemoveManagedPR(driver, vm, QEMU_ASYNC_JOB_NONE) < 0) goto cleanup; - if (disk->transient) { + if (disk->transient && (asyncJob != QEMU_ASYNC_JOB_START)) { VIR_DEBUG("Removing transient overlay '%s' of disk '%s'", disk->src->path, disk->dst); if (qemuDomainStorageFileInit(driver, vm, disk->src, NULL) >= 0) { @@ -4519,6 +4519,90 @@ qemuDomainRemoveDiskDevice(virQEMUDriverPtr driver, } +/* XXX: + * Fix memory leaks when failures happen + */ +static int +qemuHotplugDiskPrepareDisksTransient(virDomainObjPtr vm, + virQEMUDriverConfigPtr cfg G_GNUC_UNUSED, + qemuDomainAsyncJob asyncJob) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + virQEMUDriverPtr driver = priv->driver; + size_t i; + + for (i = 0; i < vm->def->ndisks; i++) { + virDomainDiskDefPtr domdisk = vm->def->disks[i]; + virDomainDiskDefPtr newdisk; + virDomainDeviceDefPtr dev; + + if (!domdisk->transient) + continue; + + if (domdisk->transient && !domdisk->src->shared) { + VIR_DEBUG("Transient disk for %s is already built with blockdev-snapshot", + domdisk->src->path); + continue; + } + + if (!(newdisk = virDomainDiskDefNew(driver->xmlopt))) + return -1; + + memcpy(&newdisk->info, &domdisk->info, sizeof(virDomainDeviceInfo)); + newdisk->info.alias = NULL; + newdisk->info.romfile = NULL; + newdisk->bus = domdisk->bus; + newdisk->dst = g_strdup(domdisk->dst); + newdisk->transient = true; + + if (!(dev = g_new0(virDomainDeviceDef, 1))) + return -1; + + dev->type = VIR_DOMAIN_DEVICE_DISK; + + if (!(newdisk->src = virStorageSourceCopy(domdisk->src, false))) + return -1; + + if (qemuDomainRemoveDiskDevice(driver, vm, domdisk, asyncJob) < 0) + return -1; + + newdisk->src->readonly = false; + + dev->data.disk = newdisk; + + VIR_DEBUG("Attaching transient disk %s", dev->data.disk->dst); + if (qemuDomainAttachDeviceDiskLiveInternal(driver, vm, dev, asyncJob) < 0) { + VIR_DEBUG("Failed to attach disk %s", dev->data.disk->dst); + return -1; + } + + VIR_FREE(dev); + } + + return 0; +} + + +int +qemuHotplugCreateDisksTransient(virDomainObjPtr vm, + qemuDomainAsyncJob asyncJob) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + virQEMUDriverPtr driver = priv->driver; + g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); + + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV) && + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_PCIE_ROOT_PORT_HOTPLUG)) { + + VIR_DEBUG("prepare transient disks with disk hotplug"); + if (qemuHotplugDiskPrepareDisksTransient(vm, cfg, asyncJob) < 0) + return -1; + } + + return 0; +} + + static int qemuDomainRemoveControllerDevice(virDomainObjPtr vm, virDomainControllerDefPtr controller) diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h index 6287c5b5e8..baef2dba42 100644 --- a/src/qemu/qemu_hotplug.h +++ b/src/qemu/qemu_hotplug.h @@ -160,3 +160,6 @@ int qemuHotplugAttachDBusVMState(virQEMUDriverPtr driver, int qemuHotplugRemoveDBusVMState(virQEMUDriverPtr driver, virDomainObjPtr vm, qemuDomainAsyncJob asyncJob); + +int qemuHotplugCreateDisksTransient(virDomainObjPtr vm, + qemuDomainAsyncJob asyncJob); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 4ba634dfc5..5724a88b7f 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -6863,6 +6863,25 @@ qemuProcessEnablePerf(virDomainObjPtr vm) } +static int +qemuProcessCreateDisksTransient(virDomainObjPtr vm, + qemuDomainAsyncJob asyncJob) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + + if (qemuSnapshotCreateDisksTransient(vm, asyncJob) < 0) + return -1; + + if (qemuHotplugCreateDisksTransient(vm, asyncJob) < 0) + return -1; + + /* the overlays are established, so they can be deleted on shutdown */ + priv->inhibitDiskTransientDelete = false; + + return 0; +} + + /** * qemuProcessLaunch: * @@ -7216,7 +7235,7 @@ qemuProcessLaunch(virConnectPtr conn, goto cleanup; VIR_DEBUG("Setting up transient disk"); - if (qemuSnapshotCreateDisksTransient(vm, asyncJob) < 0) + if (qemuProcessCreateDisksTransient(vm, asyncJob) < 0) goto cleanup; ret = 0; diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c index a5cc0d47f2..764eba7b3d 100644 --- a/src/qemu/qemu_snapshot.c +++ b/src/qemu/qemu_snapshot.c @@ -1188,6 +1188,12 @@ qemuSnapshotDiskPrepareDisksTransient(virDomainObjPtr vm, if (!domdisk->transient) continue; + if (domdisk->transient && domdisk->src->shared) { + VIR_DEBUG("%s has shareable disk option, so it's hot-added later.", + domdisk->src->path); + continue; + } + /* validation code makes sure that we do this only for local disks * with a file source */ snapdisk->name = g_strdup(domdisk->dst); @@ -1379,9 +1385,6 @@ qemuSnapshotCreateDisksTransient(virDomainObjPtr vm, return -1; } - /* the overlays are established, so they can be deleted on shutdown */ - priv->inhibitDiskTransientDelete = false; - return 0; } -- 2.27.0

From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> Add shareable transient disk test to qemuxml2argvdata. Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> --- ...isk-transient-shareable.x86_64-latest.args | 41 +++++++++++++++++++ .../disk-transient-shareable.xml | 26 ++++++++++++ tests/qemuxml2argvtest.c | 1 + 3 files changed, 68 insertions(+) create mode 100644 tests/qemuxml2argvdata/disk-transient-shareable.x86_64-latest.args create mode 100644 tests/qemuxml2argvdata/disk-transient-shareable.xml diff --git a/tests/qemuxml2argvdata/disk-transient-shareable.x86_64-latest.args b/tests/qemuxml2argvdata/disk-transient-shareable.x86_64-latest.args new file mode 100644 index 0000000000..21669559cf --- /dev/null +++ b/tests/qemuxml2argvdata/disk-transient-shareable.x86_64-latest.args @@ -0,0 +1,41 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/tmp/lib/domain--1-QEMUGuest1 \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \ +/usr/bin/qemu-system-i386 \ +-name guest=QEMUGuest1,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw",\ +"file":"/tmp/lib/domain--1-QEMUGuest1/master-key.aes"}' \ +-machine pc,accel=tcg,usb=off,dump-guest-core=off,memory-backend=pc.ram \ +-cpu qemu64 \ +-m 214 \ +-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-no-acpi \ +-boot strict=on \ +-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \ +-blockdev '{"driver":"file","filename":"/tmp/QEMUGuest1.img",\ +"node-name":"libvirt-1-storage","cache":{"direct":true,"no-flush":false},\ +"auto-read-only":true,"discard":"unmap"}' \ +-blockdev '{"node-name":"libvirt-1-format","read-only":true,\ +"cache":{"direct":true,"no-flush":false},"driver":"qcow2",\ +"file":"libvirt-1-storage"}' \ +-audiodev id=audio1,driver=none \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\ +resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxml2argvdata/disk-transient-shareable.xml b/tests/qemuxml2argvdata/disk-transient-shareable.xml new file mode 100644 index 0000000000..075811809b --- /dev/null +++ b/tests/qemuxml2argvdata/disk-transient-shareable.xml @@ -0,0 +1,26 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-i386</emulator> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2' cache='none'/> + <source file='/tmp/QEMUGuest1.img'/> + <target dev='vda' bus='virtio'/> + <shareable/> + <transient/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> + </disk> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 12c2b68fd7..b74e9ee824 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1347,6 +1347,7 @@ mymain(void) DO_TEST_CAPS_LATEST("disk-metadata-cache"); DO_TEST_CAPS_ARCH_VER_PARSE_ERROR("disk-transient", "x86_64", "4.1.0"); DO_TEST_CAPS_LATEST("disk-transient"); + DO_TEST_CAPS_LATEST("disk-transient-shareable"); DO_TEST("disk-network-nbd", NONE); DO_TEST_CAPS_VER("disk-network-nbd", "2.12.0"); DO_TEST_CAPS_LATEST("disk-network-nbd"); -- 2.27.0

On Wed, Mar 24, 2021 at 20:54:04 -0400, Masayoshi Mizuma wrote:
This patch series has two parts; the first part is trying to support for hotplugging disks with <transient/> option for qemu, and make the disk shareable when <shareable/> disk option is set as well.
The second part is trying to make shareable the disks with <transient/> disk option which is described on the domain xml. The second part is marked as Work In Progress (WIP) because the design may be modified by the first part changes.
I have had a look at this series and I have spotted a few significant problems with it: - <shareable/> must not be abused in this case, since you've used it in a different meaning that it actually has: - shareable means that the TOP image is shareable between VMs - QCOW2 images must not be shareable as QCOW2 metadata can't be shared - the combination of commandline instantiated -blockdev backends and hotplugged disk frontends - everything should be done together - tests fail in between patches Since I'm planning a few refactors around this code which will allow simpler fixing of some of the problems I have with the patches I think it will be best if I pick up the patches and fix them after I'm done with the refactors, so there's no need to attempt to fix the problems I've pointed out for now. Thanks Peter

On Tue, Apr 13, 2021 at 05:52:59PM +0200, Peter Krempa wrote:
On Wed, Mar 24, 2021 at 20:54:04 -0400, Masayoshi Mizuma wrote:
This patch series has two parts; the first part is trying to support for hotplugging disks with <transient/> option for qemu, and make the disk shareable when <shareable/> disk option is set as well.
The second part is trying to make shareable the disks with <transient/> disk option which is described on the domain xml. The second part is marked as Work In Progress (WIP) because the design may be modified by the first part changes.
I have had a look at this series and I have spotted a few significant problems with it:
- <shareable/> must not be abused in this case, since you've used it in a different meaning that it actually has: - shareable means that the TOP image is shareable between VMs - QCOW2 images must not be shareable as QCOW2 metadata can't be shared - the combination of commandline instantiated -blockdev backends and hotplugged disk frontends
- everything should be done together
- tests fail in between patches
Since I'm planning a few refactors around this code which will allow simpler fixing of some of the problems I have with the patches I think it will be best if I pick up the patches and fix them after I'm done with the refactors, so there's no need to attempt to fix the problems I've pointed out for now.
Thank you for your comments. I really appreciate your help with this! - Masa
participants (2)
-
Masayoshi Mizuma
-
Peter Krempa