[PATCH 30/35] qemuDomainAttachDiskGeneric: Implement hotplug of <transient> disk

Peter Krempa pkrempa at redhat.com
Fri May 21 12:47:30 UTC 2021


Add code which creates the transient overlay after hotplugging the disk
backend before attaching the disk frontend.

The state of the topmost image is modified to be already read-only to
prevent the need to open the image in read-write mode.

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 src/qemu/qemu_hotplug.c | 52 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 46 insertions(+), 6 deletions(-)

diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index e13a739ade..59832ea2b3 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -34,6 +34,7 @@
 #include "qemu_process.h"
 #include "qemu_security.h"
 #include "qemu_block.h"
+#include "qemu_snapshot.h"
 #include "domain_audit.h"
 #include "netdev_bandwidth_conf.h"
 #include "domain_nwfilter.h"
@@ -685,6 +686,25 @@ qemuDomainChangeEjectableMedia(virQEMUDriver *driver,
 }


+static qemuSnapshotDiskContext *
+qemuDomainAttachDiskGenericTransient(virDomainObj *vm,
+                                     virDomainDiskDef *disk,
+                                     GHashTable *blockNamedNodeData)
+{
+    g_autoptr(qemuSnapshotDiskContext) snapctxt = NULL;
+    g_autoptr(virDomainSnapshotDiskDef) snapdiskdef = NULL;
+
+    snapdiskdef = qemuSnapshotGetTransientDiskDef(disk, vm->def->name);
+    snapctxt = qemuSnapshotDiskContextNew(1, vm, QEMU_ASYNC_JOB_NONE);
+
+    if (qemuSnapshotDiskPrepareOne(snapctxt, disk, snapdiskdef,
+                                   blockNamedNodeData, false, false) < 0)
+        return NULL;
+
+    return g_steal_pointer(&snapctxt);
+}
+
+
 /**
  * qemuDomainAttachDiskGeneric:
  *
@@ -701,6 +721,11 @@ qemuDomainAttachDiskGeneric(virQEMUDriver *driver,
     bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
     bool extensionDeviceAttached = false;
     int rc;
+    g_autoptr(qemuSnapshotDiskContext) transientDiskSnapshotCtxt = NULL;
+    bool origReadonly = disk->src->readonly;
+
+    if (disk->transient)
+        disk->src->readonly = true;

     if (virStorageSourceGetActualType(disk->src) == VIR_STORAGE_TYPE_VHOST_USER) {
         if (!(data = qemuBuildStorageSourceChainAttachPrepareChardev(disk)))
@@ -723,6 +748,8 @@ qemuDomainAttachDiskGeneric(virQEMUDriver *driver,
             return -1;
     }

+    disk->src->readonly = origReadonly;
+
     qemuDomainObjEnterMonitor(driver, vm);

     rc = qemuBlockStorageSourceChainAttach(priv->mon, data);
@@ -733,6 +760,25 @@ qemuDomainAttachDiskGeneric(virQEMUDriver *driver,
     if (rc < 0)
         goto rollback;

+    if (disk->transient) {
+        g_autoptr(qemuBlockStorageSourceAttachData) backend = NULL;
+        g_autoptr(GHashTable) blockNamedNodeData = NULL;
+
+        if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, QEMU_ASYNC_JOB_NONE)))
+            goto rollback;
+
+        if (!(transientDiskSnapshotCtxt = qemuDomainAttachDiskGenericTransient(vm, disk, blockNamedNodeData)))
+            goto rollback;
+
+
+        if (qemuSnapshotDiskCreate(transientDiskSnapshotCtxt) < 0)
+            goto rollback;
+
+        QEMU_DOMAIN_DISK_PRIVATE(disk)->transientOverlayCreated = true;
+        backend = qemuBlockStorageSourceDetachPrepare(disk->src, NULL);
+        ignore_value(VIR_INSERT_ELEMENT(data->srcdata, 0, data->nsrcdata, backend));
+    }
+
     if (!(devstr = qemuBuildDiskDeviceStr(vm->def, disk, priv->qemuCaps)))
         goto rollback;

@@ -937,12 +983,6 @@ qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriver *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;

-- 
2.31.1




More information about the libvir-list mailing list