]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Add an API for iterating over disk paths
authorDaniel P. Berrange <berrange@redhat.com>
Mon, 14 Jun 2010 17:09:15 +0000 (18:09 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Mon, 19 Jul 2010 17:25:13 +0000 (18:25 +0100)
There is duplicated code which iterates over disk backing stores
performing some action. Provide a convenient helper for doing
this to eliminate duplication & risk of mistakes with disk format
probing

* src/conf/domain_conf.c, src/conf/domain_conf.h,
  src/libvirt_private.syms: Add virDomainDiskDefForeachPath()

src/conf/domain_conf.c
src/conf/domain_conf.h
src/libvirt_private.syms

index 378c06ef0a976b7a7a524de0eadbcc99b508bfdd..b20ca975e5c1ff5074f3f3989837ded5d1008c77 100644 (file)
@@ -45,6 +45,7 @@
 #include "macvtap.h"
 #include "nwfilter_conf.h"
 #include "ignore-value.h"
+#include "storage_file.h"
 
 #define VIR_FROM_THIS VIR_FROM_DOMAIN
 
@@ -7273,4 +7274,102 @@ done:
 }
 
 
+int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
+                                bool allowProbing,
+                                bool ignoreOpenFailure,
+                                virDomainDiskDefPathIterator iter,
+                                void *opaque)
+{
+    virHashTablePtr paths;
+    int format;
+    int ret = -1;
+    size_t depth = 0;
+    char *nextpath = NULL;
+
+    if (!disk->src)
+        return 0;
+
+    if (disk->driverType) {
+        const char *formatStr = disk->driverType;
+        if (STREQ(formatStr, "aio"))
+            formatStr = "raw"; /* Xen compat */
+
+        if ((format = virStorageFileFormatTypeFromString(formatStr)) < 0) {
+            virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                 _("unknown disk format '%s' for %s"),
+                                 disk->driverType, disk->src);
+            return -1;
+        }
+    } else {
+        if (allowProbing) {
+            format = VIR_STORAGE_FILE_AUTO;
+        } else {
+            virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                 _("no disk format for %s and probing is disabled"),
+                                 disk->src);
+            return -1;
+        }
+    }
+
+    paths = virHashCreate(5);
+
+    do {
+        virStorageFileMetadata meta;
+        const char *path = nextpath ? nextpath : disk->src;
+        int fd;
+
+        if (iter(disk, path, depth, opaque) < 0)
+            goto cleanup;
+
+        if (virHashLookup(paths, path)) {
+            virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                 _("backing store for %s is self-referential"),
+                                 disk->src);
+            goto cleanup;
+        }
+
+        if ((fd = open(path, O_RDONLY)) < 0) {
+            if (ignoreOpenFailure) {
+                char ebuf[1024];
+                VIR_WARN("Ignoring open failure on %s: %s", path,
+                         virStrerror(errno, ebuf, sizeof(ebuf)));
+                break;
+            } else {
+                virReportSystemError(errno,
+                                     _("unable to open disk path %s"),
+                                     path);
+                goto cleanup;
+            }
+        }
+
+        if (virStorageFileGetMetadataFromFD(path, fd, format, &meta) < 0) {
+            close(fd);
+            goto cleanup;
+        }
+        close(fd);
+
+        if (virHashAddEntry(paths, path, (void*)0x1) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        depth++;
+        nextpath = meta.backingStore;
+
+        format = meta.backingStoreFormat;
+
+        if (format == VIR_STORAGE_FILE_AUTO &&
+            !allowProbing)
+            format = VIR_STORAGE_FILE_RAW; /* Stops further recursion */
+    } while (nextpath);
+
+    ret = 0;
+
+cleanup:
+    virHashFree(paths, NULL);
+    VIR_FREE(nextpath);
+
+    return ret;
+}
+
 #endif /* ! PROXY */
index 01da17e5e2d049b5a1b112218f2b85b03e5310a3..d46869e44ff0479b96a557f7eeec3af976dd3a55 100644 (file)
@@ -1079,6 +1079,17 @@ int virDomainChrDefForeach(virDomainDefPtr def,
                            void *opaque);
 
 
+typedef int (*virDomainDiskDefPathIterator)(virDomainDiskDefPtr disk,
+                                            const char *path,
+                                            size_t depth,
+                                            void *opaque);
+
+int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
+                                bool allowProbing,
+                                bool ignoreOpenFailure,
+                                virDomainDiskDefPathIterator iter,
+                                void *opaque);
+
 VIR_ENUM_DECL(virDomainVirt)
 VIR_ENUM_DECL(virDomainBoot)
 VIR_ENUM_DECL(virDomainFeature)
index 4607f49bf4e5db2139b684a6b6a8956b21e4fa71..b5f36953bbb4a407ac61094b9f3c03966928291a 100644 (file)
@@ -225,6 +225,7 @@ virDomainSnapshotDefFormat;
 virDomainSnapshotAssignDef;
 virDomainObjAssignDef;
 virDomainChrDefForeach;
+virDomainDiskDefForeachPath;
 
 
 # domain_event.h