[libvirt] [PATCH v3 14/18] blockcopy: tweak how rebase calls into copy
Peter Krempa
pkrempa at redhat.com
Fri Sep 5 14:09:57 UTC 2014
On 08/31/14 06:02, Eric Blake wrote:
> In order to implement the new virDomainBlockCopy, the existing
> block copy internal implementation needs to be adjusted. The
> new function will parse XML into a storage source, and parse
> typed parameters into integers, then call into the same common
> backend. For now, it's easier to keep the same implementation
> limits that only local file destinations are suported, but now
> the check needs to be explicit.
>
> * src/qemu/qemu_driver.c (qemuDomainBlockCopy): Rename...
> (qemuDomainBlockCopyCommon): ...and adjust parameters.
> (qemuDomainBlockRebase): Adjust caller.
>
> Signed-off-by: Eric Blake <eblake at redhat.com>
> ---
> src/qemu/qemu_driver.c | 108 ++++++++++++++++++++++++++-----------------------
> 1 file changed, 58 insertions(+), 50 deletions(-)
>
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 946c384..d3f1042 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -15351,11 +15351,12 @@ qemuDomainBlockJobSetSpeed(virDomainPtr dom, const char *path,
>
> /* bandwidth in bytes/s */
> static int
> -qemuDomainBlockCopy(virDomainObjPtr vm,
> - virConnectPtr conn,
> - const char *path,
> - const char *dest, const char *format,
> - unsigned long long bandwidth, unsigned int flags)
You should mention that this function consumes @dest.
> +qemuDomainBlockCopyCommon(virDomainObjPtr vm,
> + virConnectPtr conn,
> + const char *path,
> + virStorageSourcePtr dest,
> + unsigned long long bandwidth,
> + unsigned int flags)
> {
> virQEMUDriverPtr driver = conn->privateData;
> qemuDomainObjPrivatePtr priv;
> @@ -15367,11 +15368,12 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
> bool need_unlink = false;
> virStorageSourcePtr mirror = NULL;
> virQEMUDriverConfigPtr cfg = NULL;
> + const char *format = NULL;
> + int desttype = virStorageSourceGetActualType(dest);
>
> /* Preliminaries: find the disk we are editing, sanity checks */
> - virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
> - VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT |
> - VIR_DOMAIN_BLOCK_REBASE_COPY_DEV, -1);
> + virCheckFlags(VIR_DOMAIN_BLOCK_COPY_SHALLOW |
> + VIR_DOMAIN_BLOCK_COPY_REUSE_EXT, -1);
>
> priv = vm->privateData;
> cfg = virQEMUDriverGetConfig(driver);
> @@ -15416,8 +15418,8 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
> if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0)
> goto endjob;
>
> - if ((flags & VIR_DOMAIN_BLOCK_REBASE_SHALLOW) &&
> - STREQ_NULLABLE(format, "raw") &&
> + if ((flags & VIR_DOMAIN_BLOCK_COPY_SHALLOW) &&
> + dest->format == VIR_STORAGE_FILE_RAW &&
> disk->src->backingStore->path) {
> virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> _("disk '%s' has backing file, so raw shallow copy "
> @@ -15427,72 +15429,68 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
> }
>
> /* Prepare the destination file. */
> - if (stat(dest, &st) < 0) {
> + /* XXX Allow non-file mirror destinations */
> + if (!virStorageSourceIsLocalStorage(dest)) {
> + virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
> + _("non-file destination not supported yet"));
> + }
> + if (stat(dest->path, &st) < 0) {
> if (errno != ENOENT) {
> virReportSystemError(errno, _("unable to stat for disk %s: %s"),
> - disk->dst, dest);
> + disk->dst, dest->path);
> goto endjob;
> - } else if (flags & (VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT |
> - VIR_DOMAIN_BLOCK_REBASE_COPY_DEV)) {
> + } else if (flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT ||
> + desttype == VIR_STORAGE_TYPE_BLOCK) {
> virReportSystemError(errno,
> _("missing destination file for disk %s: %s"),
> - disk->dst, dest);
> + disk->dst, dest->path);
> goto endjob;
> }
> } else if (!S_ISBLK(st.st_mode)) {
> - if (st.st_size && !(flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)) {
> + if (st.st_size && !(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT)) {
> virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> _("external destination file for disk %s already "
> "exists and is not a block device: %s"),
> - disk->dst, dest);
> + disk->dst, dest->path);
> goto endjob;
> }
> - if (flags & VIR_DOMAIN_BLOCK_REBASE_COPY_DEV) {
> + if (desttype == VIR_STORAGE_TYPE_BLOCK) {
> virReportError(VIR_ERR_INVALID_ARG,
> _("blockdev flag requested for disk %s, but file "
> - "'%s' is not a block device"), disk->dst, dest);
> + "'%s' is not a block device"),
> + disk->dst, dest->path);
> goto endjob;
> }
> }
>
> - if (VIR_ALLOC(mirror) < 0)
> + if (!(mirror = virStorageSourceCopy(dest, false)))
Also you won't need to copy it then.
> goto endjob;
> - /* XXX Allow non-file mirror destinations */
> - mirror->type = flags & VIR_DOMAIN_BLOCK_REBASE_COPY_DEV ?
> - VIR_STORAGE_TYPE_BLOCK : VIR_STORAGE_TYPE_FILE;
>
> - if (format) {
> - if ((mirror->format = virStorageFileFormatTypeFromString(format)) <= 0) {
> - virReportError(VIR_ERR_INVALID_ARG, _("unrecognized format '%s'"),
> - format);
> - goto endjob;
> - }
> - } else {
> - if (!(flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)) {
> + if (!dest->format) {
> + if (!(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT)) {
> mirror->format = disk->src->format;
> } else {
> /* If the user passed the REUSE_EXT flag, then either they
> - * also passed the RAW flag (and format is non-NULL), or it is
> - * safe for us to probe the format from the file that we will
> - * be using. */
> - mirror->format = virStorageFileProbeFormat(dest, cfg->user,
> + * can also pass the RAW flag or use XML to tell us the format.
> + * So if we get here, we assume it is safe for us to probe the
> + * format from the file that we will be using. */
> + mirror->format = virStorageFileProbeFormat(dest->path, cfg->user,
> cfg->group);
> }
> }
>
> /* pre-create the image file */
> - if (!(flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)) {
> - int fd = qemuOpenFile(driver, vm, dest, O_WRONLY | O_TRUNC | O_CREAT,
> + if (!(flags & VIR_DOMAIN_BLOCK_COPY_REUSE_EXT)) {
> + int fd = qemuOpenFile(driver, vm, dest->path,
> + O_WRONLY | O_TRUNC | O_CREAT,
> &need_unlink, NULL);
> if (fd < 0)
> goto endjob;
> VIR_FORCE_CLOSE(fd);
> }
>
> - if (!format && mirror->format > 0)
> + if (mirror->format > 0)
> format = virStorageFileFormatTypeToString(mirror->format);
> - if (VIR_STRDUP(mirror->path, dest) < 0)
> - goto endjob;
>
> if (virStorageSourceInitChainElement(mirror, disk->src, false) < 0)
> goto endjob;
> @@ -15506,8 +15504,8 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
>
> /* Actually start the mirroring */
> qemuDomainObjEnterMonitor(driver, vm);
> - ret = qemuMonitorDriveMirror(priv->mon, device, dest, format, bandwidth,
> - flags);
> + ret = qemuMonitorDriveMirror(priv->mon, device, dest->path, format,
> + bandwidth, flags);
> virDomainAuditDisk(vm, NULL, mirror, "mirror", ret >= 0);
> qemuDomainObjExitMonitor(driver, vm);
> if (ret < 0) {
> @@ -15527,8 +15525,8 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
> vm->def->name);
>
> endjob:
> - if (need_unlink && unlink(dest))
> - VIR_WARN("unable to unlink just-created %s", dest);
> + if (need_unlink && unlink(dest->path))
> + VIR_WARN("unable to unlink just-created %s", dest->path);
> virStorageSourceFree(mirror);
> if (!qemuDomainObjEndJob(driver, vm))
> vm = NULL;
> @@ -15546,9 +15544,9 @@ qemuDomainBlockRebase(virDomainPtr dom, const char *path, const char *base,
> unsigned long bandwidth, unsigned int flags)
> {
> virDomainObjPtr vm;
> - const char *format = NULL;
> int ret = -1;
> unsigned long long speed = bandwidth;
> + virStorageSourcePtr dest = NULL;
>
> virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
> VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT |
> @@ -15570,8 +15568,14 @@ qemuDomainBlockRebase(virDomainPtr dom, const char *path, const char *base,
> BLOCK_JOB_PULL, flags);
>
> /* If we got here, we are doing a block copy rebase. */
> + if (VIR_ALLOC(dest) < 0)
> + goto cleanup;
> + dest->type = (flags & VIR_DOMAIN_BLOCK_REBASE_COPY_DEV) ?
> + VIR_STORAGE_TYPE_BLOCK : VIR_STORAGE_TYPE_FILE;
> + if (VIR_STRDUP(dest->path, base) < 0)
> + goto cleanup;
> if (flags & VIR_DOMAIN_BLOCK_REBASE_COPY_RAW)
> - format = "raw";
> + dest->format = VIR_STORAGE_FILE_RAW;
>
> /* Convert bandwidth MiB to bytes */
> if (speed > LLONG_MAX >> 20) {
> @@ -15591,15 +15595,19 @@ qemuDomainBlockRebase(virDomainPtr dom, const char *path, const char *base,
> goto cleanup;
> }
>
> + /* We rely on the fact that VIR_DOMAIN_BLOCK_REBASE_SHALLOW
> + * and VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT map to the same values
> + * as for block copy. */
> flags &= (VIR_DOMAIN_BLOCK_REBASE_SHALLOW |
> - VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT |
> - VIR_DOMAIN_BLOCK_REBASE_COPY_DEV);
> - ret = qemuDomainBlockCopy(vm, dom->conn, path, base, format,
> - bandwidth, flags);
> + VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT);
> + ret = qemuDomainBlockCopyCommon(vm, dom->conn, path, dest,
> + bandwidth, flags);
> vm = NULL;
> +
> cleanup:
> if (vm)
> virObjectUnlock(vm);
> + virStorageSourceFree(dest);
If you don't free it afterwards.
> return ret;
> }
>
ACK with the docs added. The tweaks of the @dest handling are not necessary.
Peter
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20140905/2d8769e3/attachment-0001.sig>
More information about the libvir-list
mailing list