[libvirt] [PATCH 01/15] qemu: Introduce a list to maintain the shared disks between domains

Osier Yang jyang at redhat.com
Wed Dec 5 09:25:02 UTC 2012


A single entry of the list is constructed by the _disk path_ and
a sub-list of domain names which are using the disk.

* src/qemu/qemu_conf.h (New struct qemuSharedDisk, qemuSharedDiskList;
                        New type qemuSharedDiskPtr, qemuSharedDiskListPtr;
                        Declare the helpers qemuSharedDiskListFree,
                        qemuSharedDiskListAdd, qemuSharedDiskListFind,
                        qemuSharedDiskListDel)
* src/qemu/qemu_conf.c (Implement the helpers)
---
 src/qemu/qemu_conf.c |  170 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_conf.h |   30 +++++++++
 2 files changed, 200 insertions(+), 0 deletions(-)

diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 8d380a1..4fdfb8c 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -556,3 +556,173 @@ qemuDriverCloseCallbackRunAll(virQEMUDriverPtr driver,
 
     virHashForEach(driver->closeCallbacks, qemuDriverCloseCallbackRun, &data);
 }
+
+void
+qemuSharedDiskListFree(qemuSharedDiskListPtr list)
+{
+    int i;
+    int j;
+
+    for (i = 0; i < list->ndisks; i++) {
+        VIR_FREE(list->disks[i]->path);
+
+        for (j = 0; j < list->disks[i]->ndomains; j++)
+            VIR_FREE(list->disks[i]->domains[j]);
+        VIR_FREE(list->disks[i]->domains);
+        VIR_FREE(list->disks[i]);
+    }
+    VIR_FREE(list);
+}
+
+/* Return the matched entry on success, with @idx set as
+ * the index of the matched entry. Or NULL on failure.
+ *
+ * If @domain_name is passed as NULL, it simply returns
+ * the entry which matches the @disk_path.
+ */
+qemuSharedDiskPtr
+qemuSharedDiskListFind(qemuSharedDiskListPtr list,
+                       const char *disk_path,
+                       const char *domain_name,
+                       int *idx)
+{
+    int i;
+    int j;
+
+    for (i = 0; i < list->ndisks; i++) {
+        if (STREQ(disk_path, list->disks[i]->path)) {
+            if (!domain_name)
+                return list->disks[i];
+
+            for (j = 0; j < list->disks[i]->ndomains; j++) {
+                if (STREQ(domain_name, list->disks[i]->domains[j])) {
+                    *idx = i;
+                    return list->disks[i];
+                }
+            }
+        }
+    }
+
+    return NULL;
+}
+
+int
+qemuSharedDiskListAdd(qemuSharedDiskListPtr list,
+                      const char *disk_path,
+                      const char *domain_name)
+{
+    int i;
+    bool existed = false;
+
+    if (qemuSharedDiskListFind(list, disk_path, domain_name, NULL)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("disk '%s' of domain '%s' is already "
+                         "maintained"), disk_path, domain_name);
+        return -1;
+    }
+
+    for (i = 0; i < list->ndisks; i++) {
+        qemuSharedDiskPtr disk = list->disks[i];
+
+        /* Append the domain name to the existed entry */
+        if (STREQ(disk->path, disk_path)) {
+            if (VIR_REALLOC_N(disk->domains,
+                              disk->ndomains + 1) < 0) {
+                virReportOOMError();
+                return -1;
+            }
+
+            disk->domains[disk->ndomains++] = strdup(domain_name);
+            existed = true;
+            break;
+        }
+    }
+
+    /* No existed entry for the @disk_path yet */
+    if (!existed) {
+        if (VIR_REALLOC_N(list->disks, list->ndisks + 1) < 0) {
+            virReportOOMError();
+            return -1;
+        }
+
+        qemuSharedDiskPtr disk = NULL;
+
+        if ((VIR_ALLOC(disk) < 0) ||
+            (VIR_ALLOC_N(disk->domains, 1) < 0)) {
+            virReportOOMError();
+            return -1;
+        }
+
+        disk->path = strdup(disk_path);
+        disk->ndomains = 1;
+        disk->domains[0] = strdup(domain_name);
+
+        list->disks[list->ndisks] = disk;
+        list->ndisks++;
+    }
+
+    return 0;
+}
+
+int
+qemuSharedDiskListDel(qemuSharedDiskListPtr list,
+                      const char *disk_path,
+                      const char *domain_name)
+{
+    qemuSharedDiskPtr disk = NULL;
+    int i;
+    int idx;
+
+    if (!qemuSharedDiskListFind(list, disk_path, domain_name, &idx)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("disk '%s' of domain '%s' is not "
+                         "maintained yet"), disk_path, domain_name);
+        return -1;
+    }
+
+    disk = list->disks[idx];
+
+    if (disk->ndomains == 1) {
+        /* Free the disk entry if there is only one domain using it */
+        if (idx != list->ndisks - 1)
+            memmove(&list->disks[idx],
+                    &list->disks[idx + 1],
+                    sizeof(*list->disks) * (list->ndisks - idx - 1));
+
+        if (VIR_REALLOC_N(list->disks, list->ndisks - 1) < 0) {
+            virReportOOMError();
+            return -1;
+        }
+
+        VIR_FREE(disk->domains[0]);
+        VIR_FREE(disk->domains);
+        VIR_FREE(disk->path);
+        VIR_FREE(disk);
+        list->ndisks--;
+    } else {
+        /* Otherwise just remove the domain name from the sub-list
+         * list->disk[i]->domains.
+         */
+        for (i = 0; i < disk->ndomains; i++) {
+            if (STREQ(disk->domains[i], domain_name)) {
+                char *name = disk->domains[i];
+
+                if (i != disk->ndomains - 1)
+                    memmove(&disk->domains[i],
+                            &disk->domains[i + 1],
+                            sizeof(*disk->domains) * (disk->ndomains - i - 1));
+
+                if (VIR_REALLOC_N(disk->domains, disk->ndomains - 1) < 0) {
+                    virReportOOMError();
+                    return -1;
+                }
+
+                disk->ndomains--;
+                VIR_FREE(name);
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index d0d25ce..01768f7 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -53,6 +53,22 @@ typedef qemuDriverCloseDef *qemuDriverCloseDefPtr;
 typedef struct _virQEMUDriver virQEMUDriver;
 typedef virQEMUDriver *virQEMUDriverPtr;
 
+typedef struct _qemuSharedDisk qemuSharedDisk;
+typedef struct _qemuSharedDiskList qemuSharedDiskList;
+typedef qemuSharedDiskList *qemuSharedDiskListPtr;
+typedef qemuSharedDisk *qemuSharedDiskPtr;
+
+struct _qemuSharedDisk {
+    char *path;     /* Disk path */
+    char **domains; /* List of domain names which share the disk */
+    int ndomains;
+};
+
+struct _qemuSharedDiskList {
+    int ndisks;
+    qemuSharedDiskPtr *disks;
+};
+
 /* Main driver state */
 struct _virQEMUDriver {
     virMutex lock;
@@ -147,6 +163,8 @@ struct _virQEMUDriver {
     /* The devices which is are not in use by the host or any guest. */
     pciDeviceList *inactivePciHostdevs;
 
+    qemuSharedDiskListPtr sharedDisks;
+
     virBitmapPtr reservedRemotePorts;
 
     virSysinfoDefPtr hostsysinfo;
@@ -211,4 +229,16 @@ qemuDriverCloseCallback qemuDriverCloseCallbackGet(virQEMUDriverPtr driver,
 void qemuDriverCloseCallbackRunAll(virQEMUDriverPtr driver,
                                    virConnectPtr conn);
 
+void qemuSharedDiskListFree(qemuSharedDiskListPtr list);
+int qemuSharedDiskListAdd(qemuSharedDiskListPtr list,
+                          const char *disk_path,
+                          const char *domain_name);
+qemuSharedDiskPtr qemuSharedDiskListFind(qemuSharedDiskListPtr list,
+                                         const char *disk_path,
+                                         const char *domain_name,
+                                         int *idx);
+int qemuSharedDiskListDel(qemuSharedDiskListPtr list,
+                          const char *disk_path,
+                          const char *domain_name);
+
 #endif /* __QEMUD_CONF_H */
-- 
1.7.7.6




More information about the libvir-list mailing list