This prevents domain starting and disk attaching if the shared disk's
setting conflicts with other active domain(s), E.g. A domain with
"sgio" set as "filtered", however, another active domain is using
it set as "unfiltered".
---
 src/qemu/qemu_driver.c  |    5 ++++
 src/qemu/qemu_process.c |   53 +++++++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_process.h |    3 ++
 3 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 98b6b59..2f2b15a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5995,6 +5995,11 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
         goto end;
     }
 
+    if (disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK &&
+        disk->shared &&
+        (qemuCheckSharedDisk(driver->sharedDisks, disk) < 0))
+        goto end;
+
     if (qemuDomainDetermineDiskChain(driver, disk, false) < 0)
         goto end;
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 66637d1..2e4d139 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3413,6 +3413,56 @@ qemuSetUnprivSGIO(virDomainDiskDefPtr disk)
     return 0;
 }
 
+/* Check if a shared disk's setting conflicts with the conf
+ * used by other domain(s). Currently only checks the sgio
+ * setting. Note that this should only be called for disk with
+ * block source.
+ *
+ * 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, NULL, &val) < 0) {
+        ret = -1;
+        goto cleanup;
+    }
+
+    if ((val == 0 &&
+         (disk->sgio == VIR_DOMAIN_DISK_SGIO_FILTERED ||
+          disk->sgio == VIR_DOMAIN_DISK_SGIO_DEFAULT)) ||
+        (val == 1 &&
+         disk->sgio == VIR_DOMAIN_DISK_SGIO_UNFILTERED))
+        goto cleanup;
+
+    virReportError(VIR_ERR_OPERATION_INVALID,
+                   _("sgio 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,
@@ -3761,6 +3811,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;
         }
 
         if (qemuSetUnprivSGIO(disk) < 0)
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index 52a298d..313fa39 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -100,4 +100,7 @@ virBitmapPtr qemuPrepareCpumap(virQEMUDriverPtr driver,
                                virBitmapPtr nodemask);
 int qemuSetUnprivSGIO(virDomainDiskDefPtr disk);
 
+int qemuCheckSharedDisk(virHashTablePtr sharedDisks,
+                        virDomainDiskDefPtr disk);
+
 #endif /* __QEMU_PROCESS_H__ */
-- 
1.7.7.6

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to