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   |   99 ++++++++++++++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h   |   11 +++++
 src/libvirt_private.syms |    1 +
 3 files changed, 111 insertions(+), 0 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 378c06e..b20ca97 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -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 */
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 01da17e..d46869e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -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)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4607f49..b5f3695 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -225,6 +225,7 @@ virDomainSnapshotDefFormat;
 virDomainSnapshotAssignDef;
 virDomainObjAssignDef;
 virDomainChrDefForeach;
+virDomainDiskDefForeachPath;
 
 
 # domain_event.h
-- 
1.7.1.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to