[RFC PATCH 40/41] qemu: Rewrite bitmap handling for block copy

Peter Krempa pkrempa at redhat.com
Tue Jun 9 15:00:47 UTC 2020


Reuse qemuBlockGetBitmapMergeActions which allows to remove the ad-hoc
implementatio of bitmap merging for block copy.

Signed-off-by: Peter Krempa <pkrempa at 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




More information about the libvir-list mailing list