[libvirt] [PATCH v4 5/5] blockcommit: turn on active commit

Eric Blake eblake at redhat.com
Mon Jun 23 23:30: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!

Still not done: the persistent XML is not updated; which means
stopping and restarting a persistent guest will use the wrong
file and likely fail to boot.

* 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 | 40 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 35 insertions(+), 5 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 79554e9..ae81712 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -15493,9 +15493,12 @@ 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;
@@ -15543,9 +15546,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",
@@ -15559,6 +15559,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;
     } else if (flags & VIR_DOMAIN_BLOCK_COMMIT_ACTIVE) {
         virReportError(VIR_ERR_INVALID_ARG,
                        _("active commit requested but '%s' is not active"),
@@ -15605,6 +15613,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
@@ -15617,6 +15640,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.  */
@@ -15627,6 +15656,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