[libvirt] [PATCH v2 10/10] blockcommit: turn on active commit

Eric Blake eblake at redhat.com
Thu Jun 5 22:52:37 UTC 2014


With this in place, I can (finally!) now do:

virsh blockcommit $dom vda --shallow --wait --verbose --pivot

and watch qemu shorten the backing chain by one, followed by
libvirt automatically updating the dumpxml output, effectively
undoing the work of virsh snapshot-commit --no-metadata --disk-only.
Commit is SOOOO much faster than blockpull, when I'm still fairly
close in time to when the temporary qcow2 wrapper file was created
via a snapshot operation!

* src/qemu/qemu_driver.c (qemuDomainBlockCommit): Implement live
commit to regular files.

Signed-off-by: Eric Blake <eblake at redhat.com>
---
 src/qemu/qemu_driver.c | 45 +++++++++++++++++++++++++++++++++++++++------
 1 file changed, 39 insertions(+), 6 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 5903144..c0fc5e9 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -15492,9 +15492,11 @@ qemuDomainBlockCommit(virDomainPtr dom,
     unsigned int baseIndex = 0;
     const char *top_parent = NULL;
     bool clean_access = false;
+    virStorageSourcePtr mirror = NULL;

-    /* XXX Add support for COMMIT_ACTIVE, COMMIT_DELETE */
-    virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW, -1);
+    /* XXX Add support for COMMIT_DELETE */
+    virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW |
+                  VIR_DOMAIN_BLOCK_COMMIT_ACTIVE, -1);

     if (!(vm = qemuDomObjFromDomain(dom)))
         goto cleanup;
@@ -15540,13 +15542,14 @@ qemuDomainBlockCommit(virDomainPtr dom,
                                                      &top_parent)))
         goto endjob;

-    /* FIXME: qemu 2.0 supports active commit, but as a two-stage
-     * process; qemu 2.1 is further improving active commit. We need
-     * to start supporting it in libvirt. */
     if (topSource == disk->src) {
         /* We assume that no one will backport qemu 2.0 active commit
          * to an earlier qemu without also backporting the block job
-         * ready event; but this makes sure of that fact */
+         * ready event; but this makes sure of that fact.
+         *
+         * XXX Also need to check other capability bit(s): qemu 1.7
+         * supports async blockjob but not active commit; and qemu 2.0
+         * active commit misbehaves on 0-byte file.  */
         if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC)) {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                            _("active commit not supported with this QEMU binary"));
@@ -15559,6 +15562,14 @@ qemuDomainBlockCommit(virDomainPtr dom,
                            disk->dst);
             goto endjob;
         }
+        if (disk->mirror) {
+            virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
+                           _("disk '%s' already in active block job"),
+                           disk->dst);
+            goto endjob;
+        }
+        if (VIR_ALLOC(mirror) < 0)
+            goto endjob;
     }

     if (!topSource->backingStore) {
@@ -15600,6 +15611,21 @@ qemuDomainBlockCommit(virDomainPtr dom,
                                                VIR_DISK_CHAIN_READ_WRITE) < 0))
         goto endjob;

+    /* For an active commit, clone enough of the base to act as the mirror */
+    if (mirror) {
+        /* XXX Support network commits */
+        if (baseSource->type != VIR_STORAGE_TYPE_FILE &&
+            baseSource->type != VIR_STORAGE_TYPE_BLOCK) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("active commit to non-file not supported yet"));
+            goto endjob;
+        }
+        mirror->type = baseSource->type;
+        if (VIR_STRDUP(mirror->path, baseSource->path) < 0)
+            goto endjob;
+        mirror->format = baseSource->format;
+    }
+
     /* Start the commit operation.  Pass the user's original spelling,
      * if any, through to qemu, since qemu may behave differently
      * depending on whether the input was specified as relative or
@@ -15612,6 +15638,12 @@ qemuDomainBlockCommit(virDomainPtr dom,
                                  bandwidth);
     qemuDomainObjExitMonitor(driver, vm);

+    if (ret == 0 && mirror) {
+        disk->mirror = mirror;
+        mirror = NULL;
+        disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT;
+    }
+
  endjob:
     if (ret < 0 && clean_access) {
         /* Revert access to read-only, if possible.  */
@@ -15622,6 +15654,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
                                                   top_parent,
                                                   VIR_DISK_CHAIN_READ_ONLY);
     }
+    virStorageSourceFree(mirror);
     if (!qemuDomainObjEndJob(driver, vm))
         vm = NULL;

-- 
1.9.3




More information about the libvir-list mailing list