So far, only paths could be used to specify blockcommit's base and top images. However, this is not general enough as paths have limitations (most notably they can only work for file-based storage sources). This commit preserves the path-based interface but factors out the core of blockcommit implementation into a separate function that takes its base and top as virStorageSources. The path-based interface basically just converts the paths into virStorageSource just as it was done before and calls the virStorageSource-based implementation core. Signed-off-by: Pavel Mores <pmores@xxxxxxxxxx> --- src/qemu/qemu_driver.c | 108 +++++++++++++++++++++++++---------------- 1 file changed, 65 insertions(+), 43 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index b642b24fa2..09300c1e90 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -18441,25 +18441,27 @@ qemuDomainBlockPull(virDomainPtr dom, const char *path, unsigned long bandwidth, } static int -qemuDomainBlockCommitImpl(virDomainObjPtr vm, - virQEMUDriverPtr driver, - const char *path, - const char *base, - const char *top, - unsigned long bandwidth, - unsigned int flags) +qemuDomainBlockCommitCommon(virDomainObjPtr vm, + virQEMUDriverPtr driver, + virDomainDiskDefPtr disk, + virStorageSourcePtr baseSource, + virStorageSourcePtr topSource, + virStorageSourcePtr topParentSource, + unsigned long bandwidth, + unsigned int flags) { qemuDomainObjPrivatePtr priv = vm->privateData; const char *device = NULL; const char *jobname = NULL; int ret = -1; - virDomainDiskDefPtr disk = NULL; - virStorageSourcePtr topSource; - unsigned int topIndex = 0; - virStorageSourcePtr baseSource = NULL; - unsigned int baseIndex = 0; - virStorageSourcePtr top_parent = NULL; bool clean_access = false; + /* TODO the following 2 are just for error reporting. Originally these + * could have been either paths or indexed identifiers (like 'vda[1]'). + * Now the error reporting will always use paths instead of what the + * user originally specified. Find out if this is fine, find a solution + * if it isn't. */ + const char *path = disk->src->path; + const char *base = baseSource->path; g_autofree char *topPath = NULL; g_autofree char *basePath = NULL; g_autofree char *backingPath = NULL; @@ -18473,9 +18475,6 @@ qemuDomainBlockCommitImpl(virDomainObjPtr vm, g_autoptr(virJSONValue) bitmapDisableActions = NULL; VIR_AUTOSTRINGLIST bitmapDisableList = NULL; - if (virDomainObjCheckActive(vm) < 0) - goto endjob; - blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV); /* Convert bandwidth MiB to bytes, if necessary */ @@ -18489,9 +18488,6 @@ qemuDomainBlockCommitImpl(virDomainObjPtr vm, speed <<= 20; } - if (!(disk = qemuDomainDiskByName(vm->def, path))) - goto endjob; - if (virStorageSourceIsEmpty(disk->src)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("disk %s has no source file to be committed"), @@ -18511,14 +18507,6 @@ qemuDomainBlockCommitImpl(virDomainObjPtr vm, goto endjob; } - if (!top || STREQ(top, disk->dst)) - topSource = disk->src; - else if (virStorageFileParseChainIndex(disk->dst, top, &topIndex) < 0 || - !(topSource = virStorageFileChainLookup(disk->src, NULL, - top, topIndex, - &top_parent))) - goto endjob; - if (topSource == disk->src) { if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_ACTIVE_COMMIT)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -18546,13 +18534,6 @@ qemuDomainBlockCommitImpl(virDomainObjPtr vm, goto endjob; } - if (!base && (flags & VIR_DOMAIN_BLOCK_COMMIT_SHALLOW)) - baseSource = topSource->backingStore; - else if (virStorageFileParseChainIndex(disk->dst, base, &baseIndex) < 0 || - !(baseSource = virStorageFileChainLookup(disk->src, topSource, - base, baseIndex, NULL))) - goto endjob; - if ((flags & VIR_DOMAIN_BLOCK_COMMIT_SHALLOW) && baseSource != topSource->backingStore) { virReportError(VIR_ERR_INVALID_ARG, @@ -18580,8 +18561,8 @@ qemuDomainBlockCommitImpl(virDomainObjPtr vm, goto endjob; } - if (blockdev && top_parent && - qemuBlockUpdateRelativeBacking(vm, top_parent, disk->src) < 0) + if (blockdev && topParentSource && + qemuBlockUpdateRelativeBacking(vm, topParentSource, disk->src) < 0) goto endjob; if (virStorageFileGetRelativeBackingPath(topSource, baseSource, @@ -18607,11 +18588,11 @@ qemuDomainBlockCommitImpl(virDomainObjPtr vm, false, false, false) < 0) goto endjob; - if (top_parent && top_parent != disk->src) { - /* While top_parent is topmost image, we don't need to remember its + if (topParentSource && topParentSource != disk->src) { + /* While topParentSource is topmost image, we don't need to remember its * owner as it will be overwritten upon finishing the commit. Hence, * pass chainTop = false. */ - if (qemuDomainStorageSourceAccessAllow(driver, vm, top_parent, + if (qemuDomainStorageSourceAccessAllow(driver, vm, topParentSource, false, false, false) < 0) goto endjob; } @@ -18637,7 +18618,7 @@ qemuDomainBlockCommitImpl(virDomainObjPtr vm, } } - if (!(job = qemuBlockJobDiskNewCommit(vm, disk, top_parent, topSource, + if (!(job = qemuBlockJobDiskNewCommit(vm, disk, topParentSource, topSource, baseSource, &bitmapDisableList, flags & VIR_DOMAIN_BLOCK_COMMIT_DELETE, flags))) @@ -18657,7 +18638,7 @@ qemuDomainBlockCommitImpl(virDomainObjPtr vm, nodetop = topSource->nodeformat; nodebase = baseSource->nodeformat; device = qemuDomainDiskGetTopNodename(disk); - if (!backingPath && top_parent && + if (!backingPath && topParentSource && !(backingPath = qemuBlockGetBackingStoreString(baseSource, false))) goto endjob; @@ -18714,8 +18695,8 @@ qemuDomainBlockCommitImpl(virDomainObjPtr vm, /* Revert access to read-only, if possible. */ qemuDomainStorageSourceAccessAllow(driver, vm, baseSource, true, false, false); - if (top_parent && top_parent != disk->src) - qemuDomainStorageSourceAccessAllow(driver, vm, top_parent, + if (topParentSource && topParentSource != disk->src) + qemuDomainStorageSourceAccessAllow(driver, vm, topParentSource, true, false, false); virErrorRestore(&orig_err); @@ -18725,6 +18706,47 @@ qemuDomainBlockCommitImpl(virDomainObjPtr vm, return ret; } +static int +qemuDomainBlockCommitImpl(virDomainObjPtr vm, + virQEMUDriverPtr driver, + const char *path, + const char *base, + const char *top, + unsigned long bandwidth, + unsigned int flags) +{ + virDomainDiskDefPtr disk = NULL; + virStorageSourcePtr topSource; + unsigned int topIndex = 0; + virStorageSourcePtr baseSource = NULL; + unsigned int baseIndex = 0; + virStorageSourcePtr top_parent = NULL; + + if (virDomainObjCheckActive(vm) < 0) + return -1; + + if (!(disk = qemuDomainDiskByName(vm->def, path))) + return -1; + + if (!top || STREQ(top, disk->dst)) + topSource = disk->src; + else if (virStorageFileParseChainIndex(disk->dst, top, &topIndex) < 0 || + !(topSource = virStorageFileChainLookup(disk->src, NULL, + top, topIndex, + &top_parent))) + return -1; + + if (!base && (flags & VIR_DOMAIN_BLOCK_COMMIT_SHALLOW)) + baseSource = topSource->backingStore; + else if (virStorageFileParseChainIndex(disk->dst, base, &baseIndex) < 0 || + !(baseSource = virStorageFileChainLookup(disk->src, topSource, + base, baseIndex, NULL))) + return -1; + + return qemuDomainBlockCommitCommon(vm, driver, disk, baseSource, topSource, + top_parent, bandwidth, flags); +} + static int qemuDomainBlockCommit(virDomainPtr dom, -- 2.24.1