a41c76
From ae0be0a7cbfb291c640b25d31013f938745e8c08 Mon Sep 17 00:00:00 2001
a41c76
Message-Id: <ae0be0a7cbfb291c640b25d31013f938745e8c08@dist-git>
a41c76
From: Peter Krempa <pkrempa@redhat.com>
a41c76
Date: Tue, 23 Jun 2020 12:24:00 +0200
a41c76
Subject: [PATCH] qemu: Rewrite bitmap handling for block commit
a41c76
MIME-Version: 1.0
a41c76
Content-Type: text/plain; charset=UTF-8
a41c76
Content-Transfer-Encoding: 8bit
a41c76
a41c76
Reuse qemuBlockGetBitmapMergeActions which allows removing the ad-hoc
a41c76
implementation of bitmap merging for block commit. The new approach is
a41c76
way simpler and more robust and also allows us to get rid of the
a41c76
disabling of bitmaps done prior to the start as we actually do want to
a41c76
update the bitmaps in the base.
a41c76
a41c76
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
a41c76
Reviewed-by: Eric Blake <eblake@redhat.com>
a41c76
(cherry picked from commit 20a7abc2d2d8a378103abf105fa0c617218ec023)
a41c76
https://bugzilla.redhat.com/show_bug.cgi?id=1804593
a41c76
Message-Id: <2b1054dbe576d3984c960a42d175edbafa92565a.1592906423.git.pkrempa@redhat.com>
a41c76
Reviewed-by: Ján Tomko <jtomko@redhat.com>
a41c76
---
a41c76
 src/qemu/qemu_block.c                         | 203 +-----------------
a41c76
 src/qemu/qemu_block.h                         |  11 +-
a41c76
 src/qemu/qemu_blockjob.c                      |  25 ++-
a41c76
 src/qemu/qemu_driver.c                        |  56 +----
a41c76
 tests/qemublocktest.c                         |  18 +-
a41c76
 .../qemublocktestdata/bitmapblockcommit/empty |   1 -
a41c76
 6 files changed, 42 insertions(+), 272 deletions(-)
a41c76
a41c76
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
a41c76
index b2296c2b4c..ff9e000461 100644
a41c76
--- a/src/qemu/qemu_block.c
a41c76
+++ b/src/qemu/qemu_block.c
a41c76
@@ -3194,117 +3194,7 @@ qemuBlockBitmapsHandleBlockcopy(virStorageSourcePtr src,
a41c76
 /**
a41c76
  * @topsrc: virStorageSource representing 'top' of the job
a41c76
  * @basesrc: virStorageSource representing 'base' of the job
a41c76
- * @blockNamedNodeData: hash table containing data about bitmaps
a41c76
- * @actions: filled with arguments for a 'transaction' command
a41c76
- * @disabledBitmapsBase: filled with a list of bitmap names which must be disabled
a41c76
- *
a41c76
- * Prepares data for correctly handling bitmaps during the start of a commit
a41c76
- * job. The bitmaps in the 'base' image must be disabled, so that the writes
a41c76
- * done by the blockjob don't dirty the enabled bitmaps.
a41c76
- *
a41c76
- * @actions and @disabledBitmapsBase are untouched if no bitmaps need
a41c76
- * to be disabled.
a41c76
- */
a41c76
-int
a41c76
-qemuBlockBitmapsHandleCommitStart(virStorageSourcePtr topsrc,
a41c76
-                                  virStorageSourcePtr basesrc,
a41c76
-                                  virHashTablePtr blockNamedNodeData,
a41c76
-                                  virJSONValuePtr *actions,
a41c76
-                                  char ***disabledBitmapsBase)
a41c76
-{
a41c76
-    g_autoptr(virJSONValue) act = virJSONValueNewArray();
a41c76
-    VIR_AUTOSTRINGLIST bitmaplist = NULL;
a41c76
-    size_t curbitmapstr = 0;
a41c76
-    qemuBlockNamedNodeDataPtr entry;
a41c76
-    bool disable_bitmaps = false;
a41c76
-    size_t i;
a41c76
-
a41c76
-    if (!(entry = virHashLookup(blockNamedNodeData, basesrc->nodeformat)))
a41c76
-        return 0;
a41c76
-
a41c76
-    bitmaplist = g_new0(char *, entry->nbitmaps + 1);
a41c76
-
a41c76
-    for (i = 0; i < entry->nbitmaps; i++) {
a41c76
-        qemuBlockNamedNodeDataBitmapPtr bitmap = entry->bitmaps[i];
a41c76
-
a41c76
-        if (!bitmap->recording || bitmap->inconsistent ||
a41c76
-            !qemuBlockBitmapChainIsValid(topsrc, bitmap->name, blockNamedNodeData))
a41c76
-            continue;
a41c76
-
a41c76
-        disable_bitmaps = true;
a41c76
-
a41c76
-        if (qemuMonitorTransactionBitmapDisable(act, basesrc->nodeformat,
a41c76
-                                                bitmap->name) < 0)
a41c76
-            return -1;
a41c76
-
a41c76
-        bitmaplist[curbitmapstr++] = g_strdup(bitmap->name);
a41c76
-    }
a41c76
-
a41c76
-    if (disable_bitmaps) {
a41c76
-        *actions = g_steal_pointer(&act;;
a41c76
-        *disabledBitmapsBase = g_steal_pointer(&bitmaplist);
a41c76
-    }
a41c76
-
a41c76
-    return 0;
a41c76
-}
a41c76
-
a41c76
-
a41c76
-struct qemuBlockBitmapsHandleCommitData {
a41c76
-    bool skip;
a41c76
-    bool create;
a41c76
-    bool enable;
a41c76
-    const char *basenode;
a41c76
-    virJSONValuePtr merge;
a41c76
-    unsigned long long granularity;
a41c76
-    bool persistent;
a41c76
-};
a41c76
-
a41c76
-
a41c76
-static void
a41c76
-qemuBlockBitmapsHandleCommitDataFree(void *opaque)
a41c76
-{
a41c76
-    struct qemuBlockBitmapsHandleCommitData *data = opaque;
a41c76
-
a41c76
-    virJSONValueFree(data->merge);
a41c76
-    g_free(data);
a41c76
-}
a41c76
-
a41c76
-
a41c76
-static int
a41c76
-qemuBlockBitmapsHandleCommitFinishIterate(void *payload,
a41c76
-                                          const void *entryname,
a41c76
-                                          void *opaque)
a41c76
-{
a41c76
-    struct qemuBlockBitmapsHandleCommitData *data = payload;
a41c76
-    const char *bitmapname = entryname;
a41c76
-    virJSONValuePtr actions = opaque;
a41c76
-
a41c76
-    if (data->skip)
a41c76
-        return 0;
a41c76
-
a41c76
-    if (data->create) {
a41c76
-        if (qemuMonitorTransactionBitmapAdd(actions, data->basenode, bitmapname,
a41c76
-                                            data->persistent, !data->enable,
a41c76
-                                            data->granularity) < 0)
a41c76
-            return -1;
a41c76
-    } else {
a41c76
-        if (data->enable &&
a41c76
-            qemuMonitorTransactionBitmapEnable(actions, data->basenode, bitmapname) < 0)
a41c76
-            return -1;
a41c76
-    }
a41c76
-
a41c76
-    if (data->merge &&
a41c76
-        qemuMonitorTransactionBitmapMerge(actions, data->basenode, bitmapname,
a41c76
-                                          &data->merge) < 0)
a41c76
-        return -1;
a41c76
-
a41c76
-    return 0;
a41c76
-}
a41c76
-
a41c76
-
a41c76
-/**
a41c76
- * @topsrc: virStorageSource representing 'top' of the job
a41c76
- * @basesrc: virStorageSource representing 'base' of the job
a41c76
+ * @active: commit job is an active layer block-commit
a41c76
  * @blockNamedNodeData: hash table containing data about bitmaps
a41c76
  * @actions: filled with arguments for a 'transaction' command
a41c76
  * @disabledBitmapsBase: bitmap names which were disabled
a41c76
@@ -3317,95 +3207,20 @@ qemuBlockBitmapsHandleCommitFinishIterate(void *payload,
a41c76
 int
a41c76
 qemuBlockBitmapsHandleCommitFinish(virStorageSourcePtr topsrc,
a41c76
                                    virStorageSourcePtr basesrc,
a41c76
+                                   bool active,
a41c76
                                    virHashTablePtr blockNamedNodeData,
a41c76
-                                   virJSONValuePtr *actions,
a41c76
-                                   char **disabledBitmapsBase)
a41c76
+                                   virJSONValuePtr *actions)
a41c76
 {
a41c76
-    g_autoptr(virJSONValue) act = virJSONValueNewArray();
a41c76
-    virStorageSourcePtr n;
a41c76
-    qemuBlockNamedNodeDataPtr entry;
a41c76
-    g_autoptr(virHashTable) commitdata = NULL;
a41c76
-    struct qemuBlockBitmapsHandleCommitData *bitmapdata;
a41c76
-    size_t i;
a41c76
-
a41c76
-    commitdata = virHashNew(qemuBlockBitmapsHandleCommitDataFree);
a41c76
-
a41c76
-    for (n = topsrc; n != basesrc; n = n->backingStore) {
a41c76
-        if (!(entry = virHashLookup(blockNamedNodeData, n->nodeformat)))
a41c76
-            continue;
a41c76
-
a41c76
-        for (i = 0; i < entry->nbitmaps; i++) {
a41c76
-            qemuBlockNamedNodeDataBitmapPtr bitmap = entry->bitmaps[i];
a41c76
-
a41c76
-            if (!(bitmapdata = virHashLookup(commitdata, bitmap->name))) {
a41c76
-                bitmapdata = g_new0(struct qemuBlockBitmapsHandleCommitData, 1);
a41c76
+    virStorageSourcePtr writebitmapsrc = NULL;
a41c76
 
a41c76
-                /* we must mirror the state of the topmost bitmap and merge
a41c76
-                 * everything else */
a41c76
-                bitmapdata->create = true;
a41c76
-                bitmapdata->enable = bitmap->recording;
a41c76
-                bitmapdata->basenode = basesrc->nodeformat;
a41c76
-                bitmapdata->merge = virJSONValueNewArray();
a41c76
-                bitmapdata->granularity = bitmap->granularity;
a41c76
-                bitmapdata->persistent = bitmap->persistent;
a41c76
+    if (active)
a41c76
+        writebitmapsrc = basesrc;
a41c76
 
a41c76
-                if (virHashAddEntry(commitdata, bitmap->name, bitmapdata) < 0) {
a41c76
-                    qemuBlockBitmapsHandleCommitDataFree(bitmapdata);
a41c76
-                    return -1;
a41c76
-                }
a41c76
-            }
a41c76
-
a41c76
-            if (bitmap->inconsistent ||
a41c76
-                !qemuBlockBitmapChainIsValid(topsrc, bitmap->name, blockNamedNodeData))
a41c76
-                bitmapdata->skip = true;
a41c76
-
a41c76
-            if (qemuMonitorTransactionBitmapMergeSourceAddBitmap(bitmapdata->merge,
a41c76
-                                                                 n->nodeformat,
a41c76
-                                                                 bitmap->name) < 0)
a41c76
-                return -1;
a41c76
-        }
a41c76
-    }
a41c76
-
a41c76
-    if ((entry = virHashLookup(blockNamedNodeData, basesrc->nodeformat))) {
a41c76
-        /* note that all bitmaps in 'base' were disabled when commit was started */
a41c76
-        for (i = 0; i < entry->nbitmaps; i++) {
a41c76
-            qemuBlockNamedNodeDataBitmapPtr bitmap = entry->bitmaps[i];
a41c76
-
a41c76
-            if ((bitmapdata = virHashLookup(commitdata, bitmap->name))) {
a41c76
-                bitmapdata->create = false;
a41c76
-            } else {
a41c76
-                if (disabledBitmapsBase) {
a41c76
-                    char **disabledbitmaps;
a41c76
-
a41c76
-                    for (disabledbitmaps = disabledBitmapsBase; *disabledbitmaps; disabledbitmaps++) {
a41c76
-                        if (STREQ(*disabledbitmaps, bitmap->name)) {
a41c76
-                            bitmapdata = g_new0(struct qemuBlockBitmapsHandleCommitData, 1);
a41c76
-
a41c76
-                            bitmapdata->create = false;
a41c76
-                            bitmapdata->enable = true;
a41c76
-                            bitmapdata->basenode = basesrc->nodeformat;
a41c76
-                            bitmapdata->granularity = bitmap->granularity;
a41c76
-                            bitmapdata->persistent = bitmap->persistent;
a41c76
-
a41c76
-                            if (virHashAddEntry(commitdata, bitmap->name, bitmapdata) < 0) {
a41c76
-                                qemuBlockBitmapsHandleCommitDataFree(bitmapdata);
a41c76
-                                return -1;
a41c76
-                            }
a41c76
-
a41c76
-                            break;
a41c76
-                        }
a41c76
-                    }
a41c76
-                }
a41c76
-            }
a41c76
-        }
a41c76
-    }
a41c76
-
a41c76
-    if (virHashForEach(commitdata, qemuBlockBitmapsHandleCommitFinishIterate, act) < 0)
a41c76
+    if (qemuBlockGetBitmapMergeActions(topsrc, basesrc, basesrc, NULL, NULL,
a41c76
+                                       writebitmapsrc, actions,
a41c76
+                                       blockNamedNodeData) < 0)
a41c76
         return -1;
a41c76
 
a41c76
-    if (virJSONValueArraySize(act) > 0)
a41c76
-        *actions = g_steal_pointer(&act;;
a41c76
-
a41c76
     return 0;
a41c76
 }
a41c76
 
a41c76
diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h
a41c76
index 2500390734..19d2fc32e0 100644
a41c76
--- a/src/qemu/qemu_block.h
a41c76
+++ b/src/qemu/qemu_block.h
a41c76
@@ -243,19 +243,12 @@ qemuBlockBitmapsHandleBlockcopy(virStorageSourcePtr src,
a41c76
                                 bool shallow,
a41c76
                                 virJSONValuePtr *actions);
a41c76
 
a41c76
-int
a41c76
-qemuBlockBitmapsHandleCommitStart(virStorageSourcePtr topsrc,
a41c76
-                                  virStorageSourcePtr basesrc,
a41c76
-                                  virHashTablePtr blockNamedNodeData,
a41c76
-                                  virJSONValuePtr *actions,
a41c76
-                                  char ***disabledBitmapsBase);
a41c76
-
a41c76
 int
a41c76
 qemuBlockBitmapsHandleCommitFinish(virStorageSourcePtr topsrc,
a41c76
                                    virStorageSourcePtr basesrc,
a41c76
+                                   bool active,
a41c76
                                    virHashTablePtr blockNamedNodeData,
a41c76
-                                   virJSONValuePtr *actions,
a41c76
-                                   char **disabledBitmapsBase);
a41c76
+                                   virJSONValuePtr *actions);
a41c76
 
a41c76
 int
a41c76
 qemuBlockReopenReadWrite(virDomainObjPtr vm,
a41c76
diff --git a/src/qemu/qemu_blockjob.c b/src/qemu/qemu_blockjob.c
a41c76
index c80c71295b..c63a691a0e 100644
a41c76
--- a/src/qemu/qemu_blockjob.c
a41c76
+++ b/src/qemu/qemu_blockjob.c
a41c76
@@ -1063,6 +1063,7 @@ qemuBlockJobProcessEventCompletedCommitBitmaps(virDomainObjPtr vm,
a41c76
     qemuDomainObjPrivatePtr priv = vm->privateData;
a41c76
     g_autoptr(virHashTable) blockNamedNodeData = NULL;
a41c76
     g_autoptr(virJSONValue) actions = NULL;
a41c76
+    bool active = job->type == QEMU_BLOCKJOB_TYPE_ACTIVE_COMMIT;
a41c76
 
a41c76
     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_REOPEN))
a41c76
         return 0;
a41c76
@@ -1072,16 +1073,18 @@ qemuBlockJobProcessEventCompletedCommitBitmaps(virDomainObjPtr vm,
a41c76
 
a41c76
     if (qemuBlockBitmapsHandleCommitFinish(job->data.commit.top,
a41c76
                                            job->data.commit.base,
a41c76
+                                           active,
a41c76
                                            blockNamedNodeData,
a41c76
-                                           &actions,
a41c76
-                                           job->data.commit.disabledBitmapsBase) < 0)
a41c76
+                                           &actions) < 0)
a41c76
         return 0;
a41c76
 
a41c76
     if (!actions)
a41c76
         return 0;
a41c76
 
a41c76
-    if (qemuBlockReopenReadWrite(vm, job->data.commit.base, asyncJob) < 0)
a41c76
-        return -1;
a41c76
+    if (!active) {
a41c76
+        if (qemuBlockReopenReadWrite(vm, job->data.commit.base, asyncJob) < 0)
a41c76
+            return -1;
a41c76
+    }
a41c76
 
a41c76
     if (qemuDomainObjEnterMonitorAsync(priv->driver, vm, asyncJob) < 0)
a41c76
         return -1;
a41c76
@@ -1091,8 +1094,10 @@ qemuBlockJobProcessEventCompletedCommitBitmaps(virDomainObjPtr vm,
a41c76
     if (qemuDomainObjExitMonitor(priv->driver, vm) < 0)
a41c76
         return -1;
a41c76
 
a41c76
-    if (qemuBlockReopenReadOnly(vm, job->data.commit.base, asyncJob) < 0)
a41c76
-        return -1;
a41c76
+    if (!active) {
a41c76
+        if (qemuBlockReopenReadOnly(vm, job->data.commit.base, asyncJob) < 0)
a41c76
+            return -1;
a41c76
+    }
a41c76
 
a41c76
     return 0;
a41c76
 }
a41c76
@@ -1262,6 +1267,9 @@ qemuBlockJobProcessEventCompletedActiveCommit(virQEMUDriverPtr driver,
a41c76
     job->disk->src = job->data.commit.base;
a41c76
     job->disk->src->readonly = job->data.commit.top->readonly;
a41c76
 
a41c76
+    if (qemuBlockJobProcessEventCompletedCommitBitmaps(vm, job, asyncJob) < 0)
a41c76
+        return;
a41c76
+
a41c76
     qemuBlockJobEventProcessConcludedRemoveChain(driver, vm, asyncJob, job->data.commit.top);
a41c76
 
a41c76
     if (job->data.commit.deleteCommittedImages)
a41c76
@@ -1333,6 +1341,7 @@ qemuBlockJobProcessEventFailedActiveCommit(virQEMUDriverPtr driver,
a41c76
                                            virDomainObjPtr vm,
a41c76
                                            qemuBlockJobDataPtr job)
a41c76
 {
a41c76
+    g_autoptr(virJSONValue) actions = virJSONValueNewArray();
a41c76
     virDomainDiskDefPtr disk = job->disk;
a41c76
 
a41c76
     VIR_DEBUG("active commit job '%s' on VM '%s' failed", job->name, vm->def->name);
a41c76
@@ -1340,6 +1349,10 @@ qemuBlockJobProcessEventFailedActiveCommit(virQEMUDriverPtr driver,
a41c76
     if (!disk)
a41c76
         return;
a41c76
 
a41c76
+    ignore_value(qemuMonitorTransactionBitmapRemove(actions, disk->mirror->nodeformat,
a41c76
+                                                    "libvirt-tmp-activewrite"));
a41c76
+
a41c76
+
a41c76
     /* Ideally, we would make the backing chain read only again (yes, SELinux
a41c76
      * can do that using different labels). But that is not implemented yet and
a41c76
      * not leaking security driver metadata is more important. */
a41c76
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
a41c76
index 9f7d96c0b6..983d4a04a8 100644
a41c76
--- a/src/qemu/qemu_driver.c
a41c76
+++ b/src/qemu/qemu_driver.c
a41c76
@@ -17594,9 +17594,9 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
a41c76
 
a41c76
     case QEMU_BLOCKJOB_TYPE_COPY:
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
+            g_autoptr(virHashTable) blockNamedNodeData = NULL;
a41c76
 
a41c76
             if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, QEMU_ASYNC_JOB_NONE)))
a41c76
                 return -1;
a41c76
@@ -17634,16 +17634,15 @@ qemuDomainBlockPivot(virQEMUDriverPtr driver,
a41c76
          * the bitmaps if it wasn't present thus must skip this */
a41c76
         if (blockdev &&
a41c76
             virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_REOPEN)) {
a41c76
-            g_autoptr(virHashTable) blockNamedNodeData = NULL;
a41c76
 
a41c76
-            if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, QEMU_ASYNC_JOB_NONE)))
a41c76
-                return -1;
a41c76
+            actions = virJSONValueNewArray();
a41c76
 
a41c76
-            if (qemuBlockBitmapsHandleCommitFinish(job->data.commit.top,
a41c76
-                                                   job->data.commit.base,
a41c76
-                                                   blockNamedNodeData,
a41c76
-                                                   &actions,
a41c76
-                                                   job->data.commit.disabledBitmapsBase) < 0)
a41c76
+            if (qemuMonitorTransactionBitmapAdd(actions,
a41c76
+                                                job->data.commit.base->nodeformat,
a41c76
+                                                "libvirt-tmp-activewrite",
a41c76
+                                                false,
a41c76
+                                                false,
a41c76
+                                                0) < 0)
a41c76
                 return -1;
a41c76
         }
a41c76
 
a41c76
@@ -18758,7 +18757,6 @@ qemuDomainBlockCommit(virDomainPtr dom,
a41c76
     const char *nodebase = NULL;
a41c76
     bool persistjob = false;
a41c76
     bool blockdev = false;
a41c76
-    g_autoptr(virJSONValue) bitmapDisableActions = NULL;
a41c76
     VIR_AUTOSTRINGLIST bitmapDisableList = NULL;
a41c76
 
a41c76
     virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW |
a41c76
@@ -18920,27 +18918,6 @@ qemuDomainBlockCommit(virDomainPtr dom,
a41c76
             goto endjob;
a41c76
     }
a41c76
 
a41c76
-    if (blockdev &&
a41c76
-        virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_REOPEN)) {
a41c76
-        g_autoptr(virHashTable) blockNamedNodeData = NULL;
a41c76
-        if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, QEMU_ASYNC_JOB_NONE)))
a41c76
-            goto endjob;
a41c76
-
a41c76
-        if (qemuBlockBitmapsHandleCommitStart(topSource, baseSource,
a41c76
-                                              blockNamedNodeData,
a41c76
-                                              &bitmapDisableActions,
a41c76
-                                              &bitmapDisableList) < 0)
a41c76
-            goto endjob;
a41c76
-
a41c76
-        /* if we don't have terminator on 'base' we can't reopen it */
a41c76
-        if (bitmapDisableActions && !baseSource->backingStore) {
a41c76
-            virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
a41c76
-                           _("can't handle bitmaps on unterminated backing image '%s'"),
a41c76
-                           base);
a41c76
-            goto endjob;
a41c76
-        }
a41c76
-    }
a41c76
-
a41c76
     if (!(job = qemuBlockJobDiskNewCommit(vm, disk, top_parent, topSource,
a41c76
                                           baseSource, &bitmapDisableList,
a41c76
                                           flags & VIR_DOMAIN_BLOCK_COMMIT_DELETE,
a41c76
@@ -18965,23 +18942,6 @@ qemuDomainBlockCommit(virDomainPtr dom,
a41c76
             !(backingPath = qemuBlockGetBackingStoreString(baseSource, false)))
a41c76
             goto endjob;
a41c76
 
a41c76
-        if (bitmapDisableActions) {
a41c76
-            int rc;
a41c76
-
a41c76
-            if (qemuBlockReopenReadWrite(vm, baseSource, QEMU_ASYNC_JOB_NONE) < 0)
a41c76
-                goto endjob;
a41c76
-
a41c76
-            qemuDomainObjEnterMonitor(driver, vm);
a41c76
-            rc = qemuMonitorTransaction(priv->mon, &bitmapDisableActions);
a41c76
-            if (qemuDomainObjExitMonitor(driver, vm) < 0)
a41c76
-                goto endjob;
a41c76
-
a41c76
-            if (qemuBlockReopenReadOnly(vm, baseSource, QEMU_ASYNC_JOB_NONE) < 0)
a41c76
-                goto endjob;
a41c76
-
a41c76
-            if (rc < 0)
a41c76
-                goto endjob;
a41c76
-        }
a41c76
     } else {
a41c76
         device = job->name;
a41c76
     }
a41c76
diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c
a41c76
index 8ce878f15b..f0e80a0738 100644
a41c76
--- a/tests/qemublocktest.c
a41c76
+++ b/tests/qemublocktest.c
a41c76
@@ -928,12 +928,11 @@ testQemuBlockBitmapBlockcommit(const void *opaque)
a41c76
 
a41c76
     g_autofree char *actual = NULL;
a41c76
     g_autofree char *expectpath = NULL;
a41c76
-    g_autoptr(virJSONValue) actionsDisable = NULL;
a41c76
     g_autoptr(virJSONValue) actionsMerge = NULL;
a41c76
     g_autoptr(virJSONValue) nodedatajson = NULL;
a41c76
     g_autoptr(virHashTable) nodedata = NULL;
a41c76
     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
a41c76
-    VIR_AUTOSTRINGLIST bitmapsDisable = NULL;
a41c76
+    bool active = data->top == data->chain;
a41c76
 
a41c76
     expectpath = g_strdup_printf("%s/%s%s", abs_srcdir,
a41c76
                                  blockcommitPrefix, data->name);
a41c76
@@ -947,20 +946,10 @@ testQemuBlockBitmapBlockcommit(const void *opaque)
a41c76
         return -1;
a41c76
     }
a41c76
 
a41c76
-    if (qemuBlockBitmapsHandleCommitStart(data->top, data->base, nodedata,
a41c76
-                                          &actionsDisable, &bitmapsDisable) < 0)
a41c76
-        return -1;
a41c76
-
a41c76
-    virBufferAddLit(&buf, "pre job bitmap disable:\n");
a41c76
-
a41c76
-    if (actionsDisable &&
a41c76
-        virJSONValueToBuffer(actionsDisable, &buf, true) < 0)
a41c76
-        return -1;
a41c76
-
a41c76
     virBufferAddLit(&buf, "merge bitmpas:\n");
a41c76
 
a41c76
-    if (qemuBlockBitmapsHandleCommitFinish(data->top, data->base, nodedata,
a41c76
-                                           &actionsMerge, bitmapsDisable) < 0)
a41c76
+    if (qemuBlockBitmapsHandleCommitFinish(data->top, data->base, active, nodedata,
a41c76
+                                           &actionsMerge) < 0)
a41c76
         return -1;
a41c76
 
a41c76
     if (actionsMerge &&
a41c76
@@ -1356,6 +1345,7 @@ mymain(void)
a41c76
 #define TEST_BITMAP_BLOCKCOMMIT(testname, topimg, baseimg, ndf) \
a41c76
     do {\
a41c76
         blockbitmapblockcommitdata.name = testname; \
a41c76
+        blockbitmapblockcommitdata.chain = bitmapSourceChain; \
a41c76
         blockbitmapblockcommitdata.top = testQemuBitmapGetFakeChainEntry(bitmapSourceChain, topimg); \
a41c76
         blockbitmapblockcommitdata.base = testQemuBitmapGetFakeChainEntry(bitmapSourceChain, baseimg); \
a41c76
         blockbitmapblockcommitdata.nodedatafile = ndf; \
a41c76
diff --git a/tests/qemublocktestdata/bitmapblockcommit/empty b/tests/qemublocktestdata/bitmapblockcommit/empty
a41c76
index bfc58f994e..9260011852 100644
a41c76
--- a/tests/qemublocktestdata/bitmapblockcommit/empty
a41c76
+++ b/tests/qemublocktestdata/bitmapblockcommit/empty
a41c76
@@ -1,2 +1 @@
a41c76
-pre job bitmap disable:
a41c76
 merge bitmpas:
a41c76
-- 
a41c76
2.27.0
a41c76