mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 06:05:27 +00:00
qemu: Disallow concurrent block jobs on a single disk
While qemu may be prepared to do this libvirt is not. Forbid the block
ops until we fix our code.
(cherry picked from commit 51f9f03a4c
)
This commit is contained in:
parent
6eb78379c2
commit
c7e01d5e1e
@ -664,6 +664,10 @@ struct _virDomainDiskDef {
|
|||||||
int tray_status; /* enum virDomainDiskTray */
|
int tray_status; /* enum virDomainDiskTray */
|
||||||
int removable; /* enum virTristateSwitch */
|
int removable; /* enum virTristateSwitch */
|
||||||
|
|
||||||
|
/* ideally we want a smarter way to interlock block jobs on single qemu disk
|
||||||
|
* in the future, but for now we just disallow any concurrent job on a
|
||||||
|
* single disk */
|
||||||
|
bool blockjob;
|
||||||
virStorageSourcePtr mirror;
|
virStorageSourcePtr mirror;
|
||||||
int mirrorState; /* enum virDomainDiskMirrorState */
|
int mirrorState; /* enum virDomainDiskMirrorState */
|
||||||
int mirrorJob; /* virDomainBlockJobType */
|
int mirrorJob; /* virDomainBlockJobType */
|
||||||
|
@ -2757,6 +2757,29 @@ qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
|
|||||||
return ret;
|
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
|
int
|
||||||
qemuDomainUpdateDeviceList(virQEMUDriverPtr driver,
|
qemuDomainUpdateDeviceList(virQEMUDriverPtr driver,
|
||||||
virDomainObjPtr vm,
|
virDomainObjPtr vm,
|
||||||
|
@ -414,6 +414,8 @@ int qemuDomainJobInfoToParams(qemuDomainJobInfoPtr jobInfo,
|
|||||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
|
||||||
ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
|
ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
|
||||||
|
|
||||||
|
bool qemuDomainDiskBlockJobIsActive(virDomainDiskDefPtr disk);
|
||||||
|
|
||||||
void qemuDomObjEndAPI(virDomainObjPtr *vm);
|
void qemuDomObjEndAPI(virDomainObjPtr *vm);
|
||||||
|
|
||||||
#endif /* __QEMU_DOMAIN_H__ */
|
#endif /* __QEMU_DOMAIN_H__ */
|
||||||
|
@ -4569,6 +4569,7 @@ processBlockJobEvent(virQEMUDriverPtr driver,
|
|||||||
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
|
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
|
||||||
ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk,
|
ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk,
|
||||||
true, true));
|
true, true));
|
||||||
|
disk->blockjob = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_BLOCK_JOB_READY:
|
case VIR_DOMAIN_BLOCK_JOB_READY:
|
||||||
@ -4584,6 +4585,7 @@ processBlockJobEvent(virQEMUDriverPtr driver,
|
|||||||
VIR_DOMAIN_DISK_MIRROR_STATE_ABORT : VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
|
VIR_DOMAIN_DISK_MIRROR_STATE_ABORT : VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
|
||||||
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
|
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
|
||||||
save = true;
|
save = true;
|
||||||
|
disk->blockjob = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_BLOCK_JOB_LAST:
|
case VIR_DOMAIN_BLOCK_JOB_LAST:
|
||||||
@ -15827,6 +15829,7 @@ qemuDomainBlockPivot(virConnectPtr conn,
|
|||||||
disk->mirror = NULL;
|
disk->mirror = NULL;
|
||||||
disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
|
disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
|
||||||
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
|
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
|
||||||
|
disk->blockjob = false;
|
||||||
}
|
}
|
||||||
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
||||||
ret = -1;
|
ret = -1;
|
||||||
@ -15927,12 +15930,9 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm,
|
|||||||
goto endjob;
|
goto endjob;
|
||||||
disk = vm->def->disks[idx];
|
disk = vm->def->disks[idx];
|
||||||
|
|
||||||
if (mode == BLOCK_JOB_PULL && disk->mirror) {
|
if (mode == BLOCK_JOB_PULL && qemuDomainDiskBlockJobIsActive(disk))
|
||||||
virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
|
|
||||||
_("disk '%s' already in active block job"),
|
|
||||||
disk->dst);
|
|
||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
|
||||||
if (mode == BLOCK_JOB_ABORT) {
|
if (mode == BLOCK_JOB_ABORT) {
|
||||||
if ((flags & VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT) &&
|
if ((flags & VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT) &&
|
||||||
!(async && disk->mirror)) {
|
!(async && disk->mirror)) {
|
||||||
@ -16017,6 +16017,8 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm,
|
|||||||
if (mode == BLOCK_JOB_ABORT && disk->mirror)
|
if (mode == BLOCK_JOB_ABORT && disk->mirror)
|
||||||
disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
|
disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
} else if (mode == BLOCK_JOB_PULL) {
|
||||||
|
disk->blockjob = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
waitjob:
|
waitjob:
|
||||||
@ -16269,12 +16271,8 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm,
|
|||||||
if (!device)
|
if (!device)
|
||||||
goto endjob;
|
goto endjob;
|
||||||
disk = vm->def->disks[idx];
|
disk = vm->def->disks[idx];
|
||||||
if (disk->mirror) {
|
if (qemuDomainDiskBlockJobIsActive(disk))
|
||||||
virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
|
|
||||||
_("disk '%s' already in active block job"),
|
|
||||||
disk->dst);
|
|
||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
|
||||||
|
|
||||||
if (!(virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_MIRROR) &&
|
if (!(virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_MIRROR) &&
|
||||||
virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC))) {
|
virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC))) {
|
||||||
@ -16396,6 +16394,7 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm,
|
|||||||
disk->mirror = mirror;
|
disk->mirror = mirror;
|
||||||
mirror = NULL;
|
mirror = NULL;
|
||||||
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
|
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
|
||||||
|
disk->blockjob = true;
|
||||||
|
|
||||||
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
||||||
VIR_WARN("Unable to save status on vm %s after state change",
|
VIR_WARN("Unable to save status on vm %s after state change",
|
||||||
@ -16657,12 +16656,9 @@ qemuDomainBlockCommit(virDomainPtr dom,
|
|||||||
disk->dst);
|
disk->dst);
|
||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
}
|
||||||
if (disk->mirror) {
|
|
||||||
virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
|
if (qemuDomainDiskBlockJobIsActive(disk))
|
||||||
_("disk '%s' already in active block job"),
|
|
||||||
disk->dst);
|
|
||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
|
||||||
if (qemuDomainDetermineDiskChain(driver, vm, disk, false, true) < 0)
|
if (qemuDomainDetermineDiskChain(driver, vm, disk, false, true) < 0)
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
|
||||||
@ -16785,6 +16781,8 @@ qemuDomainBlockCommit(virDomainPtr dom,
|
|||||||
goto endjob;
|
goto endjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disk->blockjob = true;
|
||||||
|
|
||||||
if (mirror) {
|
if (mirror) {
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||||
|
Loading…
Reference in New Issue
Block a user