Reuse qemuBlockGetBitmapMergeActions which allows to remove the ad-hoc implementatio of bitmap merging for block copy. Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx> --- 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