|
|
d89b3e |
From 4e7b21b4138e011c05ae72ed8b92f0bd2b888744 Mon Sep 17 00:00:00 2001
|
|
|
d89b3e |
Message-Id: <4e7b21b4138e011c05ae72ed8b92f0bd2b888744@dist-git>
|
|
|
d89b3e |
From: Peter Krempa <pkrempa@redhat.com>
|
|
|
d89b3e |
Date: Tue, 17 Mar 2015 13:13:53 +0100
|
|
|
d89b3e |
Subject: [PATCH] qemu: Disallow concurrent block jobs on a single disk
|
|
|
d89b3e |
|
|
|
d89b3e |
https://bugzilla.redhat.com/show_bug.cgi?id=1202719
|
|
|
d89b3e |
|
|
|
d89b3e |
While qemu may be prepared to do this libvirt is not. Forbid the block
|
|
|
d89b3e |
ops until we fix our code.
|
|
|
d89b3e |
|
|
|
d89b3e |
(cherry picked from commit 51f9f03a4ca50b070c0fbfb29748d49f583e15e1)
|
|
|
d89b3e |
|
|
|
d89b3e |
Conflicts:
|
|
|
d89b3e |
src/qemu/qemu_domain.h - context with upstream changes
|
|
|
d89b3e |
|
|
|
d89b3e |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
d89b3e |
---
|
|
|
d89b3e |
src/conf/domain_conf.h | 4 ++++
|
|
|
d89b3e |
src/qemu/qemu_domain.c | 23 +++++++++++++++++++++++
|
|
|
d89b3e |
src/qemu/qemu_domain.h | 2 ++
|
|
|
d89b3e |
src/qemu/qemu_driver.c | 28 +++++++++++++---------------
|
|
|
d89b3e |
4 files changed, 42 insertions(+), 15 deletions(-)
|
|
|
d89b3e |
|
|
|
d89b3e |
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
|
|
|
d89b3e |
index 1436eb8..654c27d 100644
|
|
|
d89b3e |
--- a/src/conf/domain_conf.h
|
|
|
d89b3e |
+++ b/src/conf/domain_conf.h
|
|
|
d89b3e |
@@ -636,6 +636,10 @@ struct _virDomainDiskDef {
|
|
|
d89b3e |
int tray_status; /* enum virDomainDiskTray */
|
|
|
d89b3e |
int removable; /* enum virTristateSwitch */
|
|
|
d89b3e |
|
|
|
d89b3e |
+ /* ideally we want a smarter way to interlock block jobs on single qemu disk
|
|
|
d89b3e |
+ * in the future, but for now we just disallow any concurrent job on a
|
|
|
d89b3e |
+ * single disk */
|
|
|
d89b3e |
+ bool blockjob;
|
|
|
d89b3e |
virStorageSourcePtr mirror;
|
|
|
d89b3e |
int mirrorState; /* enum virDomainDiskMirrorState */
|
|
|
d89b3e |
int mirrorJob; /* virDomainBlockJobType */
|
|
|
d89b3e |
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
|
|
|
d89b3e |
index 0c3d21f..b9bf3eb 100644
|
|
|
d89b3e |
--- a/src/qemu/qemu_domain.c
|
|
|
d89b3e |
+++ b/src/qemu/qemu_domain.c
|
|
|
d89b3e |
@@ -2771,6 +2771,29 @@ qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
|
|
|
d89b3e |
return ret;
|
|
|
d89b3e |
}
|
|
|
d89b3e |
|
|
|
d89b3e |
+
|
|
|
d89b3e |
+bool
|
|
|
d89b3e |
+qemuDomainDiskBlockJobIsActive(virDomainDiskDefPtr disk)
|
|
|
d89b3e |
+{
|
|
|
d89b3e |
+ if (disk->mirror) {
|
|
|
d89b3e |
+ virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
|
|
|
d89b3e |
+ _("disk '%s' already in active block job"),
|
|
|
d89b3e |
+ disk->dst);
|
|
|
d89b3e |
+
|
|
|
d89b3e |
+ return true;
|
|
|
d89b3e |
+ }
|
|
|
d89b3e |
+
|
|
|
d89b3e |
+ if (disk->blockjob) {
|
|
|
d89b3e |
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
|
|
|
d89b3e |
+ _("disk '%s' already in active block job"),
|
|
|
d89b3e |
+ disk->dst);
|
|
|
d89b3e |
+ return true;
|
|
|
d89b3e |
+ }
|
|
|
d89b3e |
+
|
|
|
d89b3e |
+ return false;
|
|
|
d89b3e |
+}
|
|
|
d89b3e |
+
|
|
|
d89b3e |
+
|
|
|
d89b3e |
int
|
|
|
d89b3e |
qemuDomainUpdateDeviceList(virQEMUDriverPtr driver,
|
|
|
d89b3e |
virDomainObjPtr vm,
|
|
|
d89b3e |
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
|
|
|
d89b3e |
index 76054ec..63d1261 100644
|
|
|
d89b3e |
--- a/src/qemu/qemu_domain.h
|
|
|
d89b3e |
+++ b/src/qemu/qemu_domain.h
|
|
|
d89b3e |
@@ -416,4 +416,6 @@ int qemuDomainJobInfoToParams(qemuDomainJobInfoPtr jobInfo,
|
|
|
d89b3e |
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
|
|
|
d89b3e |
ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4);
|
|
|
d89b3e |
|
|
|
d89b3e |
+bool qemuDomainDiskBlockJobIsActive(virDomainDiskDefPtr disk);
|
|
|
d89b3e |
+
|
|
|
d89b3e |
#endif /* __QEMU_DOMAIN_H__ */
|
|
|
d89b3e |
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
|
|
d89b3e |
index a19281d..2bd4a1d 100644
|
|
|
d89b3e |
--- a/src/qemu/qemu_driver.c
|
|
|
d89b3e |
+++ b/src/qemu/qemu_driver.c
|
|
|
d89b3e |
@@ -4490,6 +4490,7 @@ processBlockJobEvent(virQEMUDriverPtr driver,
|
|
|
d89b3e |
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
|
|
|
d89b3e |
ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk,
|
|
|
d89b3e |
true, true));
|
|
|
d89b3e |
+ disk->blockjob = false;
|
|
|
d89b3e |
break;
|
|
|
d89b3e |
|
|
|
d89b3e |
case VIR_DOMAIN_BLOCK_JOB_READY:
|
|
|
d89b3e |
@@ -4505,6 +4506,7 @@ processBlockJobEvent(virQEMUDriverPtr driver,
|
|
|
d89b3e |
VIR_DOMAIN_DISK_MIRROR_STATE_ABORT : VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
|
|
|
d89b3e |
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
|
|
|
d89b3e |
save = true;
|
|
|
d89b3e |
+ disk->blockjob = false;
|
|
|
d89b3e |
break;
|
|
|
d89b3e |
|
|
|
d89b3e |
case VIR_DOMAIN_BLOCK_JOB_LAST:
|
|
|
d89b3e |
@@ -15583,6 +15585,7 @@ qemuDomainBlockPivot(virConnectPtr conn,
|
|
|
d89b3e |
disk->mirror = NULL;
|
|
|
d89b3e |
disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
|
|
|
d89b3e |
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
|
|
|
d89b3e |
+ disk->blockjob = false;
|
|
|
d89b3e |
}
|
|
|
d89b3e |
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
|
|
d89b3e |
ret = -1;
|
|
|
d89b3e |
@@ -15679,12 +15682,9 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm,
|
|
|
d89b3e |
goto endjob;
|
|
|
d89b3e |
disk = vm->def->disks[idx];
|
|
|
d89b3e |
|
|
|
d89b3e |
- if (mode == BLOCK_JOB_PULL && disk->mirror) {
|
|
|
d89b3e |
- virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
|
|
|
d89b3e |
- _("disk '%s' already in active block job"),
|
|
|
d89b3e |
- disk->dst);
|
|
|
d89b3e |
+ if (mode == BLOCK_JOB_PULL && qemuDomainDiskBlockJobIsActive(disk))
|
|
|
d89b3e |
goto endjob;
|
|
|
d89b3e |
- }
|
|
|
d89b3e |
+
|
|
|
d89b3e |
if (mode == BLOCK_JOB_ABORT) {
|
|
|
d89b3e |
if ((flags & VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT) &&
|
|
|
d89b3e |
!(async && disk->mirror)) {
|
|
|
d89b3e |
@@ -15756,6 +15756,8 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm,
|
|
|
d89b3e |
if (mode == BLOCK_JOB_ABORT && disk->mirror)
|
|
|
d89b3e |
disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE;
|
|
|
d89b3e |
goto endjob;
|
|
|
d89b3e |
+ } else if (mode == BLOCK_JOB_PULL) {
|
|
|
d89b3e |
+ disk->blockjob = true;
|
|
|
d89b3e |
}
|
|
|
d89b3e |
|
|
|
d89b3e |
/* Snoop block copy operations, so future cancel operations can
|
|
|
d89b3e |
@@ -15943,12 +15945,8 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
|
|
|
d89b3e |
goto endjob;
|
|
|
d89b3e |
}
|
|
|
d89b3e |
disk = vm->def->disks[idx];
|
|
|
d89b3e |
- if (disk->mirror) {
|
|
|
d89b3e |
- virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
|
|
|
d89b3e |
- _("disk '%s' already in active block job"),
|
|
|
d89b3e |
- disk->dst);
|
|
|
d89b3e |
+ if (qemuDomainDiskBlockJobIsActive(disk))
|
|
|
d89b3e |
goto endjob;
|
|
|
d89b3e |
- }
|
|
|
d89b3e |
|
|
|
d89b3e |
if (!(virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE_MIRROR) &&
|
|
|
d89b3e |
virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_BLOCKJOB_ASYNC))) {
|
|
|
d89b3e |
@@ -16074,6 +16072,7 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
|
|
|
d89b3e |
disk->mirror = mirror;
|
|
|
d89b3e |
mirror = NULL;
|
|
|
d89b3e |
disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
|
|
|
d89b3e |
+ disk->blockjob = true;
|
|
|
d89b3e |
|
|
|
d89b3e |
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
|
|
|
d89b3e |
VIR_WARN("Unable to save status on vm %s after state change",
|
|
|
d89b3e |
@@ -16232,12 +16231,9 @@ qemuDomainBlockCommit(virDomainPtr dom,
|
|
|
d89b3e |
disk->dst);
|
|
|
d89b3e |
goto endjob;
|
|
|
d89b3e |
}
|
|
|
d89b3e |
- if (disk->mirror) {
|
|
|
d89b3e |
- virReportError(VIR_ERR_BLOCK_COPY_ACTIVE,
|
|
|
d89b3e |
- _("disk '%s' already in active block job"),
|
|
|
d89b3e |
- disk->dst);
|
|
|
d89b3e |
+
|
|
|
d89b3e |
+ if (qemuDomainDiskBlockJobIsActive(disk))
|
|
|
d89b3e |
goto endjob;
|
|
|
d89b3e |
- }
|
|
|
d89b3e |
if (qemuDomainDetermineDiskChain(driver, vm, disk, false, true) < 0)
|
|
|
d89b3e |
goto endjob;
|
|
|
d89b3e |
|
|
|
d89b3e |
@@ -16358,6 +16354,8 @@ qemuDomainBlockCommit(virDomainPtr dom,
|
|
|
d89b3e |
bandwidth);
|
|
|
d89b3e |
qemuDomainObjExitMonitor(driver, vm);
|
|
|
d89b3e |
|
|
|
d89b3e |
+ disk->blockjob = true;
|
|
|
d89b3e |
+
|
|
|
d89b3e |
if (mirror) {
|
|
|
d89b3e |
if (ret == 0) {
|
|
|
d89b3e |
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
|
|
d89b3e |
--
|
|
|
d89b3e |
2.3.3
|
|
|
d89b3e |
|