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@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list