[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [libvirt] [PATCH 07/12] qemu: Error out when domain starting if the cdbfilter setting conflicts



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);

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]