This prevents the domain starting if the shared disk's setting
conflicts with other active domain(s), E.g. A domain with
"cdbfilter" set as "yes", however, another active domain is using
it set as "no".
---
This assumes the lock manager will prevents one using same disk
mixed with non-shared and shared modes. I.E. The following
scenario won't be happen:
* dom1, with disk /dev/sdb's cdbfilter="no" shared
* dom2, with disk /dev/sdb's cdbfilter="yes" and non-shared
Without the lock manager, dom2's staring will override the
disk's unpriv_sgio to 0.
---
src/qemu/qemu_process.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_process.h | 2 +
2 files changed, 53 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 4117251..ace0404 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3385,6 +3385,54 @@ qemuProcessReconnectAll(virConnectPtr conn, virQEMUDriverPtr
driver)
virHashForEach(driver->domains.objs, qemuProcessReconnectHelper, &data);
}
+/* Check if a shared disk's setting conflicts with the conf
+ * used by other domain(s). Currently only checks the cdbfilter
+ * setting.
+ *
+ * Returns 0 if no conflicts, otherwise returns -1.
+ */
+int
+qemuCheckSharedDisk(virHashTablePtr sharedDisks,
+ virDomainDiskDefPtr disk)
+{
+ int val;
+ size_t *ref = NULL;
+ char *key = NULL;
+ int ret = 0;
+
+ if (!(key = qemuGetSharedDiskKey(disk->src)))
+ return -1;
+
+ /* It can't be conflict if no other domain is
+ * is sharing it.
+ */
+ if (!(ref = virHashLookup(sharedDisks, key)))
+ goto cleanup;
+
+ if (ref == (void *)0x1)
+ goto cleanup;
+
+ if (virGetDeviceUnprivSGIO(disk->src, &val) < 0) {
+ ret = -1;
+ goto cleanup;
+ }
+
+ if ((val == 0 &&
+ disk->cdbfilter == VIR_DOMAIN_DISK_CDB_FILTER_YES) ||
+ (val == 1 &&
+ disk->cdbfilter == VIR_DOMAIN_DISK_CDB_FILTER_NO))
+ goto cleanup;
+
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cdbfilter of shared disk '%s' conflicts with other
"
+ "active domains"), disk->src);
+ ret = -1;
+
+cleanup:
+ VIR_FREE(key);
+ return ret;
+}
+
int qemuProcessStart(virConnectPtr conn,
virQEMUDriverPtr driver,
virDomainObjPtr vm,
@@ -3733,6 +3781,9 @@ int qemuProcessStart(virConnectPtr conn,
if (disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK && disk->shared) {
if (qemuAddSharedDisk(driver->sharedDisks, disk->src) < 0)
goto cleanup;
+
+ if (qemuCheckSharedDisk(driver->sharedDisks, disk) < 0)
+ goto cleanup;
}
/* Set sysfs unpriv_sgio if cdbfilter is specified */
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index c12df32..3aad08f 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -98,5 +98,7 @@ bool qemuProcessAutoDestroyActive(virQEMUDriverPtr driver,
virDomainObjPtr vm);
virBitmapPtr qemuPrepareCpumap(virQEMUDriverPtr driver,
virBitmapPtr nodemask);
+int qemuCheckSharedDisk(virHashTablePtr sharedDisks,
+ virDomainDiskDefPtr disk);
#endif /* __QEMU_PROCESS_H__ */
--
1.7.7.6