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

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