While qemu may be prepared to do this libvirt is not. Forbid the block ops until we fix our code. --- src/conf/domain_conf.h | 1 + src/qemu/qemu_domain.c | 23 +++++++++++++++++++++++ src/qemu/qemu_domain.h | 2 ++ src/qemu/qemu_driver.c | 28 +++++++++++++--------------- 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index ea463cb..6f2df46 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -664,6 +664,7 @@ struct _virDomainDiskDef { int tray_status; /* enum virDomainDiskTray */ int removable; /* enum virTristateSwitch */ + bool blockjob; virStorageSourcePtr mirror; int mirrorState; /* enum virDomainDiskMirrorState */ int mirrorJob; /* virDomainBlockJobType */ diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index d8a2087..ff4307b 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2756,6 +2756,29 @@ qemuDomainDetermineDiskChain(virQEMUDriverPtr driver, return ret; } + +bool +qemuDomainDiskBlockJobIsActive(virDomainDiskDefPtr disk) +{ + if (disk->mirror) { + virReportError(VIR_ERR_BLOCK_COPY_ACTIVE, + _("disk '%s' already in active block job"), + disk->dst); + + return true; + } + + if (disk->blockjob) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, + _("disk '%s' already in active block job"), + disk->dst); + return true; + } + + return false; +} + + int qemuDomainUpdateDeviceList(virQEMUDriverPtr driver, virDomainObjPtr vm, diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index a7ebb47..41e075b 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -414,6 +414,8 @@ int qemuDomainJobInfoToParams(qemuDomainJobInfoPtr jobInfo, ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); +bool qemuDomainDiskBlockJobIsActive(virDomainDiskDefPtr disk); + void qemuDomObjEndAPI(virDomainObjPtr *vm); #endif /* __QEMU_DOMAIN_H__ */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 1aed55f..864ee50 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4537,6 +4537,7 @@ processBlockJobEvent(virQEMUDriverPtr driver, disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN; ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk, true, true)); + disk->blockjob = false; break; case VIR_DOMAIN_BLOCK_JOB_READY: @@ -4552,6 +4553,7 @@ processBlockJobEvent(virQEMUDriverPtr driver, VIR_DOMAIN_DISK_MIRROR_STATE_ABORT : VIR_DOMAIN_DISK_MIRROR_STATE_NONE; disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN; save = true; + disk->blockjob = false; break; case VIR_DOMAIN_BLOCK_JOB_LAST: @@ -16133,6 +16135,7 @@ qemuDomainBlockPivot(virConnectPtr conn, disk->mirror = NULL; disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE; disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN; + disk->blockjob = false; } if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) ret = -1; @@ -16233,12 +16236,9 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm, goto endjob; disk = vm->def->disks[idx]; - if (mode == BLOCK_JOB_PULL && disk->mirror) { - virReportError(VIR_ERR_BLOCK_COPY_ACTIVE, - _("disk '%s' already in active block job"), - disk->dst); + if (mode == BLOCK_JOB_PULL && qemuDomainDiskBlockJobIsActive(disk)) goto endjob; - } + if (mode == BLOCK_JOB_ABORT) { if ((flags & VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT) && !(async && disk->mirror)) { @@ -16322,6 +16322,8 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm, if (mode == BLOCK_JOB_ABORT && disk->mirror) disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE; goto endjob; + } else if (mode == BLOCK_JOB_PULL) { + disk->blockjob = true; } waitjob: @@ -16573,12 +16575,8 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm, if (!device) goto endjob; disk = vm->def->disks[idx]; - if (disk->mirror) { - virReportError(VIR_ERR_BLOCK_COPY_ACTIVE, - _("disk '%s' already in active block job"), - disk->dst); + if (qemuDomainDiskBlockJobIsActive(disk)) goto endjob; - } if (!(virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_MIRROR) && virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC))) { @@ -16699,6 +16697,7 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm, disk->mirror = mirror; mirror = NULL; disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY; + disk->blockjob = true; if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) VIR_WARN("Unable to save status on vm %s after state change", @@ -16960,12 +16959,9 @@ qemuDomainBlockCommit(virDomainPtr dom, disk->dst); goto endjob; } - if (disk->mirror) { - virReportError(VIR_ERR_BLOCK_COPY_ACTIVE, - _("disk '%s' already in active block job"), - disk->dst); + + if (qemuDomainDiskBlockJobIsActive(disk)) goto endjob; - } if (qemuDomainDetermineDiskChain(driver, vm, disk, false, true) < 0) goto endjob; @@ -17089,6 +17085,8 @@ qemuDomainBlockCommit(virDomainPtr dom, goto endjob; } + disk->blockjob = true; + if (mirror) { if (ret == 0) { virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); -- 2.2.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list