提交 51f9f03a 编写于 作者: P Peter Krempa

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.
上级 1a92c719
...@@ -664,6 +664,10 @@ struct _virDomainDiskDef { ...@@ -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 */
......
...@@ -2756,6 +2756,29 @@ qemuDomainDetermineDiskChain(virQEMUDriverPtr driver, ...@@ -2756,6 +2756,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, ...@@ -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__ */
...@@ -4537,6 +4537,7 @@ processBlockJobEvent(virQEMUDriverPtr driver, ...@@ -4537,6 +4537,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:
...@@ -4552,6 +4553,7 @@ processBlockJobEvent(virQEMUDriverPtr driver, ...@@ -4552,6 +4553,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:
...@@ -16133,6 +16135,7 @@ qemuDomainBlockPivot(virConnectPtr conn, ...@@ -16133,6 +16135,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;
...@@ -16233,12 +16236,9 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm, ...@@ -16233,12 +16236,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)) {
...@@ -16322,6 +16322,8 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm, ...@@ -16322,6 +16322,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:
...@@ -16573,12 +16575,8 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm, ...@@ -16573,12 +16575,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))) {
...@@ -16699,6 +16697,7 @@ qemuDomainBlockCopyCommon(virDomainObjPtr vm, ...@@ -16699,6 +16697,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",
...@@ -16960,12 +16959,9 @@ qemuDomainBlockCommit(virDomainPtr dom, ...@@ -16960,12 +16959,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;
...@@ -17089,6 +17085,8 @@ qemuDomainBlockCommit(virDomainPtr dom, ...@@ -17089,6 +17085,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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册