On start of the commit job, we need to disable any active bitmap in the
base. Use qemuBlockBitmapsHandleCommitStart to calculate which and call
the appropriate QMP APIs. We use blockdev-reopen to make the 'base'
writable to disable the bitmaps.
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
src/qemu/qemu_driver.c | 43 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 31c0f2dd91..628fe9b107 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -18399,6 +18399,8 @@ qemuDomainBlockCommit(virDomainPtr dom,
const char *nodebase = NULL;
bool persistjob = false;
bool blockdev = false;
+ g_autoptr(virJSONValue) bitmapDisableActions = NULL;
+ VIR_AUTOSTRINGLIST bitmapDisableList = NULL;
virCheckFlags(VIR_DOMAIN_BLOCK_COMMIT_SHALLOW |
VIR_DOMAIN_BLOCK_COMMIT_ACTIVE |
@@ -18555,8 +18557,29 @@ qemuDomainBlockCommit(virDomainPtr dom,
goto endjob;
}
+ if (blockdev &&
+ virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_REOPEN)) {
+ g_autoptr(virHashTable) blockNamedNodeData = NULL;
+ if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, QEMU_ASYNC_JOB_NONE)))
+ goto endjob;
+
+ if (qemuBlockBitmapsHandleCommitStart(topSource, baseSource,
+ blockNamedNodeData,
+ &bitmapDisableActions,
+ &bitmapDisableList) < 0)
+ goto endjob;
+
+ /* if we don't have terminator on 'base' we can't reopen it */
+ if (bitmapDisableActions && !baseSource->backingStore) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+ _("can't handle bitmaps on unterminated backing image
'%s'"),
+ base);
+ goto endjob;
+ }
+ }
+
if (!(job = qemuBlockJobDiskNewCommit(vm, disk, top_parent, topSource,
- baseSource, NULL,
+ baseSource, &bitmapDisableList,
flags & VIR_DOMAIN_BLOCK_COMMIT_DELETE,
flags)))
goto endjob;
@@ -18578,6 +18601,24 @@ qemuDomainBlockCommit(virDomainPtr dom,
if (!backingPath && top_parent &&
!(backingPath = qemuBlockGetBackingStoreString(baseSource)))
goto endjob;
+
+ if (bitmapDisableActions) {
+ int rc;
+
+ if (qemuBlockReopenReadWrite(vm, baseSource, QEMU_ASYNC_JOB_NONE) < 0)
+ goto endjob;
+
+ qemuDomainObjEnterMonitor(driver, vm);
+ rc = qemuMonitorTransaction(priv->mon, &bitmapDisableActions);
+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
+ goto endjob;
+
+ if (qemuBlockReopenReadOnly(vm, baseSource, QEMU_ASYNC_JOB_NONE) < 0)
+ goto endjob;
+
+ if (rc < 0)
+ goto endjob;
+ }
} else {
device = job->name;
}
--
2.24.1