Blame SOURCES/libvirt-qemu-blockcopy-Allow-late-opening-of-the-backing-chain-of-a-shallow-copy.patch

d76c62
From 7e60e728bc225b3499a3d1fad6b56d0ce8c40908 Mon Sep 17 00:00:00 2001
d76c62
Message-Id: <7e60e728bc225b3499a3d1fad6b56d0ce8c40908@dist-git>
d76c62
From: Peter Krempa <pkrempa@redhat.com>
d76c62
Date: Mon, 16 Mar 2020 22:11:39 +0100
d76c62
Subject: [PATCH] qemu: blockcopy: Allow late opening of the backing chain of a
d76c62
 shallow copy
d76c62
MIME-Version: 1.0
d76c62
Content-Type: text/plain; charset=UTF-8
d76c62
Content-Transfer-Encoding: 8bit
d76c62
d76c62
oVirt used a quirk in the pre-blockdev semantics of drive-mirror which
d76c62
opened the backing chain of the mirror destination only once
d76c62
'block-job-complete' was called.
d76c62
d76c62
Our introduction of blockdev made qemu open the backing chain images
d76c62
right at the start of the job. This broke oVirt's usage of this API
d76c62
because they copy the data into the backing chain during the time the
d76c62
block copy job is running.
d76c62
d76c62
Re-introduce late open of the backing chain if qemu allows us to use
d76c62
blockdev-snapshot on write-only nodes as it can be used to install the
d76c62
backing chain even for an existing image now.
d76c62
d76c62
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
d76c62
Reviewed-by: Eric Blake <eblake@redhat.com>
d76c62
(cherry picked from commit cc7868a8b3cfa4a0062936c23e82e4a31923f724)
d76c62
d76c62
https://bugzilla.redhat.com/show_bug.cgi?id=1803092
d76c62
Message-Id: <d37e660b9610d7a1cc42892ff3305cb477a8f98a.1584391726.git.pkrempa@redhat.com>
d76c62
Reviewed-by: Ján Tomko <jtomko@redhat.com>
d76c62
---
d76c62
 src/qemu/qemu_driver.c | 57 +++++++++++++++++++++++++++++++++++++++---
d76c62
 1 file changed, 53 insertions(+), 4 deletions(-)
d76c62
d76c62
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
d76c62
index 5a4e979907..441bb02b6b 100644
d76c62
--- a/src/qemu/qemu_driver.c
d76c62
+++ b/src/qemu/qemu_driver.c
d76c62
@@ -17556,10 +17556,12 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
d76c62
                      qemuBlockJobDataPtr job,
d76c62
                      virDomainDiskDefPtr disk)
d76c62
 {
d76c62
+    g_autoptr(qemuBlockStorageSourceChainData) chainattachdata = NULL;
d76c62
     int ret = -1;
d76c62
     qemuDomainObjPrivatePtr priv = vm->privateData;
d76c62
     bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV);
d76c62
     g_autoptr(virJSONValue) actions = NULL;
d76c62
+    g_autoptr(virJSONValue) reopenactions = NULL;
d76c62
 
d76c62
     if (job->state != QEMU_BLOCKJOB_STATE_READY) {
d76c62
         virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
d76c62
@@ -17590,6 +17592,7 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
d76c62
         if (blockdev && !job->jobflagsmissing) {
d76c62
             g_autoptr(virHashTable) blockNamedNodeData = NULL;
d76c62
             bool shallow = job->jobflags & VIR_DOMAIN_BLOCK_COPY_SHALLOW;
d76c62
+            bool reuse = job->jobflags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT;
d76c62
 
d76c62
             if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, QEMU_ASYNC_JOB_NONE)))
d76c62
                 return -1;
d76c62
@@ -17598,6 +17601,27 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
d76c62
                                                 blockNamedNodeData,
d76c62
                                                 shallow, &actions) < 0)
d76c62
                 return -1;
d76c62
+
d76c62
+            /* Open and install the backing chain of 'mirror' late if we can use
d76c62
+             * blockdev-snapshot to do it. This is to appease oVirt that wants
d76c62
+             * to copy data into the backing chain while the top image is being
d76c62
+             * copied shallow */
d76c62
+            if (reuse && shallow &&
d76c62
+                virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_SNAPSHOT_ALLOW_WRITE_ONLY) &&
d76c62
+                virStorageSourceHasBacking(disk->mirror)) {
d76c62
+
d76c62
+                if (!(chainattachdata = qemuBuildStorageSourceChainAttachPrepareBlockdev(disk->mirror->backingStore,
d76c62
+                                                                                         priv->qemuCaps)))
d76c62
+                    return -1;
d76c62
+
d76c62
+                reopenactions = virJSONValueNewArray();
d76c62
+
d76c62
+                if (qemuMonitorTransactionSnapshotBlockdev(reopenactions,
d76c62
+                                                           disk->mirror->backingStore->nodeformat,
d76c62
+                                                           disk->mirror->nodeformat))
d76c62
+                    return -1;
d76c62
+            }
d76c62
+
d76c62
         }
d76c62
         break;
d76c62
 
d76c62
@@ -17609,7 +17633,15 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
d76c62
     if (blockdev) {
d76c62
         int rc = 0;
d76c62
 
d76c62
-        if (actions)
d76c62
+        if (chainattachdata) {
d76c62
+            if ((rc = qemuBlockStorageSourceChainAttach(priv->mon, chainattachdata)) == 0) {
d76c62
+                /* install backing images on success, or unplug them on failure */
d76c62
+                if ((rc = qemuMonitorTransaction(priv->mon, &reopenactions)) != 0)
d76c62
+                    qemuBlockStorageSourceChainDetach(priv->mon, chainattachdata);
d76c62
+            }
d76c62
+        }
d76c62
+
d76c62
+        if (actions && rc == 0)
d76c62
             rc = qemuMonitorTransaction(priv->mon, &actions);
d76c62
 
d76c62
         if (rc == 0)
d76c62
@@ -18354,9 +18386,26 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm,
d76c62
 
d76c62
     if (blockdev) {
d76c62
         if (mirror_reuse) {
d76c62
-            if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdev(mirror,
d76c62
-                                                                          priv->qemuCaps)))
d76c62
-                goto endjob;
d76c62
+            /* oVirt depended on late-backing-chain-opening semantics the old
d76c62
+             * qemu command had to copy the backing chain data while the top
d76c62
+             * level is being copied. To restore this semantics if
d76c62
+             * blockdev-reopen is supported defer opening of the backing chain
d76c62
+             * of 'mirror' to the pivot step */
d76c62
+            if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_SNAPSHOT_ALLOW_WRITE_ONLY)) {
d76c62
+                g_autoptr(virStorageSource) terminator = virStorageSourceNew();
d76c62
+
d76c62
+                if (!terminator)
d76c62
+                    goto endjob;
d76c62
+
d76c62
+                if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdevTop(mirror,
d76c62
+                                                                                 terminator,
d76c62
+                                                                                 priv->qemuCaps)))
d76c62
+                    goto endjob;
d76c62
+            } else {
d76c62
+                if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdev(mirror,
d76c62
+                                                                              priv->qemuCaps)))
d76c62
+                    goto endjob;
d76c62
+            }
d76c62
         } else {
d76c62
             if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, QEMU_ASYNC_JOB_NONE)))
d76c62
                 goto endjob;
d76c62
-- 
d76c62
2.25.1
d76c62