|
|
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 |
|