conf: store mirroring information in virStorageSource

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@redhat.com>
This commit is contained in:
Eric Blake 2014-05-21 14:22:21 -06:00
parent c123ef7104
commit 7b7bf00110
5 changed files with 78 additions and 60 deletions

View File

@ -1203,7 +1203,7 @@ virDomainDiskDefFree(virDomainDiskDefPtr def)
virStorageSourceFree(def->src);
VIR_FREE(def->serial);
VIR_FREE(def->dst);
VIR_FREE(def->mirror);
virStorageSourceFree(def->mirror);
VIR_FREE(def->wwn);
VIR_FREE(def->vendor);
VIR_FREE(def->product);
@ -5223,9 +5223,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;
@ -5374,19 +5371,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")) {
@ -5906,9 +5921,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;
@ -5930,16 +5942,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;
@ -5964,8 +5966,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);
@ -15160,10 +15160,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");

View File

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

View File

@ -887,8 +887,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) &&
@ -903,8 +903,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;
}
}
}

View File

@ -14864,13 +14864,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);
@ -14928,8 +14937,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;
@ -14937,7 +14946,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 ||
@ -14951,7 +14960,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) {
@ -14964,7 +14973,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
@ -14978,9 +14987,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:
@ -15106,8 +15115,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;
}
@ -15242,7 +15251,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 */
@ -15323,6 +15332,11 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
goto endjob;
}
if (VIR_ALLOC(mirror) < 0)
goto endjob;
/* XXX Allow non-file mirror destinations */
mirror->type = VIR_STORAGE_TYPE_FILE;
if (!(flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)) {
int fd = qemuOpenFile(driver, vm, dest, O_WRONLY | O_TRUNC | O_CREAT,
&need_unlink, NULL);
@ -15330,10 +15344,10 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
goto endjob;
VIR_FORCE_CLOSE(fd);
if (!format)
disk->mirrorFormat = disk->src->format;
mirror->format = disk->src->format;
} else if (format) {
disk->mirrorFormat = virStorageFileFormatTypeFromString(format);
if (disk->mirrorFormat <= 0) {
mirror->format = virStorageFileFormatTypeFromString(format);
if (mirror->format <= 0) {
virReportError(VIR_ERR_INVALID_ARG, _("unrecognized format '%s'"),
format);
goto endjob;
@ -15343,12 +15357,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);
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 && mirror->format > 0)
format = virStorageFileFormatTypeToString(mirror->format);
if (VIR_STRDUP(mirror->path, dest) < 0)
goto endjob;
if (qemuDomainPrepareDiskChainElementPath(driver, vm, disk, dest,
@ -15378,9 +15392,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;

View File

@ -1033,12 +1033,15 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT) &&
status == VIR_DOMAIN_BLOCK_JOB_COMPLETED)
qemuDomainDetermineDiskChain(driver, vm, disk, true);
if (disk->mirror && type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY &&
status == VIR_DOMAIN_BLOCK_JOB_READY)
disk->mirroring = true;
if (disk->mirror && type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY &&
status == VIR_DOMAIN_BLOCK_JOB_FAILED)
VIR_FREE(disk->mirror);
if (disk->mirror && type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY) {
if (status == VIR_DOMAIN_BLOCK_JOB_READY) {
disk->mirroring = true;
} else if (status == VIR_DOMAIN_BLOCK_JOB_FAILED) {
virStorageSourceFree(disk->mirror);
disk->mirror = NULL;
disk->mirroring = false;
}
}
}
virObjectUnlock(vm);