The current implementation of 'virsh blockcopy' (virDomainBlockRebase) is limited to copying to a local file name. But future patches want to extend it to also copy to network disks. This patch converts over to a virStorageSourcePtr, although it should have no semantic change visible to the user, in anticipation of those future patches being able to use more fields for non-file destinations. * src/conf/domain_conf.h (_virDomainDiskDef): Change type of mirror information. * src/conf/domain_conf.c (virDomainDiskDefParseXML): Localize mirror parsing into new object. (virDomainDiskDefFormat): Adjust clients. * src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse): Likewise. * src/qemu/qemu_driver.c (qemuDomainBlockPivot) (qemuDomainBlockJobImpl, qemuDomainBlockCopy): Likewise. Signed-off-by: Eric Blake <eblake@xxxxxxxxxx> --- src/conf/domain_conf.c | 50 +++++++++++++++++++++---------------------- src/conf/domain_conf.h | 3 +-- src/qemu/qemu_domain.c | 8 +++---- src/qemu/qemu_driver.c | 58 +++++++++++++++++++++++++++++++------------------- 4 files changed, 66 insertions(+), 53 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 45f2691..57142cb 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -5202,9 +5202,6 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, char *ioeventfd = NULL; char *event_idx = NULL; char *copy_on_read = NULL; - char *mirror = NULL; - char *mirrorFormat = NULL; - bool mirroring = false; char *devaddr = NULL; virStorageEncryptionPtr encryption = NULL; char *serial = NULL; @@ -5353,19 +5350,37 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, event_idx = virXMLPropString(cur, "event_idx"); copy_on_read = virXMLPropString(cur, "copy_on_read"); discard = virXMLPropString(cur, "discard"); - } else if (!mirror && xmlStrEqual(cur->name, BAD_CAST "mirror") && + } else if (!def->mirror && + xmlStrEqual(cur->name, BAD_CAST "mirror") && !(flags & VIR_DOMAIN_XML_INACTIVE)) { char *ready; - mirror = virXMLPropString(cur, "file"); - if (!mirror) { + char *mirrorFormat; + + if (VIR_ALLOC(def->mirror) < 0) + goto error; + def->mirror->type = VIR_STORAGE_TYPE_FILE; + def->mirror->path = virXMLPropString(cur, "file"); + if (!def->mirror->path) { virReportError(VIR_ERR_XML_ERROR, "%s", _("mirror requires file name")); goto error; } mirrorFormat = virXMLPropString(cur, "format"); + if (mirrorFormat) { + def->mirror->format = + virStorageFileFormatTypeFromString(mirrorFormat); + if (def->mirror->format <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown mirror format value '%s'"), + mirrorFormat); + VIR_FREE(mirrorFormat); + goto error; + } + VIR_FREE(mirrorFormat); + } ready = virXMLPropString(cur, "ready"); if (ready) { - mirroring = true; + def->mirroring = true; VIR_FREE(ready); } } else if (xmlStrEqual(cur->name, BAD_CAST "auth")) { @@ -5885,9 +5900,6 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, authUsername = NULL; def->src->driverName = driverName; driverName = NULL; - def->mirror = mirror; - mirror = NULL; - def->mirroring = mirroring; def->src->encryption = encryption; encryption = NULL; def->serial = serial; @@ -5909,16 +5921,6 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, } } - if (mirrorFormat) { - def->mirrorFormat = virStorageFileFormatTypeFromString(mirrorFormat); - if (def->mirrorFormat <= 0) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("unknown mirror format value '%s'"), - driverType); - goto error; - } - } - if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && virDomainDiskDefAssignAddress(xmlopt, def) < 0) goto error; @@ -5943,8 +5945,6 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, VIR_FREE(authUsage); VIR_FREE(driverType); VIR_FREE(driverName); - VIR_FREE(mirror); - VIR_FREE(mirrorFormat); VIR_FREE(cachetag); VIR_FREE(error_policy); VIR_FREE(rerror_policy); @@ -15136,10 +15136,10 @@ virDomainDiskDefFormat(virBufferPtr buf, * for live domains, therefore we ignore it on input except for * the internal parse on libvirtd restart. */ if (def->mirror && !(flags & VIR_DOMAIN_XML_INACTIVE)) { - virBufferEscapeString(buf, "<mirror file='%s'", def->mirror); - if (def->mirrorFormat) + virBufferEscapeString(buf, "<mirror file='%s'", def->mirror->path); + if (def->mirror->format) virBufferAsprintf(buf, " format='%s'", - virStorageFileFormatTypeToString(def->mirrorFormat)); + virStorageFileFormatTypeToString(def->mirror->format)); if (def->mirroring) virBufferAddLit(buf, " ready='yes'"); virBufferAddLit(buf, "/>\n"); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index f388865..ca145a6 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -606,8 +606,7 @@ struct _virDomainDiskDef { int tray_status; /* enum virDomainDiskTray */ int removable; /* enum virDomainFeatureState */ - char *mirror; - int mirrorFormat; /* virStorageFileFormat */ + virStorageSourcePtr mirror; bool mirroring; struct { diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 0cc8b9a..4b6de62 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -885,8 +885,8 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, /* default disk format for mirrored drive */ if (disk->mirror && - disk->mirrorFormat == VIR_STORAGE_FILE_NONE) - disk->mirrorFormat = VIR_STORAGE_FILE_AUTO; + disk->mirror->format == VIR_STORAGE_FILE_NONE) + disk->mirror->format = VIR_STORAGE_FILE_AUTO; } else { /* default driver if probing is forbidden */ if (!virDomainDiskGetDriver(disk) && @@ -901,8 +901,8 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, /* default disk format for mirrored drive */ if (disk->mirror && - disk->mirrorFormat == VIR_STORAGE_FILE_NONE) - disk->mirrorFormat = VIR_STORAGE_FILE_RAW; + disk->mirror->format == VIR_STORAGE_FILE_NONE) + disk->mirror->format = VIR_STORAGE_FILE_RAW; } } } diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0f946d1..4a9dee9 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -14789,13 +14789,22 @@ qemuDomainBlockPivot(virConnectPtr conn, int ret = -1, rc; qemuDomainObjPrivatePtr priv = vm->privateData; virDomainBlockJobInfo info; - const char *format = virStorageFileFormatTypeToString(disk->mirrorFormat); + const char *format = NULL; bool resume = false; char *oldsrc = NULL; int oldformat; virStorageSourcePtr oldchain = NULL; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); + if (!disk->mirror) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("pivot of disk '%s' requires an active copy job"), + disk->dst); + goto cleanup; + } + + format = virStorageFileFormatTypeToString(disk->mirror->format); + /* Probe the status, if needed. */ if (!disk->mirroring) { qemuDomainObjEnterMonitor(driver, vm); @@ -14853,8 +14862,8 @@ qemuDomainBlockPivot(virConnectPtr conn, oldsrc = disk->src->path; oldformat = disk->src->format; oldchain = disk->src->backingStore; - disk->src->path = disk->mirror; - disk->src->format = disk->mirrorFormat; + disk->src->path = disk->mirror->path; + disk->src->format = disk->mirror->format; disk->src->backingStore = NULL; if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0) { disk->src->path = oldsrc; @@ -14862,7 +14871,7 @@ qemuDomainBlockPivot(virConnectPtr conn, disk->src->backingStore = oldchain; goto cleanup; } - if (disk->mirrorFormat && disk->mirrorFormat != VIR_STORAGE_FILE_RAW && + if (disk->mirror->format && disk->mirror->format != VIR_STORAGE_FILE_RAW && (virDomainLockDiskAttach(driver->lockManager, cfg->uri, vm, disk) < 0 || qemuSetupDiskCgroup(vm, disk) < 0 || @@ -14876,7 +14885,7 @@ qemuDomainBlockPivot(virConnectPtr conn, /* Attempt the pivot. */ qemuDomainObjEnterMonitor(driver, vm); - ret = qemuMonitorDrivePivot(priv->mon, device, disk->mirror, format); + ret = qemuMonitorDrivePivot(priv->mon, device, disk->mirror->path, format); qemuDomainObjExitMonitor(driver, vm); if (ret == 0) { @@ -14889,7 +14898,7 @@ qemuDomainBlockPivot(virConnectPtr conn, * for now, we leak the access to the original. */ VIR_FREE(oldsrc); virStorageSourceFree(oldchain); - disk->mirror = NULL; + disk->mirror->path = NULL; } else { /* On failure, qemu abandons the mirror, and reverts back to * the source disk (RHEL 6.3 has a bug where the revert could @@ -14903,9 +14912,9 @@ qemuDomainBlockPivot(virConnectPtr conn, disk->src->format = oldformat; virStorageSourceFree(disk->src->backingStore); disk->src->backingStore = oldchain; - VIR_FREE(disk->mirror); } - disk->mirrorFormat = VIR_STORAGE_FILE_NONE; + virStorageSourceFree(disk->mirror); + disk->mirror = NULL; disk->mirroring = false; cleanup: @@ -15031,8 +15040,8 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm, if (mode == BLOCK_JOB_ABORT && disk->mirror) { /* XXX We should also revoke security labels and disk lease on * the mirror, and audit that fact, before dropping things. */ - VIR_FREE(disk->mirror); - disk->mirrorFormat = VIR_STORAGE_FILE_NONE; + virStorageSourceFree(disk->mirror); + disk->mirror = NULL; disk->mirroring = false; } @@ -15167,7 +15176,7 @@ qemuDomainBlockCopy(virDomainObjPtr vm, int idx; struct stat st; bool need_unlink = false; - char *mirror = NULL; + virStorageSourcePtr mirror = NULL; virQEMUDriverConfigPtr cfg = NULL; /* Preliminaries: find the disk we are editing, sanity checks */ @@ -15248,6 +15257,9 @@ qemuDomainBlockCopy(virDomainObjPtr vm, goto endjob; } + if (VIR_ALLOC(mirror) < 0) + goto endjob; + if (!(flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)) { int fd = qemuOpenFile(driver, vm, dest, O_WRONLY | O_TRUNC | O_CREAT, &need_unlink, NULL); @@ -15255,10 +15267,10 @@ qemuDomainBlockCopy(virDomainObjPtr vm, goto endjob; VIR_FORCE_CLOSE(fd); if (!format) - disk->mirrorFormat = disk->src->format; + disk->mirror->format = disk->src->format; } else if (format) { - disk->mirrorFormat = virStorageFileFormatTypeFromString(format); - if (disk->mirrorFormat <= 0) { + disk->mirror->format = virStorageFileFormatTypeFromString(format); + if (disk->mirror->format <= 0) { virReportError(VIR_ERR_INVALID_ARG, _("unrecognized format '%s'"), format); goto endjob; @@ -15268,12 +15280,12 @@ qemuDomainBlockCopy(virDomainObjPtr vm, * 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. */ - disk->mirrorFormat = virStorageFileProbeFormat(dest, cfg->user, - cfg->group); + disk->mirror->format = virStorageFileProbeFormat(dest, cfg->user, + cfg->group); } - if (!format && disk->mirrorFormat > 0) - format = virStorageFileFormatTypeToString(disk->mirrorFormat); - if (VIR_STRDUP(mirror, dest) < 0) + if (!format && disk->mirror->format > 0) + format = virStorageFileFormatTypeToString(disk->mirror->format); + if (VIR_STRDUP(mirror->path, dest) < 0) goto endjob; if (qemuDomainPrepareDiskChainElement(driver, vm, disk, dest, @@ -15303,9 +15315,11 @@ qemuDomainBlockCopy(virDomainObjPtr vm, endjob: if (need_unlink && unlink(dest)) VIR_WARN("unable to unlink just-created %s", dest); - if (ret < 0 && disk) - disk->mirrorFormat = VIR_STORAGE_FILE_NONE; - VIR_FREE(mirror); + if (ret < 0 && disk) { + virStorageSourceFree(disk->mirror); + disk->mirror = NULL; + } + virStorageSourceFree(mirror); if (!qemuDomainObjEndJob(driver, vm)) vm = NULL; -- 1.9.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list