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 | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_conf.h | 30 +++++++++
2 files changed, 190 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index dc4d680..98eb1b5 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -745,3 +745,163 @@ qemuDriverCloseCallbackRunAll(struct qemud_driver *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.
+ */
+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)) {
+ 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 = list->disks[list->ndisks];
+
+ if (VIR_ALLOC_N(list->disks[list->ndisks]->domains, 1) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ disk->path = strdup(disk_path);
+ disk->ndomains = 1;
+ disk->domains[0] = strdup(domain_name);
+ }
+
+ 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 2c7f70c..45e5eaa 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -50,6 +50,22 @@
typedef struct _qemuDriverCloseDef qemuDriverCloseDef;
typedef qemuDriverCloseDef *qemuDriverCloseDefPtr;
+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 qemud_driver {
virMutex lock;
@@ -140,6 +156,8 @@ struct qemud_driver {
/* The devices which is are not in use by the host or any guest. */
pciDeviceList *inactivePciHostdevs;
+ qemuSharedDiskListPtr sharedDisks;
+
virBitmapPtr reservedRemotePorts;
virSysinfoDefPtr hostsysinfo;
@@ -204,4 +222,16 @@ qemuDriverCloseCallback qemuDriverCloseCallbackGet(struct
qemud_driver *driver,
void qemuDriverCloseCallbackRunAll(struct qemud_driver *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