mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-03 11:35:19 +00:00
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:
parent
c123ef7104
commit
7b7bf00110
@ -1203,7 +1203,7 @@ virDomainDiskDefFree(virDomainDiskDefPtr def)
|
|||||||
virStorageSourceFree(def->src);
|
virStorageSourceFree(def->src);
|
||||||
VIR_FREE(def->serial);
|
VIR_FREE(def->serial);
|
||||||
VIR_FREE(def->dst);
|
VIR_FREE(def->dst);
|
||||||
VIR_FREE(def->mirror);
|
virStorageSourceFree(def->mirror);
|
||||||
VIR_FREE(def->wwn);
|
VIR_FREE(def->wwn);
|
||||||
VIR_FREE(def->vendor);
|
VIR_FREE(def->vendor);
|
||||||
VIR_FREE(def->product);
|
VIR_FREE(def->product);
|
||||||
@ -5223,9 +5223,6 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
|
|||||||
char *ioeventfd = NULL;
|
char *ioeventfd = NULL;
|
||||||
char *event_idx = NULL;
|
char *event_idx = NULL;
|
||||||
char *copy_on_read = NULL;
|
char *copy_on_read = NULL;
|
||||||
char *mirror = NULL;
|
|
||||||
char *mirrorFormat = NULL;
|
|
||||||
bool mirroring = false;
|
|
||||||
char *devaddr = NULL;
|
char *devaddr = NULL;
|
||||||
virStorageEncryptionPtr encryption = NULL;
|
virStorageEncryptionPtr encryption = NULL;
|
||||||
char *serial = NULL;
|
char *serial = NULL;
|
||||||
@ -5374,19 +5371,37 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
|
|||||||
event_idx = virXMLPropString(cur, "event_idx");
|
event_idx = virXMLPropString(cur, "event_idx");
|
||||||
copy_on_read = virXMLPropString(cur, "copy_on_read");
|
copy_on_read = virXMLPropString(cur, "copy_on_read");
|
||||||
discard = virXMLPropString(cur, "discard");
|
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)) {
|
!(flags & VIR_DOMAIN_XML_INACTIVE)) {
|
||||||
char *ready;
|
char *ready;
|
||||||
mirror = virXMLPropString(cur, "file");
|
char *mirrorFormat;
|
||||||
if (!mirror) {
|
|
||||||
|
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",
|
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||||
_("mirror requires file name"));
|
_("mirror requires file name"));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
mirrorFormat = virXMLPropString(cur, "format");
|
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");
|
ready = virXMLPropString(cur, "ready");
|
||||||
if (ready) {
|
if (ready) {
|
||||||
mirroring = true;
|
def->mirroring = true;
|
||||||
VIR_FREE(ready);
|
VIR_FREE(ready);
|
||||||
}
|
}
|
||||||
} else if (xmlStrEqual(cur->name, BAD_CAST "auth")) {
|
} else if (xmlStrEqual(cur->name, BAD_CAST "auth")) {
|
||||||
@ -5906,9 +5921,6 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
|
|||||||
authUsername = NULL;
|
authUsername = NULL;
|
||||||
def->src->driverName = driverName;
|
def->src->driverName = driverName;
|
||||||
driverName = NULL;
|
driverName = NULL;
|
||||||
def->mirror = mirror;
|
|
||||||
mirror = NULL;
|
|
||||||
def->mirroring = mirroring;
|
|
||||||
def->src->encryption = encryption;
|
def->src->encryption = encryption;
|
||||||
encryption = NULL;
|
encryption = NULL;
|
||||||
def->serial = serial;
|
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
|
if (def->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE
|
||||||
&& virDomainDiskDefAssignAddress(xmlopt, def) < 0)
|
&& virDomainDiskDefAssignAddress(xmlopt, def) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
@ -5964,8 +5966,6 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
|
|||||||
VIR_FREE(authUsage);
|
VIR_FREE(authUsage);
|
||||||
VIR_FREE(driverType);
|
VIR_FREE(driverType);
|
||||||
VIR_FREE(driverName);
|
VIR_FREE(driverName);
|
||||||
VIR_FREE(mirror);
|
|
||||||
VIR_FREE(mirrorFormat);
|
|
||||||
VIR_FREE(cachetag);
|
VIR_FREE(cachetag);
|
||||||
VIR_FREE(error_policy);
|
VIR_FREE(error_policy);
|
||||||
VIR_FREE(rerror_policy);
|
VIR_FREE(rerror_policy);
|
||||||
@ -15160,10 +15160,10 @@ virDomainDiskDefFormat(virBufferPtr buf,
|
|||||||
* for live domains, therefore we ignore it on input except for
|
* for live domains, therefore we ignore it on input except for
|
||||||
* the internal parse on libvirtd restart. */
|
* the internal parse on libvirtd restart. */
|
||||||
if (def->mirror && !(flags & VIR_DOMAIN_XML_INACTIVE)) {
|
if (def->mirror && !(flags & VIR_DOMAIN_XML_INACTIVE)) {
|
||||||
virBufferEscapeString(buf, "<mirror file='%s'", def->mirror);
|
virBufferEscapeString(buf, "<mirror file='%s'", def->mirror->path);
|
||||||
if (def->mirrorFormat)
|
if (def->mirror->format)
|
||||||
virBufferAsprintf(buf, " format='%s'",
|
virBufferAsprintf(buf, " format='%s'",
|
||||||
virStorageFileFormatTypeToString(def->mirrorFormat));
|
virStorageFileFormatTypeToString(def->mirror->format));
|
||||||
if (def->mirroring)
|
if (def->mirroring)
|
||||||
virBufferAddLit(buf, " ready='yes'");
|
virBufferAddLit(buf, " ready='yes'");
|
||||||
virBufferAddLit(buf, "/>\n");
|
virBufferAddLit(buf, "/>\n");
|
||||||
|
@ -606,8 +606,7 @@ struct _virDomainDiskDef {
|
|||||||
int tray_status; /* enum virDomainDiskTray */
|
int tray_status; /* enum virDomainDiskTray */
|
||||||
int removable; /* enum virDomainFeatureState */
|
int removable; /* enum virDomainFeatureState */
|
||||||
|
|
||||||
char *mirror;
|
virStorageSourcePtr mirror;
|
||||||
int mirrorFormat; /* virStorageFileFormat */
|
|
||||||
bool mirroring;
|
bool mirroring;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -887,8 +887,8 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
|
|||||||
|
|
||||||
/* default disk format for mirrored drive */
|
/* default disk format for mirrored drive */
|
||||||
if (disk->mirror &&
|
if (disk->mirror &&
|
||||||
disk->mirrorFormat == VIR_STORAGE_FILE_NONE)
|
disk->mirror->format == VIR_STORAGE_FILE_NONE)
|
||||||
disk->mirrorFormat = VIR_STORAGE_FILE_AUTO;
|
disk->mirror->format = VIR_STORAGE_FILE_AUTO;
|
||||||
} else {
|
} else {
|
||||||
/* default driver if probing is forbidden */
|
/* default driver if probing is forbidden */
|
||||||
if (!virDomainDiskGetDriver(disk) &&
|
if (!virDomainDiskGetDriver(disk) &&
|
||||||
@ -903,8 +903,8 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
|
|||||||
|
|
||||||
/* default disk format for mirrored drive */
|
/* default disk format for mirrored drive */
|
||||||
if (disk->mirror &&
|
if (disk->mirror &&
|
||||||
disk->mirrorFormat == VIR_STORAGE_FILE_NONE)
|
disk->mirror->format == VIR_STORAGE_FILE_NONE)
|
||||||
disk->mirrorFormat = VIR_STORAGE_FILE_RAW;
|
disk->mirror->format = VIR_STORAGE_FILE_RAW;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14864,13 +14864,22 @@ qemuDomainBlockPivot(virConnectPtr conn,
|
|||||||
int ret = -1, rc;
|
int ret = -1, rc;
|
||||||
qemuDomainObjPrivatePtr priv = vm->privateData;
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
virDomainBlockJobInfo info;
|
virDomainBlockJobInfo info;
|
||||||
const char *format = virStorageFileFormatTypeToString(disk->mirrorFormat);
|
const char *format = NULL;
|
||||||
bool resume = false;
|
bool resume = false;
|
||||||
char *oldsrc = NULL;
|
char *oldsrc = NULL;
|
||||||
int oldformat;
|
int oldformat;
|
||||||
virStorageSourcePtr oldchain = NULL;
|
virStorageSourcePtr oldchain = NULL;
|
||||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
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. */
|
/* Probe the status, if needed. */
|
||||||
if (!disk->mirroring) {
|
if (!disk->mirroring) {
|
||||||
qemuDomainObjEnterMonitor(driver, vm);
|
qemuDomainObjEnterMonitor(driver, vm);
|
||||||
@ -14928,8 +14937,8 @@ qemuDomainBlockPivot(virConnectPtr conn,
|
|||||||
oldsrc = disk->src->path;
|
oldsrc = disk->src->path;
|
||||||
oldformat = disk->src->format;
|
oldformat = disk->src->format;
|
||||||
oldchain = disk->src->backingStore;
|
oldchain = disk->src->backingStore;
|
||||||
disk->src->path = disk->mirror;
|
disk->src->path = disk->mirror->path;
|
||||||
disk->src->format = disk->mirrorFormat;
|
disk->src->format = disk->mirror->format;
|
||||||
disk->src->backingStore = NULL;
|
disk->src->backingStore = NULL;
|
||||||
if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0) {
|
if (qemuDomainDetermineDiskChain(driver, vm, disk, false) < 0) {
|
||||||
disk->src->path = oldsrc;
|
disk->src->path = oldsrc;
|
||||||
@ -14937,7 +14946,7 @@ qemuDomainBlockPivot(virConnectPtr conn,
|
|||||||
disk->src->backingStore = oldchain;
|
disk->src->backingStore = oldchain;
|
||||||
goto cleanup;
|
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,
|
(virDomainLockDiskAttach(driver->lockManager, cfg->uri,
|
||||||
vm, disk) < 0 ||
|
vm, disk) < 0 ||
|
||||||
qemuSetupDiskCgroup(vm, disk) < 0 ||
|
qemuSetupDiskCgroup(vm, disk) < 0 ||
|
||||||
@ -14951,7 +14960,7 @@ qemuDomainBlockPivot(virConnectPtr conn,
|
|||||||
|
|
||||||
/* Attempt the pivot. */
|
/* Attempt the pivot. */
|
||||||
qemuDomainObjEnterMonitor(driver, vm);
|
qemuDomainObjEnterMonitor(driver, vm);
|
||||||
ret = qemuMonitorDrivePivot(priv->mon, device, disk->mirror, format);
|
ret = qemuMonitorDrivePivot(priv->mon, device, disk->mirror->path, format);
|
||||||
qemuDomainObjExitMonitor(driver, vm);
|
qemuDomainObjExitMonitor(driver, vm);
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
@ -14964,7 +14973,7 @@ qemuDomainBlockPivot(virConnectPtr conn,
|
|||||||
* for now, we leak the access to the original. */
|
* for now, we leak the access to the original. */
|
||||||
VIR_FREE(oldsrc);
|
VIR_FREE(oldsrc);
|
||||||
virStorageSourceFree(oldchain);
|
virStorageSourceFree(oldchain);
|
||||||
disk->mirror = NULL;
|
disk->mirror->path = NULL;
|
||||||
} else {
|
} else {
|
||||||
/* On failure, qemu abandons the mirror, and reverts back to
|
/* On failure, qemu abandons the mirror, and reverts back to
|
||||||
* the source disk (RHEL 6.3 has a bug where the revert could
|
* the source disk (RHEL 6.3 has a bug where the revert could
|
||||||
@ -14978,9 +14987,9 @@ qemuDomainBlockPivot(virConnectPtr conn,
|
|||||||
disk->src->format = oldformat;
|
disk->src->format = oldformat;
|
||||||
virStorageSourceFree(disk->src->backingStore);
|
virStorageSourceFree(disk->src->backingStore);
|
||||||
disk->src->backingStore = oldchain;
|
disk->src->backingStore = oldchain;
|
||||||
VIR_FREE(disk->mirror);
|
|
||||||
}
|
}
|
||||||
disk->mirrorFormat = VIR_STORAGE_FILE_NONE;
|
virStorageSourceFree(disk->mirror);
|
||||||
|
disk->mirror = NULL;
|
||||||
disk->mirroring = false;
|
disk->mirroring = false;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@ -15106,8 +15115,8 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm,
|
|||||||
if (mode == BLOCK_JOB_ABORT && disk->mirror) {
|
if (mode == BLOCK_JOB_ABORT && disk->mirror) {
|
||||||
/* XXX We should also revoke security labels and disk lease on
|
/* XXX We should also revoke security labels and disk lease on
|
||||||
* the mirror, and audit that fact, before dropping things. */
|
* the mirror, and audit that fact, before dropping things. */
|
||||||
VIR_FREE(disk->mirror);
|
virStorageSourceFree(disk->mirror);
|
||||||
disk->mirrorFormat = VIR_STORAGE_FILE_NONE;
|
disk->mirror = NULL;
|
||||||
disk->mirroring = false;
|
disk->mirroring = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15242,7 +15251,7 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
|
|||||||
int idx;
|
int idx;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
bool need_unlink = false;
|
bool need_unlink = false;
|
||||||
char *mirror = NULL;
|
virStorageSourcePtr mirror = NULL;
|
||||||
virQEMUDriverConfigPtr cfg = NULL;
|
virQEMUDriverConfigPtr cfg = NULL;
|
||||||
|
|
||||||
/* Preliminaries: find the disk we are editing, sanity checks */
|
/* Preliminaries: find the disk we are editing, sanity checks */
|
||||||
@ -15323,6 +15332,11 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
|
|||||||
goto endjob;
|
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)) {
|
if (!(flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)) {
|
||||||
int fd = qemuOpenFile(driver, vm, dest, O_WRONLY | O_TRUNC | O_CREAT,
|
int fd = qemuOpenFile(driver, vm, dest, O_WRONLY | O_TRUNC | O_CREAT,
|
||||||
&need_unlink, NULL);
|
&need_unlink, NULL);
|
||||||
@ -15330,10 +15344,10 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
|
|||||||
goto endjob;
|
goto endjob;
|
||||||
VIR_FORCE_CLOSE(fd);
|
VIR_FORCE_CLOSE(fd);
|
||||||
if (!format)
|
if (!format)
|
||||||
disk->mirrorFormat = disk->src->format;
|
mirror->format = disk->src->format;
|
||||||
} else if (format) {
|
} else if (format) {
|
||||||
disk->mirrorFormat = virStorageFileFormatTypeFromString(format);
|
mirror->format = virStorageFileFormatTypeFromString(format);
|
||||||
if (disk->mirrorFormat <= 0) {
|
if (mirror->format <= 0) {
|
||||||
virReportError(VIR_ERR_INVALID_ARG, _("unrecognized format '%s'"),
|
virReportError(VIR_ERR_INVALID_ARG, _("unrecognized format '%s'"),
|
||||||
format);
|
format);
|
||||||
goto endjob;
|
goto endjob;
|
||||||
@ -15343,12 +15357,12 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
|
|||||||
* also passed the RAW flag (and format is non-NULL), or it is
|
* 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
|
* safe for us to probe the format from the file that we will
|
||||||
* be using. */
|
* be using. */
|
||||||
disk->mirrorFormat = virStorageFileProbeFormat(dest, cfg->user,
|
mirror->format = virStorageFileProbeFormat(dest, cfg->user,
|
||||||
cfg->group);
|
cfg->group);
|
||||||
}
|
}
|
||||||
if (!format && disk->mirrorFormat > 0)
|
if (!format && mirror->format > 0)
|
||||||
format = virStorageFileFormatTypeToString(disk->mirrorFormat);
|
format = virStorageFileFormatTypeToString(mirror->format);
|
||||||
if (VIR_STRDUP(mirror, dest) < 0)
|
if (VIR_STRDUP(mirror->path, dest) < 0)
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
|
||||||
if (qemuDomainPrepareDiskChainElementPath(driver, vm, disk, dest,
|
if (qemuDomainPrepareDiskChainElementPath(driver, vm, disk, dest,
|
||||||
@ -15378,9 +15392,11 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
|
|||||||
endjob:
|
endjob:
|
||||||
if (need_unlink && unlink(dest))
|
if (need_unlink && unlink(dest))
|
||||||
VIR_WARN("unable to unlink just-created %s", dest);
|
VIR_WARN("unable to unlink just-created %s", dest);
|
||||||
if (ret < 0 && disk)
|
if (ret < 0 && disk) {
|
||||||
disk->mirrorFormat = VIR_STORAGE_FILE_NONE;
|
virStorageSourceFree(disk->mirror);
|
||||||
VIR_FREE(mirror);
|
disk->mirror = NULL;
|
||||||
|
}
|
||||||
|
virStorageSourceFree(mirror);
|
||||||
if (!qemuDomainObjEndJob(driver, vm))
|
if (!qemuDomainObjEndJob(driver, vm))
|
||||||
vm = NULL;
|
vm = NULL;
|
||||||
|
|
||||||
|
@ -1033,12 +1033,15 @@ qemuProcessHandleBlockJob(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
|||||||
type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT) &&
|
type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT) &&
|
||||||
status == VIR_DOMAIN_BLOCK_JOB_COMPLETED)
|
status == VIR_DOMAIN_BLOCK_JOB_COMPLETED)
|
||||||
qemuDomainDetermineDiskChain(driver, vm, disk, true);
|
qemuDomainDetermineDiskChain(driver, vm, disk, true);
|
||||||
if (disk->mirror && type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY &&
|
if (disk->mirror && type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY) {
|
||||||
status == VIR_DOMAIN_BLOCK_JOB_READY)
|
if (status == VIR_DOMAIN_BLOCK_JOB_READY) {
|
||||||
disk->mirroring = true;
|
disk->mirroring = true;
|
||||||
if (disk->mirror && type == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY &&
|
} else if (status == VIR_DOMAIN_BLOCK_JOB_FAILED) {
|
||||||
status == VIR_DOMAIN_BLOCK_JOB_FAILED)
|
virStorageSourceFree(disk->mirror);
|
||||||
VIR_FREE(disk->mirror);
|
disk->mirror = NULL;
|
||||||
|
disk->mirroring = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virObjectUnlock(vm);
|
virObjectUnlock(vm);
|
||||||
|
Loading…
Reference in New Issue
Block a user