Implement this behaviour by skipping the disks on traditional
commandline and hotplug them before resuming CPUs. That allows to use
the support for hotplugging of transient disks which inherently allows
sharing of the backing image as we open it read-only.
This commit implements the validation code to allow it only with buses
supporting hotplug and the hotplug code while starting up the VM.
When we have such disk we need to issue a system-reset so that firmware
tables are regenerated to allow booting from such device.
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
src/qemu/qemu_command.c | 6 ++++++
src/qemu/qemu_process.c | 45 +++++++++++++++++++++++++++++++++++++++-
src/qemu/qemu_validate.c | 24 +++++++++++++++++++++
3 files changed, 74 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 9c32fd16b5..697324eea5 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -2164,6 +2164,12 @@ qemuBuildDisksCommandLine(virCommand *cmd,
for (i = 0; i < def->ndisks; i++) {
virDomainDiskDef *disk = def->disks[i];
+ /* transient disks with shared backing image will be hotplugged after
+ * the VM is started */
+ if (disk->transient &&
+ disk->transientShareBacking == VIR_TRISTATE_BOOL_YES)
+ continue;
+
if (qemuBuildDiskCommandLine(cmd, def, disk, qemuCaps) < 0)
return -1;
}
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 9302180403..c0b4f3530f 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7017,7 +7017,8 @@ qemuProcessSetupDisksTransientSnapshot(virDomainObj *vm,
virDomainDiskDef *domdisk = vm->def->disks[i];
g_autoptr(virDomainSnapshotDiskDef) snapdisk = NULL;
- if (!domdisk->transient)
+ if (!domdisk->transient ||
+ domdisk->transientShareBacking == VIR_TRISTATE_BOOL_YES)
continue;
/* validation code makes sure that we do this only for local disks
@@ -7048,6 +7049,45 @@ qemuProcessSetupDisksTransientSnapshot(virDomainObj *vm,
}
+static int
+qemuProcessSetupDisksTransientHotplug(virDomainObj *vm,
+ qemuDomainAsyncJob asyncJob)
+{
+ qemuDomainObjPrivate *priv = vm->privateData;
+ bool hasHotpluggedDisk = false;
+ size_t i;
+
+ for (i = 0; i < vm->def->ndisks; i++) {
+ virDomainDiskDef *domdisk = vm->def->disks[i];
+
+ if (!domdisk->transient ||
+ domdisk->transientShareBacking != VIR_TRISTATE_BOOL_YES)
+ continue;
+
+ if (qemuDomainAttachDiskGeneric(priv->driver, vm, domdisk, asyncJob) < 0)
+ return -1;
+
+ hasHotpluggedDisk = true;
+ }
+
+ /* in order to allow booting from such disks we need to issue a system-reset
+ * so that the firmware tables recording bootable devices are regerated */
+ if (hasHotpluggedDisk) {
+ int rc;
+
+ if (qemuDomainObjEnterMonitorAsync(priv->driver, vm, asyncJob) < 0)
+ return -1;
+
+ rc = qemuMonitorSystemReset(priv->mon);
+
+ if (qemuDomainObjExitMonitor(priv->driver, vm) < 0 || rc < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int
qemuProcessSetupDisksTransient(virDomainObj *vm,
qemuDomainAsyncJob asyncJob)
@@ -7060,6 +7100,9 @@ qemuProcessSetupDisksTransient(virDomainObj *vm,
if (qemuProcessSetupDisksTransientSnapshot(vm, asyncJob) < 0)
return -1;
+ if (qemuProcessSetupDisksTransientHotplug(vm, asyncJob) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 9c74092f23..6d6bca859b 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -2980,6 +2980,30 @@ qemuValidateDomainDeviceDefDiskTransient(const virDomainDiskDef
*disk,
return -1;
}
+ if (disk->transientShareBacking == VIR_TRISTATE_BOOL_YES) {
+ /* sharing the backing file requires hotplug of the disk in the qemu driver */
+ switch (disk->bus) {
+ case VIR_DOMAIN_DISK_BUS_USB:
+ case VIR_DOMAIN_DISK_BUS_VIRTIO:
+ case VIR_DOMAIN_DISK_BUS_SCSI:
+ break;
+
+ case VIR_DOMAIN_DISK_BUS_IDE:
+ case VIR_DOMAIN_DISK_BUS_FDC:
+ case VIR_DOMAIN_DISK_BUS_XEN:
+ case VIR_DOMAIN_DISK_BUS_UML:
+ case VIR_DOMAIN_DISK_BUS_SATA:
+ case VIR_DOMAIN_DISK_BUS_SD:
+ case VIR_DOMAIN_DISK_BUS_NONE:
+ case VIR_DOMAIN_DISK_BUS_LAST:
+ default:
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("disk bus '%s' doesn't support transiend
disk backing image sharing"),
+ virDomainDiskBusTypeToString(disk->bus));
+ return -1;
+ }
+ }
+
return 0;
}
--
2.31.1