Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx> --- src/qemu/qemu_driver.c | 171 ++++++++++++++++------------------------- 1 file changed, 66 insertions(+), 105 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 811b4a610c..bae9558cfd 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -14943,8 +14943,7 @@ qemuDomainBlockCopyValidateMirror(virStorageSource *mirror, */ static int qemuDomainBlockCopyCommonValidateUserMirrorBackingStore(virStorageSource *mirror, - bool shallow, - bool blockdev) + bool shallow) { if (!virStorageSourceHasBacking(mirror)) { /* for deep copy there won't be backing chain so we can terminate it */ @@ -14960,12 +14959,6 @@ qemuDomainBlockCopyCommonValidateUserMirrorBackingStore(virStorageSource *mirror * For a copy when we are not reusing external image requesting shallow * is okay and will inherit the original backing chain */ } else { - if (!blockdev) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("backingStore of mirror target is not supported by this qemu")); - return -1; - } - if (!shallow) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("backingStore of mirror without VIR_DOMAIN_BLOCK_COPY_SHALLOW doesn't make sense")); @@ -15000,13 +14993,11 @@ qemuDomainBlockCopyCommon(virDomainObj *vm, bool need_unlink = false; bool need_revoke = false; g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(driver); - const char *format = NULL; bool mirror_reuse = !!(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT); bool mirror_shallow = !!(flags & VIR_DOMAIN_BLOCK_COPY_SHALLOW); bool existing = mirror_reuse; qemuBlockJobData *job = NULL; g_autoptr(virStorageSource) mirror = mirrorsrc; - bool blockdev = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV); bool supports_create = false; bool supports_access = false; bool supports_detect = false; @@ -15060,12 +15051,6 @@ qemuDomainBlockCopyCommon(virDomainObj *vm, virDomainDiskDefSourceLUNValidate(mirror) < 0) goto endjob; - if (syncWrites && !blockdev) { - virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", - _("VIR_DOMAIN_BLOCK_COPY_SYNCHRONOUS_WRITES is not supported by this VM")); - goto endjob; - } - if (!(flags & VIR_DOMAIN_BLOCK_COPY_TRANSIENT_JOB) && vm->persistent) { /* XXX if qemu ever lets us start a new domain with mirroring @@ -15084,8 +15069,7 @@ qemuDomainBlockCopyCommon(virDomainObj *vm, } if (qemuDomainBlockCopyCommonValidateUserMirrorBackingStore(mirror, - mirror_shallow, - blockdev) < 0) + mirror_shallow) < 0) goto endjob; /* unless the user provides a pre-created file, shallow copy into a raw @@ -15098,14 +15082,6 @@ qemuDomainBlockCopyCommon(virDomainObj *vm, goto endjob; } - /* Prepare the destination file. */ - if (!blockdev && - !virStorageSourceIsLocalStorage(mirror)) { - virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", - _("non-file destination not supported yet")); - goto endjob; - } - supports_access = virStorageSourceSupportsAccess(mirror) == 1; supports_create = virStorageSourceSupportsCreate(mirror) == 1; supports_detect = virStorageSourceSupportsBackingChainTraversal(mirror) == 1; @@ -15148,8 +15124,8 @@ qemuDomainBlockCopyCommon(virDomainObj *vm, goto endjob; } - /* pre-create the image file. In case when 'blockdev' is used this is - * required so that libvirt can properly label the image for access by qemu */ + /* pre-create the image file. This is required so that libvirt can properly + * label the image for access by qemu */ if (!existing) { if (supports_create) { if (virStorageSourceCreate(mirror) < 0) { @@ -15161,9 +15137,6 @@ qemuDomainBlockCopyCommon(virDomainObj *vm, } } - if (mirror->format > 0) - format = virStorageFileFormatTypeToString(mirror->format); - if (virStorageSourceInitChainElement(mirror, disk->src, keepParentLabel) < 0) goto endjob; @@ -15179,21 +15152,19 @@ qemuDomainBlockCopyCommon(virDomainObj *vm, /* we must initialize XML-provided chain prior to detecting to keep semantics * with VM startup */ - if (blockdev) { - for (n = mirror; virStorageSourceIsBacking(n); n = n->backingStore) { - if (qemuDomainPrepareStorageSourceBlockdev(disk, n, priv, cfg) < 0) - goto endjob; - } - - /* 'qemuDomainPrepareStorageSourceBlockdev' calls - * 'qemuDomainPrepareDiskSourceData' which propagates 'detect_zeroes' - * into the topmost virStorage source of the disk chain. - * Since 'mirror' has the ambition to replace it we need to propagate - * it into the mirror too. We do it directly as otherwise we'd need - * to modify all callers of 'qemuDomainPrepareStorageSourceBlockdev' */ - mirror->detect_zeroes = disk->detect_zeroes; + for (n = mirror; virStorageSourceIsBacking(n); n = n->backingStore) { + if (qemuDomainPrepareStorageSourceBlockdev(disk, n, priv, cfg) < 0) + goto endjob; } + /* 'qemuDomainPrepareStorageSourceBlockdev' calls + * 'qemuDomainPrepareDiskSourceData' which propagates 'detect_zeroes' + * into the topmost virStorage source of the disk chain. + * Since 'mirror' has the ambition to replace it we need to propagate + * it into the mirror too. We do it directly as otherwise we'd need + * to modify all callers of 'qemuDomainPrepareStorageSourceBlockdev' */ + mirror->detect_zeroes = disk->detect_zeroes; + /* If reusing an external image that includes a backing file but the user * did not enumerate the chain in the XML we need to detect the chain */ if (mirror_reuse && @@ -15206,67 +15177,65 @@ qemuDomainBlockCopyCommon(virDomainObj *vm, goto endjob; need_revoke = true; - if (blockdev) { - if (mirror_reuse) { - /* oVirt depended on late-backing-chain-opening semantics the old - * qemu command had to copy the backing chain data while the top - * level is being copied. To restore this semantics if - * blockdev-reopen is supported defer opening of the backing chain - * of 'mirror' to the pivot step */ - if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_SNAPSHOT_ALLOW_WRITE_ONLY)) { - g_autoptr(virStorageSource) terminator = virStorageSourceNew(); - - if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdevTop(mirror, - terminator))) - goto endjob; - } else { - if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdev(mirror))) - goto endjob; - } + if (mirror_reuse) { + /* oVirt depended on late-backing-chain-opening semantics the old + * qemu command had to copy the backing chain data while the top + * level is being copied. To restore this semantics if + * blockdev-reopen is supported defer opening of the backing chain + * of 'mirror' to the pivot step */ + if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKDEV_SNAPSHOT_ALLOW_WRITE_ONLY)) { + g_autoptr(virStorageSource) terminator = virStorageSourceNew(); + + if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdevTop(mirror, + terminator))) + goto endjob; } else { - if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, VIR_ASYNC_JOB_NONE))) + if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdev(mirror))) goto endjob; + } + } else { + if (!(blockNamedNodeData = qemuBlockGetNamedNodeData(vm, VIR_ASYNC_JOB_NONE))) + goto endjob; - if (qemuBlockStorageSourceCreateDetectSize(blockNamedNodeData, - mirror, disk->src)) - goto endjob; + if (qemuBlockStorageSourceCreateDetectSize(blockNamedNodeData, + mirror, disk->src)) + goto endjob; + + if (mirror_shallow) { + /* if external backing store is populated we'll need to open it */ + if (virStorageSourceHasBacking(mirror)) { + if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdev(mirror->backingStore))) + goto endjob; - if (mirror_shallow) { - /* if external backing store is populated we'll need to open it */ - if (virStorageSourceHasBacking(mirror)) { - if (!(data = qemuBuildStorageSourceChainAttachPrepareBlockdev(mirror->backingStore))) - goto endjob; - - mirrorBacking = mirror->backingStore; - } else { - /* backing store of original image will be reused, but the - * new image must refer to it in the metadata */ - mirrorBacking = disk->src->backingStore; - } - } else { mirrorBacking = mirror->backingStore; + } else { + /* backing store of original image will be reused, but the + * new image must refer to it in the metadata */ + mirrorBacking = disk->src->backingStore; } - - if (!(crdata = qemuBuildStorageSourceChainAttachPrepareBlockdevTop(mirror, - mirrorBacking))) - goto endjob; + } else { + mirrorBacking = mirror->backingStore; } - if (data) { - qemuDomainObjEnterMonitor(driver, vm); - rc = qemuBlockStorageSourceChainAttach(priv->mon, data); - qemuDomainObjExitMonitor(vm); + if (!(crdata = qemuBuildStorageSourceChainAttachPrepareBlockdevTop(mirror, + mirrorBacking))) + goto endjob; + } - if (rc < 0) - goto endjob; - } + if (data) { + qemuDomainObjEnterMonitor(driver, vm); + rc = qemuBlockStorageSourceChainAttach(priv->mon, data); + qemuDomainObjExitMonitor(vm); - if (crdata && - qemuBlockStorageSourceCreate(vm, mirror, mirrorBacking, mirror->backingStore, - crdata->srcdata[0], VIR_ASYNC_JOB_NONE) < 0) + if (rc < 0) goto endjob; } + if (crdata && + qemuBlockStorageSourceCreate(vm, mirror, mirrorBacking, mirror->backingStore, + crdata->srcdata[0], VIR_ASYNC_JOB_NONE) < 0) + goto endjob; + if (!(job = qemuBlockJobDiskNewCopy(vm, disk, mirror, mirror_shallow, mirror_reuse, flags))) goto endjob; @@ -15275,19 +15244,11 @@ qemuDomainBlockCopyCommon(virDomainObj *vm, /* Actually start the mirroring */ qemuDomainObjEnterMonitor(driver, vm); - if (blockdev) { - ret = qemuMonitorBlockdevMirror(priv->mon, job->name, true, - qemuDomainDiskGetTopNodename(disk), - mirror->nodeformat, bandwidth, - granularity, buf_size, mirror_shallow, - syncWrites); - } else { - /* qemuMonitorDriveMirror needs to honor the REUSE_EXT flag as specified - * by the user */ - ret = qemuMonitorDriveMirror(priv->mon, job->name, mirror->path, format, - bandwidth, granularity, buf_size, - mirror_shallow, mirror_reuse); - } + ret = qemuMonitorBlockdevMirror(priv->mon, job->name, true, + qemuDomainDiskGetTopNodename(disk), + mirror->nodeformat, bandwidth, + granularity, buf_size, mirror_shallow, + syncWrites); virDomainAuditDisk(vm, NULL, mirror, "mirror", ret >= 0); qemuDomainObjExitMonitor(vm); -- 2.36.1