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 | 44 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 43 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ef1314835e..85612f3281 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -18395,6 +18395,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 |
@@ -18543,8 +18545,30 @@ qemuDomainBlockCommit(virDomainPtr dom,
qemuDomainStorageSourceAccessAllow(driver, vm, top_parent, false, false) <
0))
goto endjob;
+ if (blockdev &&
+ virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_INCREMENTAL_BACKUP)) {
+ 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;
@@ -18566,6 +18590,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