[libvirt] [PATCH v5 4/4] blockcommit: turn on active commit

Eric Blake eblake at redhat.com
Tue Jul 29 04:20:56 UTC 2014


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

virsh blockcommit $dom vda --shallow --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.

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

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 683eaf3..9cf8fe8 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -15517,9 +15517,11 @@ qemuDomainBlockCommit(virDomainPtr dom,
     char *topPath = NULL;
     char *basePath = NULL;
     char *backingPath = NULL;
+    virStorageSourcePtr mirror = NULL;

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

     if (!(vm = qemuDomObjFromDomain(dom)))
@@ -15568,9 +15570,6 @@ 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) {
         if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_ACTIVE_COMMIT)) {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
@@ -15584,6 +15583,12 @@ 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;
+        }
     } else if (flags & VIR_DOMAIN_BLOCK_COMMIT_ACTIVE) {
         virReportError(VIR_ERR_INVALID_ARG,
                        _("active commit requested but '%s' is not active"),
@@ -15614,6 +15619,16 @@ qemuDomainBlockCommit(virDomainPtr dom,
         goto endjob;
     }

+    /* For an active commit, clone enough of the base to act as the mirror */
+    if (topSource == disk->src) {
+        if (!(mirror = virStorageSourceCopy(baseSource, false)))
+            goto endjob;
+        if (virStorageSourceInitChainElement(mirror,
+                                             disk->src,
+                                             false) < 0)
+            goto endjob;
+    }
+
     /* For the commit to succeed, we must allow qemu to open both the
      * 'base' image and the parent of 'top' as read/write; 'top' might
      * not have a parent, or might already be read-write.  XXX It
@@ -15665,6 +15680,18 @@ qemuDomainBlockCommit(virDomainPtr dom,
                                  bandwidth);
     qemuDomainObjExitMonitor(driver, vm);

+    if (ret == 0 && mirror) {
+        virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+
+        disk->mirror = mirror;
+        mirror = NULL;
+        disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT;
+        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
+            VIR_WARN("Unable to save status on vm %s after block job",
+                     vm->def->name);
+        virObjectUnref(cfg);
+    }
+
  endjob:
     if (ret < 0 && clean_access) {
         /* Revert access to read-only, if possible.  */
@@ -15674,6 +15701,7 @@ qemuDomainBlockCommit(virDomainPtr dom,
             qemuDomainPrepareDiskChainElement(driver, vm, 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