On 2012年12月11日 21:37, Osier Yang wrote:
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".
---
src/qemu/qemu_process.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_process.h | 3 +++
2 files changed, 47 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index f39b83f..ba777e2 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3380,6 +3380,42 @@ 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).
+ *
+ * Returns 0 if no conflicts, otherwise returns -1.
+ */
+int
+qemuCheckSharedDisk(virHashTablePtr sharedDisks,
+ virDomainDiskDefPtr disk)
+{
+ int val;
+ qemuSharedDiskEntryPtr entry = NULL;
+
+ /* It can't be conflict if no other domain is
+ * is sharing it.
+ */
+ if (!(entry = virHashLookup(sharedDisks, disk->src)))
+ return 0;
+
+ if (entry->ref == 1)
+ return 0;
+
+ if (virGetDeviceUnprivSGIO(disk->src,&val)< 0)
+ return -1;
+
+ if ((val == 0&&
+ disk->orig_cdbfilter == VIR_DOMAIN_DISK_CDB_FILTER_YES) ||
+ (val == 1&&
+ disk->orig_cdbfilter == VIR_DOMAIN_DISK_CDB_FILTER_NO))
+ return 0;
+
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cdbfilter of shared disk '%s' conflicts with other "
+ "active domains"), disk->src);
+ return -1;
+}
+
int qemuProcessStart(virConnectPtr conn,
virQEMUDriverPtr driver,
virDomainObjPtr vm,
@@ -3730,9 +3766,17 @@ int qemuProcessStart(virConnectPtr conn,
}
if (disk->shared) {
+ /* qemuAddSharedDisk must be called before qemuCheckSharedDisk
+ * in case of qemuCheckSharedDisk fails and qemuProcessStop
+ * will restore the disk's unpriv_sgio if there is only
+ * one domain is using the shared disk.
+ */
if (qemuAddSharedDisk(driver->sharedDisks, disk->src,
disk->orig_cdbfilter)< 0)
goto cleanup;
+
+ if (qemuCheckSharedDisk(driver->sharedDisks, disk)< 0)
+ goto cleanup;
}
}
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index c12df32..6d92368 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -99,4 +99,7 @@ bool qemuProcessAutoDestroyActive(virQEMUDriverPtr driver,
virBitmapPtr qemuPrepareCpumap(virQEMUDriverPtr driver,
virBitmapPtr nodemask);
+int qemuCheckSharedDisk(virHashTablePtr sharedDisks,
+ virDomainDiskDefPtr disk);
+
#endif /* __QEMU_PROCESS_H__ */
With the diff below squashed in: (comparing disk->orig_cdbfilter is not
right, it's a typo; And don't try to set the unpriv_sgio before conflict
checking, otherwise it could affect the active domain if checking fails;)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index ba777e2..1e09cab 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3405,9 +3405,9 @@ qemuCheckSharedDisk(virHashTablePtr sharedDisks,
return -1;
if ((val == 0 &&
- disk->orig_cdbfilter == VIR_DOMAIN_DISK_CDB_FILTER_YES) ||
+ disk->cdbfilter == VIR_DOMAIN_DISK_CDB_FILTER_YES) ||
(val == 1 &&
- disk->orig_cdbfilter == VIR_DOMAIN_DISK_CDB_FILTER_NO))
+ disk->cdbfilter == VIR_DOMAIN_DISK_CDB_FILTER_NO))
return 0;
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -3748,7 +3748,6 @@ int qemuProcessStart(virConnectPtr conn,
if (disk->rawio == 1)
virCommandAllowCap(cmd, CAP_SYS_RAWIO);
- /* Set sysfs unpriv_sgio if cdbfilter is specified */
if (disk->cdbfilter) {
if (virGetDeviceUnprivSGIO(disk->src, &val) < 0)
goto cleanup;
@@ -3757,12 +3756,6 @@ int qemuProcessStart(virConnectPtr conn,
disk->orig_cdbfilter = VIR_DOMAIN_DISK_CDB_FILTER_YES;
else
disk->orig_cdbfilter = VIR_DOMAIN_DISK_CDB_FILTER_NO;
-
- if (virSetDeviceUnprivSGIO(disk->src,
- (disk->cdbfilter ==
- VIR_DOMAIN_DISK_CDB_FILTER_NO)
- ? 1 : 0) < 0)
- goto cleanup;
}
if (disk->shared) {
@@ -3778,6 +3771,15 @@ int qemuProcessStart(virConnectPtr conn,
if (qemuCheckSharedDisk(driver->sharedDisks, disk) < 0)
goto cleanup;
}
+
+ /* Set sysfs unpriv_sgio if cdbfilter is specified */
+ if (disk->cdbfilter) {
+ if (virSetDeviceUnprivSGIO(disk->src,
+ (disk->cdbfilter ==
+ VIR_DOMAIN_DISK_CDB_FILTER_NO)
+ ? 1 : 0) < 0)
+ goto cleanup;
+ }
}
virCommandSetPreExecHook(cmd, qemuProcessHook, &hookData);
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list