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