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 e196631..6c66c6e 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;
@@ -143,6 +159,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;
@@ -207,4 +225,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.1