This prevents restoring the unpriv_sgio if the disk is still being,
shared by other active domain. Because we don't want to fall into
the corruption situation. And if the disk is not shared, using
diskdef->orig_cdbfilter to restore the original disk's unpriv_sgio
state. If the disk is shared, but there is no other domain is sharing
it, using orig_cdbfilter of sharedDisks' entry to restore it.
---
src/qemu/qemu_conf.c | 12 ++++++++++++
src/qemu/qemu_conf.h | 4 ++++
src/qemu/qemu_process.c | 25 ++++++++++++++++++-------
3 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 2b21186..1bd89f7 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -604,3 +604,15 @@ qemuRemoveSharedDisk(virHashTablePtr sharedDisks,
return 0;
}
+
+bool
+qemuSharedDiskIsLast(virHashTablePtr sharedDisks,
+ const char *disk_path)
+{
+ qemuSharedDiskEntryPtr entry = NULL;
+
+ if (!(entry = virHashLookup(sharedDisks, disk_path)))
+ return false;
+
+ return entry->ref == 1;
+}
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index df901f6..73bbea8 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -229,4 +229,8 @@ int qemuRemoveSharedDisk(virHashTablePtr sharedDisks,
const char *disk_path)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+bool qemuSharedDiskIsLast(virHashTablePtr sharedDisks,
+ const char *disk_path)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
#endif /* __QEMUD_CONF_H */
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 859c5b0..f39b83f 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4133,17 +4133,28 @@ void qemuProcessStop(virQEMUDriverPtr driver,
for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDefPtr disk = vm->def->disks[i];
int val;
+ qemuSharedDiskEntryPtr entry = NULL;
/* Restore sysfs unpriv_sgio for the disk */
if (disk->cdbfilter) {
- if (disk->orig_cdbfilter == VIR_DOMAIN_DISK_CDB_FILTER_YES)
- val = 0;
- else
- val = 1;
+ /* Do not restore unpriv_sgio of the disk if it's still
+ * being shared by some other domain.
+ */
+ if (!disk->shared ||
+ qemuSharedDiskIsLast(driver->sharedDisks, disk->src)) {
+ if (!disk->shared) {
+ val = disk->orig_cdbfilter;
+ } else {
+ entry = virHashLookup(driver->sharedDisks, disk->src);
+ val = entry->orig_cdbfilter;
+ }
- if (virSetDeviceUnprivSGIO(disk->src, val) < 0)
- VIR_WARN("Unable to restore unpriv_sgio for disk
'%s'",
- disk->src);
+ if (virSetDeviceUnprivSGIO(disk->src,
+ (val == VIR_DOMAIN_DISK_CDB_FILTER_YES) ?
+ 0 : 1) < 0)
+ VIR_WARN("Unable to restore unpriv_sgio for disk
'%s'",
+ disk->src);
+ }
}
if (disk->shared) {
--
1.7.7.6