[libvirt] [PATCH v3 17/18] qemu: Add -blockdev support for external snapshots

Peter Krempa pkrempa at redhat.com
Tue Sep 3 14:08:10 UTC 2019


Use the code for creating or attaching new storage source in the
snapshot code and switch to 'blockdev-snapshot' for creating the
snapshot itself.

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
Reviewed-by: Ján Tomko <jtomko at redhat.com>
---
 src/qemu/qemu_driver.c | 104 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 88 insertions(+), 16 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 8a0f1697cb..9523da4cfc 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -15256,6 +15256,8 @@ struct _qemuDomainSnapshotDiskData {
     bool prepared; /* @src was prepared using qemuDomainStorageSourceAccessAllow */
     virDomainDiskDefPtr disk;
     char *relPath; /* relative path component to fill into original disk */
+    qemuBlockStorageSourceChainDataPtr crdata;
+    bool blockdevadded;

     virStorageSourcePtr persistsrc;
     virDomainDiskDefPtr persistdisk;
@@ -15269,7 +15271,8 @@ static void
 qemuDomainSnapshotDiskCleanup(qemuDomainSnapshotDiskDataPtr data,
                               size_t ndata,
                               virQEMUDriverPtr driver,
-                              virDomainObjPtr vm)
+                              virDomainObjPtr vm,
+                              qemuDomainAsyncJob asyncJob)
 {
     virErrorPtr orig_err;
     size_t i;
@@ -15283,6 +15286,15 @@ qemuDomainSnapshotDiskCleanup(qemuDomainSnapshotDiskDataPtr data,
         /* on success of the snapshot the 'src' and 'persistsrc' properties will
          * be set to NULL by qemuDomainSnapshotDiskUpdateSource */
         if (data[i].src) {
+            if (data[i].blockdevadded) {
+                if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) {
+
+                    qemuBlockStorageSourceAttachRollback(qemuDomainGetMonitor(vm),
+                                                         data[i].crdata->srcdata[0]);
+                    ignore_value(qemuDomainObjExitMonitor(driver, vm));
+                }
+            }
+
             if (data[i].created &&
                 virStorageFileUnlink(data[i].src) < 0) {
                 VIR_WARN("Unable to remove just-created %s",
@@ -15299,6 +15311,7 @@ qemuDomainSnapshotDiskCleanup(qemuDomainSnapshotDiskDataPtr data,
         }
         virObjectUnref(data[i].persistsrc);
         VIR_FREE(data[i].relPath);
+        qemuBlockStorageSourceChainDataFree(data[i].crdata);
     }

     VIR_FREE(data);
@@ -15309,15 +15322,21 @@ qemuDomainSnapshotDiskCleanup(qemuDomainSnapshotDiskDataPtr data,
 static int
 qemuDomainSnapshotDiskPrepareOne(virQEMUDriverPtr driver,
                                  virDomainObjPtr vm,
+                                 virQEMUDriverConfigPtr cfg,
                                  virDomainDiskDefPtr disk,
                                  virDomainSnapshotDiskDefPtr snapdisk,
                                  qemuDomainSnapshotDiskDataPtr dd,
-                                 bool reuse)
+                                 bool reuse,
+                                 bool blockdev,
+                                 qemuDomainAsyncJob asyncJob)
 {
+    qemuDomainObjPrivatePtr priv = vm->privateData;
     char *backingStoreStr;
     virDomainDiskDefPtr persistdisk;
+    VIR_AUTOUNREF(virStorageSourcePtr) terminator = NULL;
     bool supportsCreate;
     bool supportsBacking;
+    int rc;

     dd->disk = disk;

@@ -15383,6 +15402,44 @@ qemuDomainSnapshotDiskPrepareOne(virQEMUDriverPtr driver,

     dd->prepared = true;

+    if (blockdev) {
+        /* create a terminator for the snapshot disks so that qemu does not try
+         * to open them at first */
+        if (!(terminator = virStorageSourceNew()))
+            return -1;
+
+        if (qemuDomainPrepareStorageSourceBlockdev(dd->disk, dd->src,
+                                                   priv, cfg) < 0)
+            return -1;
+
+        if (!(dd->crdata = qemuBuildStorageSourceChainAttachPrepareBlockdevTop(dd->src,
+                                                                               terminator,
+                                                                               priv->qemuCaps)))
+            return -1;
+
+        if (reuse) {
+            if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+                return -1;
+
+            rc = qemuBlockStorageSourceAttachApply(qemuDomainGetMonitor(vm),
+                                                   dd->crdata->srcdata[0]);
+
+            if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
+                return -1;
+        } else {
+            if (qemuBlockStorageSourceCreateDetectSize(vm, dd->src, dd->disk->src,
+                                                       asyncJob) < 0)
+                return -1;
+
+            if (qemuBlockStorageSourceCreate(vm, dd->src, dd->disk->src,
+                                             NULL, dd->crdata->srcdata[0],
+                                             asyncJob) < 0)
+                return -1;
+        }
+
+        dd->blockdevadded = true;
+    }
+
     return 0;
 }

@@ -15397,7 +15454,10 @@ static int
 qemuDomainSnapshotDiskPrepare(virQEMUDriverPtr driver,
                               virDomainObjPtr vm,
                               virDomainMomentObjPtr snap,
+                              virQEMUDriverConfigPtr cfg,
                               bool reuse,
+                              bool blockdev,
+                              qemuDomainAsyncJob asyncJob,
                               qemuDomainSnapshotDiskDataPtr *rdata,
                               size_t *rndata)
 {
@@ -15414,9 +15474,10 @@ qemuDomainSnapshotDiskPrepare(virQEMUDriverPtr driver,
         if (snapdef->disks[i].snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE)
             continue;

-        if (qemuDomainSnapshotDiskPrepareOne(driver, vm, vm->def->disks[i],
+        if (qemuDomainSnapshotDiskPrepareOne(driver, vm, cfg, vm->def->disks[i],
                                              snapdef->disks + i,
-                                             data + ndata++, reuse) < 0)
+                                             data + ndata++, reuse, blockdev,
+                                             asyncJob) < 0)
             goto cleanup;
     }

@@ -15425,7 +15486,7 @@ qemuDomainSnapshotDiskPrepare(virQEMUDriverPtr driver,
     ret = 0;

  cleanup:
-    qemuDomainSnapshotDiskCleanup(data, ndata, driver, vm);
+    qemuDomainSnapshotDiskCleanup(data, ndata, driver, vm, asyncJob);
     return ret;
 }

@@ -15446,13 +15507,15 @@ qemuDomainSnapshotDiskUpdateSourceRenumber(virStorageSourcePtr src)
  * @driver: QEMU driver
  * @vm: domain object
  * @dd: snapshot disk data object
+ * @blockdev: -blockdev is in use for the VM
  *
  * Updates disk definition after a successful snapshot.
  */
 static void
 qemuDomainSnapshotDiskUpdateSource(virQEMUDriverPtr driver,
                                    virDomainObjPtr vm,
-                                   qemuDomainSnapshotDiskDataPtr dd)
+                                   qemuDomainSnapshotDiskDataPtr dd,
+                                   bool blockdev)
 {
     /* storage driver access won'd be needed */
     if (dd->initialized)
@@ -15476,7 +15539,8 @@ qemuDomainSnapshotDiskUpdateSource(virQEMUDriverPtr driver,
     VIR_STEAL_PTR(dd->disk->src, dd->src);

     /* fix numbering of disks */
-    qemuDomainSnapshotDiskUpdateSourceRenumber(dd->disk->src);
+    if (!blockdev)
+        qemuDomainSnapshotDiskUpdateSourceRenumber(dd->disk->src);

     if (dd->persistdisk) {
         VIR_STEAL_PTR(dd->persistsrc->backingStore, dd->persistdisk->src);
@@ -15502,6 +15566,7 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
     bool reuse = (flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT) != 0;
     qemuDomainSnapshotDiskDataPtr diskdata = NULL;
     size_t ndiskdata = 0;
+    bool blockdev =  virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);

     if (virDomainObjCheckActive(vm) < 0)
         return -1;
@@ -15511,8 +15576,8 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,

     /* prepare a list of objects to use in the vm definition so that we don't
      * have to roll back later */
-    if (qemuDomainSnapshotDiskPrepare(driver, vm, snap, reuse,
-                                      &diskdata, &ndiskdata) < 0)
+    if (qemuDomainSnapshotDiskPrepare(driver, vm, snap, cfg, reuse, blockdev,
+                                      asyncJob, &diskdata, &ndiskdata) < 0)
         goto cleanup;

     /* check whether there's anything to do */
@@ -15526,11 +15591,18 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
       * VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL with a valid file name and
       * qcow2 format.  */
     for (i = 0; i < ndiskdata; i++) {
-        if (qemuBlockSnapshotAddLegacy(actions,
-                                       diskdata[i].disk,
-                                       diskdata[i].src,
-                                       reuse) < 0)
-            goto cleanup;
+        if (blockdev) {
+            if (qemuBlockSnapshotAddBlockdev(actions,
+                                             diskdata[i].disk,
+                                             diskdata[i].src))
+                goto cleanup;
+        } else {
+            if (qemuBlockSnapshotAddLegacy(actions,
+                                           diskdata[i].disk,
+                                           diskdata[i].src,
+                                           reuse) < 0)
+                goto cleanup;
+        }
     }

     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
@@ -15547,7 +15619,7 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
         virDomainAuditDisk(vm, dd->disk->src, dd->src, "snapshot", rc >= 0);

         if (rc == 0)
-            qemuDomainSnapshotDiskUpdateSource(driver, vm, dd);
+            qemuDomainSnapshotDiskUpdateSource(driver, vm, dd, blockdev);
     }

     if (rc < 0)
@@ -15561,7 +15633,7 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
     ret = 0;

  cleanup:
-    qemuDomainSnapshotDiskCleanup(diskdata, ndiskdata, driver, vm);
+    qemuDomainSnapshotDiskCleanup(diskdata, ndiskdata, driver, vm, asyncJob);
     return ret;
 }

-- 
2.21.0




More information about the libvir-list mailing list