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