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

Re: [libvirt] [PATCH 01/12] qemu: Add a hash table for the shared disks



On 2012年12月11日 21:37, Osier Yang wrote:
This introduces a hash table for qemu driver, to store the shared
disk's info as (@disk_path, { ref_count, @orig_cdbfilter}). @ref_count
is the number of domains which shares the disk. @orig_cdbfilter is
the original cdbfilter setting of the shared disk, it will be used
to restore the the disk's cdbfilter setting to original value by
later patches.

* src/qemu/qemu_conf.h: (Add member 'sharedDisks' of type
                          virHashTablePtr; New struct qemuSharedDiskEntry;
                          Declare helpers qemuAddSharedDisk,
                          qemuRemoveSharedDisk)
* src/qemu/qemu_conf.c (Implement the two helpers)
* src/qemu/qemu_process.c (Update 'sharedDisks' when domain
                            starting and shutdown)
* src/qemu/qemu_driver.c (Update 'sharedDisks' when attaching
                           or detaching disk).

0 is passed for orig_cdbfilter temporarily, later patches will update
it.
---
  src/qemu/qemu_conf.c    |   48 +++++++++++++++++++++++++++++++++++++++++++++++
  src/qemu/qemu_conf.h    |   18 +++++++++++++++++
  src/qemu/qemu_driver.c  |   17 ++++++++++++++++
  src/qemu/qemu_process.c |   17 +++++++++++++++-
  4 files changed, 99 insertions(+), 1 deletions(-)

diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 8d380a1..2b21186 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -556,3 +556,51 @@ qemuDriverCloseCallbackRunAll(virQEMUDriverPtr driver,

      virHashForEach(driver->closeCallbacks, qemuDriverCloseCallbackRun,&data);
  }
+
+/* Increase ref count if the entry already exists, otherwise
+ * add a new entry.
+ */
+int
+qemuAddSharedDisk(virHashTablePtr sharedDisks,
+                  const char *disk_path,
+                  int orig_cdbfilter)
+{
+    qemuSharedDiskEntryPtr entry = NULL;
+
+    if ((entry = virHashLookup(sharedDisks, disk_path))) {
+        entry->ref++;
+    } else {
+        if (VIR_ALLOC(entry)<  0)
+            return -1;
+
+        entry->ref = 1;
+        entry->orig_cdbfilter = orig_cdbfilter;
+
+        if (virHashAddEntry(sharedDisks, disk_path, entry))
+            return -1;
+    }
+
+    return 0;
+}
+
+/* Decrease the ref count if the entry already exists, otherwise
+ * remove the entry.
+ */
+int
+qemuRemoveSharedDisk(virHashTablePtr sharedDisks,
+                     const char *disk_path)
+{
+    qemuSharedDiskEntryPtr entry = NULL;
+
+    if (!(entry = virHashLookup(sharedDisks, disk_path)))
+        return -1;
+
+    if (entry->ref != 1) {
+        entry->ref--;
+    } else {
+        if (virHashRemoveEntry(sharedDisks, disk_path)<  0)
+            return -1;
+    }
+
+    return 0;
+}
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index d0d25ce..df901f6 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -147,6 +147,8 @@ struct _virQEMUDriver {
      /* The devices which is are not in use by the host or any guest. */
      pciDeviceList *inactivePciHostdevs;

+    virHashTablePtr sharedDisks;
+
      virBitmapPtr reservedRemotePorts;

      virSysinfoDefPtr hostsysinfo;
@@ -193,6 +195,13 @@ struct qemuDomainDiskInfo {
      int io_status;
  };

+typedef struct qemuSharedDiskEntry qemuSharedDiskEntry;
+typedef qemuSharedDiskEntry *qemuSharedDiskEntryPtr;
+struct qemuSharedDiskEntry {
+    size_t ref; /* ref count of the shared disk */
+    int orig_cdbfilter; /* Original disk's cdbfilter setting */
+};
+
  typedef virDomainObjPtr (*qemuDriverCloseCallback)(virQEMUDriverPtr driver,
                                                     virDomainObjPtr vm,
                                                     virConnectPtr conn);
@@ -211,4 +220,13 @@ qemuDriverCloseCallback qemuDriverCloseCallbackGet(virQEMUDriverPtr driver,
  void qemuDriverCloseCallbackRunAll(virQEMUDriverPtr driver,
                                     virConnectPtr conn);

+int qemuAddSharedDisk(virHashTablePtr sharedDisks,
+                      const char *disk_path,
+                      int orig_cdbfilter)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
+int qemuRemoveSharedDisk(virHashTablePtr sharedDisks,
+                         const char *disk_path)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
  #endif /* __QEMUD_CONF_H */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index e099c5c..fdde74d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -810,6 +810,9 @@ qemuStartup(bool privileged,
      if ((qemu_driver->inactivePciHostdevs = pciDeviceListNew()) == NULL)
          goto error;

+    if (!(qemu_driver->sharedDisks = virHashCreate(30, NULL)))
+        goto error;
+
      if (privileged) {
          if (chown(qemu_driver->libDir, qemu_driver->user, qemu_driver->group)<  0) {
              virReportSystemError(errno,
@@ -1064,6 +1067,7 @@ qemuShutdown(void) {
      pciDeviceListFree(qemu_driver->activePciHostdevs);
      pciDeviceListFree(qemu_driver->inactivePciHostdevs);
      usbDeviceListFree(qemu_driver->activeUsbHostdevs);
+    virHashFree(qemu_driver->sharedDisks);
      virCapabilitiesFree(qemu_driver->caps);
      qemuCapsCacheFree(qemu_driver->capsCache);

@@ -6035,6 +6039,12 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
              VIR_WARN("Failed to teardown cgroup for disk path %s",
                       NULLSTR(disk->src));
      }
+
+    if (ret == 0&&  disk->shared) {
+        if (qemuAddSharedDisk(driver->sharedDisks, disk->src, 0)<  0)
+            VIR_WARN("Failed to add disk '%s' to shared disk table",
+                     disk->src);
+    }
  end:
      if (cgroup)
          virCgroupFree(&cgroup);
@@ -6149,6 +6159,13 @@ qemuDomainDetachDeviceDiskLive(virQEMUDriverPtr driver,
                         virDomainDiskDeviceTypeToString(disk->type));
          break;
      }
+
+    if (ret == 0&&  disk->shared) {
+        if (qemuRemoveSharedDisk(driver->sharedDisks, disk->src)<  0)
+             VIR_WARN("Failed to remove disk '%s' from shared disk table",
+                      disk->src);
+    }
+
      return ret;
  }

diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index ab04599..89152b8 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3706,8 +3706,15 @@ int qemuProcessStart(virConnectPtr conn,

      /* in case a certain disk is desirous of CAP_SYS_RAWIO, add this */
      for (i = 0; i<  vm->def->ndisks; i++) {
-        if (vm->def->disks[i]->rawio == 1)
+        virDomainDiskDefPtr disk = vm->def->disks[i];
+
+        if (disk->rawio == 1)
              virCommandAllowCap(cmd, CAP_SYS_RAWIO);
+
+        if (disk->shared) {
+            if (qemuAddSharedDisk(driver->sharedDisks, disk->src, 0)<  0)
+                goto cleanup;
+        }
      }

      virCommandSetPreExecHook(cmd, qemuProcessHook,&hookData);
@@ -4104,6 +4111,14 @@ void qemuProcessStop(virQEMUDriverPtr driver,
                                            flags&  VIR_QEMU_PROCESS_STOP_MIGRATED);
      virSecurityManagerReleaseLabel(driver->securityManager, vm->def);

+    for (i = 0; i<  vm->def->ndisks; i++) {
+        virDomainDiskDefPtr disk = vm->def->disks[i];
+
+        if (disk->shared) {
+            ignore_value(qemuRemoveSharedDisk(driver->sharedDisks, disk->src));
+        }
+    }
+
      /* Clear out dynamically assigned labels */
      for (i = 0; i<  vm->def->nseclabels; i++) {
          if (vm->def->seclabels[i]->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {

With the diff below squashed in: (the dataFree was missed when
changing the hash value from only ref count to a struct).


diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 48201c1..35ce32e 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -603,6 +603,11 @@ qemuDomainFindMaxID(void *payload,
         *driver_maxid = vm->def->id + 1;
 }
 
+static void
+qemuSharedDiskFree(void *entry, const void *name ATTRIBUTE_UNUSED)
+{
+    VIR_FREE(entry);
+}
 
 /**
  * qemuStartup:
@@ -810,7 +815,7 @@ qemuStartup(bool privileged,
     if ((qemu_driver->inactivePciHostdevs = pciDeviceListNew()) == NULL)
         goto error;
 
-    if (!(qemu_driver->sharedDisks = virHashCreate(30, NULL)))
+    if (!(qemu_driver->sharedDisks = virHashCreate(30, qemuSharedDiskFree)))
         goto error;
 
     if (privileged) {
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]