forked from rpms/libvirt
190 lines
7.0 KiB
Diff
190 lines
7.0 KiB
Diff
|
From 0890cd78e9391625a591a7a9327601ee79ba6636 Mon Sep 17 00:00:00 2001
|
||
|
Message-Id: <0890cd78e9391625a591a7a9327601ee79ba6636@dist-git>
|
||
|
From: Peter Krempa <pkrempa@redhat.com>
|
||
|
Date: Tue, 4 Feb 2020 15:08:25 +0100
|
||
|
Subject: [PATCH] qemu: block: Introduce function to calculate bitmap handling
|
||
|
for block-copy
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
Add a function calculating which bitmaps to copy to the mirror during
|
||
|
a block-copy operation.
|
||
|
|
||
|
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
||
|
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||
|
(cherry picked from commit 26f07f68707e16bef3d48e1c0b138791ab5df346)
|
||
|
|
||
|
https://bugzilla.redhat.com/show_bug.cgi?id=1207659
|
||
|
Message-Id: <6d4bd72b975f9f690cb34784ed22bb5fad6bbf2c.1580824112.git.pkrempa@redhat.com>
|
||
|
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
||
|
---
|
||
|
src/qemu/qemu_block.c | 138 ++++++++++++++++++++++++++++++++++++++++++
|
||
|
src/qemu/qemu_block.h | 7 +++
|
||
|
2 files changed, 145 insertions(+)
|
||
|
|
||
|
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
|
||
|
index b19290e677..63116ef5f2 100644
|
||
|
--- a/src/qemu/qemu_block.c
|
||
|
+++ b/src/qemu/qemu_block.c
|
||
|
@@ -2728,3 +2728,141 @@ qemuBlockBitmapChainIsValid(virStorageSourcePtr src,
|
||
|
|
||
|
return chain_started;
|
||
|
}
|
||
|
+
|
||
|
+
|
||
|
+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
|
||
|
+ * @mirror: mirror source
|
||
|
+ * @blockNamedNodeData: hash table containing data about bitmaps
|
||
|
+ * @shallow: whether shallow copy is requested
|
||
|
+ * @actions: filled with arguments for a 'transaction' command
|
||
|
+ *
|
||
|
+ * Calculates which bitmaps to copy and merge during a virDomainBlockCopy job.
|
||
|
+ * This is designed to be called when the job is already synchronised as it
|
||
|
+ * may result in active bitmaps being created.
|
||
|
+ *
|
||
|
+ * Returns 0 on success and -1 on error. If @actions is NULL when 0 is returned
|
||
|
+ * there are no actions to perform for the given job.
|
||
|
+ */
|
||
|
+int
|
||
|
+qemuBlockBitmapsHandleBlockcopy(virStorageSourcePtr src,
|
||
|
+ virStorageSourcePtr mirror,
|
||
|
+ virHashTablePtr blockNamedNodeData,
|
||
|
+ bool shallow,
|
||
|
+ virJSONValuePtr *actions)
|
||
|
+{
|
||
|
+ 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();
|
||
|
+
|
||
|
+ if (virHashAddEntry(bitmaps_merge, bitmap->name, tmp) < 0)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ 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)
|
||
|
+ 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 cf51b9bf4e..a816190bb7 100644
|
||
|
--- a/src/qemu/qemu_block.h
|
||
|
+++ b/src/qemu/qemu_block.h
|
||
|
@@ -217,3 +217,10 @@ bool
|
||
|
qemuBlockBitmapChainIsValid(virStorageSourcePtr src,
|
||
|
const char *bitmapname,
|
||
|
virHashTablePtr blockNamedNodeData);
|
||
|
+
|
||
|
+int
|
||
|
+qemuBlockBitmapsHandleBlockcopy(virStorageSourcePtr src,
|
||
|
+ virStorageSourcePtr mirror,
|
||
|
+ virHashTablePtr blockNamedNodeData,
|
||
|
+ bool shallow,
|
||
|
+ virJSONValuePtr *actions);
|
||
|
--
|
||
|
2.25.0
|
||
|
|