Reuse qemuBlockGetBitmapMergeActions which allows to remove the ad-hoc
implementatio of bitmap merging for block copy.
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
src/qemu/qemu_block.c | 116 +++------------------------------------
src/qemu/qemu_block.h | 3 +-
src/qemu/qemu_blockjob.c | 45 +++++++++++++++
src/qemu/qemu_driver.c | 13 +++--
tests/qemublocktest.c | 12 +++-
5 files changed, 71 insertions(+), 118 deletions(-)
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index fd3fe4c354..d46a631671 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -3035,38 +3035,6 @@ qemuBlockBitmapChainIsValid(virStorageSourcePtr src,
}
-struct qemuBlockBitmapsHandleBlockcopyConcatData {
- virHashTablePtr bitmaps_merge;
- virJSONValuePtr actions;
- const char *mirrornodeformat;
- bool has_bitmaps;
-};
-
-
-static int
-qemuBlockBitmapsHandleBlockcopyConcatActions(void *payload,
- const void *name,
- void *opaque)
-{
- struct qemuBlockBitmapsHandleBlockcopyConcatData *data = opaque;
- virJSONValuePtr createactions = payload;
- const char *bitmapname = name;
- g_autoptr(virJSONValue) mergebitmaps = virHashSteal(data->bitmaps_merge,
bitmapname);
-
- data->has_bitmaps = true;
-
- virJSONValueArrayConcat(data->actions, createactions);
-
- if (qemuMonitorTransactionBitmapMerge(data->actions,
- data->mirrornodeformat,
- bitmapname,
- &mergebitmaps) < 0)
- return -1;
-
- return 0;
-}
-
-
/**
* qemuBlockBitmapsHandleBlockcopy:
* @src: disk source
@@ -3087,88 +3055,18 @@ qemuBlockBitmapsHandleBlockcopy(virStorageSourcePtr src,
virStorageSourcePtr mirror,
virHashTablePtr blockNamedNodeData,
bool shallow,
- virJSONValuePtr *actions)
+ virJSONValuePtr *actions,
+ GSList **allocationbitmapnodes)
{
- g_autoptr(virHashTable) bitmaps = virHashNew(virJSONValueHashFree);
- g_autoptr(virHashTable) bitmaps_merge = virHashNew(virJSONValueHashFree);
- g_autoptr(virHashTable) bitmaps_skip = virHashNew(NULL);
- g_autoptr(virJSONValue) tmpactions = virJSONValueNewArray();
- qemuBlockNamedNodeDataPtr entry;
- virStorageSourcePtr n;
- size_t i;
- struct qemuBlockBitmapsHandleBlockcopyConcatData data = { .bitmaps_merge =
bitmaps_merge,
- .actions = tmpactions,
- .mirrornodeformat =
mirror->nodeformat,
- .has_bitmaps = false, };
-
- for (n = src; n; n = n->backingStore) {
- if (!(entry = virHashLookup(blockNamedNodeData, n->nodeformat)))
- continue;
-
- for (i = 0; i < entry->nbitmaps; i++) {
- qemuBlockNamedNodeDataBitmapPtr bitmap = entry->bitmaps[i];
- virJSONValuePtr bitmap_merge;
-
- if (virHashHasEntry(bitmaps_skip, bitmap->name))
- continue;
-
- if (!(bitmap_merge = virHashLookup(bitmaps_merge, bitmap->name))) {
- g_autoptr(virJSONValue) tmp = NULL;
- bool disabled = !bitmap->recording;
-
- /* disable any non top-layer bitmaps */
- if (n != src)
- disabled = true;
-
- if (!bitmap->persistent ||
- !(qemuBlockBitmapChainIsValid(n, bitmap->name,
- blockNamedNodeData))) {
- ignore_value(virHashAddEntry(bitmaps_skip, bitmap->name, NULL));
- continue;
- }
-
- /* prepare the data for adding the bitmap to the mirror */
- tmp = virJSONValueNewArray();
-
- if (qemuMonitorTransactionBitmapAdd(tmp,
- mirror->nodeformat,
- bitmap->name,
- true,
- disabled,
- bitmap->granularity) < 0)
- return -1;
-
- if (virHashAddEntry(bitmaps, bitmap->name, tmp) < 0)
- return -1;
-
- tmp = NULL;
-
- /* prepare array for merging all the bitmaps from the original chain */
- tmp = virJSONValueNewArray();
+ virStorageSourcePtr base = NULL;
- if (virHashAddEntry(bitmaps_merge, bitmap->name, tmp) < 0)
- return -1;
+ if (shallow)
+ base = src->backingStore;
- bitmap_merge = g_steal_pointer(&tmp);
- }
-
- if (qemuMonitorTransactionBitmapMergeSourceAddBitmap(bitmap_merge,
- n->nodeformat,
- bitmap->name) <
0)
- return -1;
- }
-
- if (shallow)
- break;
- }
-
- if (virHashForEach(bitmaps, qemuBlockBitmapsHandleBlockcopyConcatActions,
- &data) < 0)
+ if (qemuBlockGetBitmapMergeActions(src, base, mirror, NULL, NULL, mirror, actions,
+ allocationbitmapnodes, blockNamedNodeData) <
0)
return -1;
- if (data.has_bitmaps)
- *actions = g_steal_pointer(&tmpactions);
-
return 0;
}
diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h
index 5d98f7ce6b..36091e44fa 100644
--- a/src/qemu/qemu_block.h
+++ b/src/qemu/qemu_block.h
@@ -242,7 +242,8 @@ qemuBlockBitmapsHandleBlockcopy(virStorageSourcePtr src,
virStorageSourcePtr mirror,
virHashTablePtr blockNamedNodeData,
bool shallow,
- virJSONValuePtr *actions);
+ virJSONValuePtr *actions,
+ GSList **allocationbitmapnodes);
int
qemuBlockBitmapsHandleCommitFinish(virStorageSourcePtr topsrc,
diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
index 801d88a9fb..126a808e20 100644
--- a/src/qemu/qemu_blockjob.c
+++ b/src/qemu/qemu_blockjob.c
@@ -1323,6 +1323,49 @@ qemuBlockJobProcessEventCompletedActiveCommit(virQEMUDriverPtr
driver,
}
+static int
+qemuBlockJobProcessEventCompletedCopyBitmaps(virDomainObjPtr vm,
+ qemuBlockJobDataPtr job,
+ qemuDomainAsyncJob asyncJob)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ g_autoptr(virHashTable) blockNamedNodeData = NULL;
+ g_autoptr(virJSONValue) actions = NULL;
+ g_autoptr(GSList) allocationbitmapnodes = NULL;
+ bool shallow = job->jobflags & VIR_DOMAIN_BLOCK_COPY_SHALLOW;
+
+ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_REOPEN))
+ return 0;
+
+ if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, asyncJob)))
+ return -1;
+
+ if (qemuBlockBitmapsHandleBlockcopy(job->disk->src,
+ job->disk->mirror,
+ blockNamedNodeData,
+ shallow,
+ &actions,
+ &allocationbitmapnodes) < 0)
+ return 0;
+
+ if (!actions)
+ return 0;
+
+ if (qemuBlockBitmapTemporaryAdd(vm, blockNamedNodeData,
+ &allocationbitmapnodes, asyncJob) < 0)
+ return -1;
+
+ if (qemuDomainObjEnterMonitorAsync(priv->driver, vm, asyncJob) < 0)
+ return -1;
+
+ qemuMonitorTransaction(priv->mon, &actions);
+
+ if (qemuDomainObjExitMonitor(priv->driver, vm) < 0)
+ return -1;
+
+ return 0;
+}
+
static void
qemuBlockJobProcessEventConcludedCopyPivot(virQEMUDriverPtr driver,
virDomainObjPtr vm,
@@ -1337,6 +1380,8 @@ qemuBlockJobProcessEventConcludedCopyPivot(virQEMUDriverPtr driver,
!job->disk->mirror)
return;
+ qemuBlockJobProcessEventCompletedCopyBitmaps(vm, job, asyncJob);
+
/* for shallow copy without reusing external image the user can either not
* specify the backing chain in which case libvirt will open and use the
* chain the user provided or not specify a chain in which case we'll
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 516be76b8f..8a677f925d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -17274,14 +17274,15 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
if (blockdev && !job->jobflagsmissing) {
bool shallow = job->jobflags & VIR_DOMAIN_BLOCK_COPY_SHALLOW;
bool reuse = job->jobflags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT;
- g_autoptr(virHashTable) blockNamedNodeData = NULL;
- if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm,
QEMU_ASYNC_JOB_NONE)))
- return -1;
+ actions = virJSONValueNewArray();
- if (qemuBlockBitmapsHandleBlockcopy(disk->src, disk->mirror,
- blockNamedNodeData,
- shallow, &actions) < 0)
+ if (qemuMonitorTransactionBitmapAdd(actions,
+ disk->mirror->nodeformat,
+ "libvirt-tmp-activewrite",
+ false,
+ false,
+ 0) < 0)
return -1;
/* Open and install the backing chain of 'mirror' late if we can use
diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
index 8706f1a5ec..91796e96d8 100644
--- a/tests/qemublocktest.c
+++ b/tests/qemublocktest.c
@@ -885,6 +885,8 @@ testQemuBlockBitmapBlockcopy(const void *opaque)
g_autoptr(virJSONValue) nodedatajson = NULL;
g_autoptr(virHashTable) nodedata = NULL;
g_autoptr(virStorageSource) fakemirror = virStorageSourceNew();
+ g_autoptr(GSList) allocationbitmapnodes = NULL;
+ g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
if (!fakemirror)
return -1;
@@ -904,13 +906,19 @@ testQemuBlockBitmapBlockcopy(const void *opaque)
}
if (qemuBlockBitmapsHandleBlockcopy(data->chain, fakemirror, nodedata,
- data->shallow, &actions) < 0)
+ data->shallow, &actions,
+ &allocationbitmapnodes) < 0)
return -1;
+
if (actions &&
- !(actual = virJSONValueToString(actions, true)))
+ virJSONValueToBuffer(actions, &buf, true) < 0)
return -1;
+ testQemuBitmapListPrint("allocation bitmap:", allocationbitmapnodes,
&buf);
+
+ actual = virBufferContentAndReset(&buf);
+
return virTestCompareToFile(actual, expectpath);
}
--
2.26.2