|
|
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 |
|