Daniel P. Berrange e3a592
From ac5067f1e2e98181ee0e9230f756697f50d853eb Mon Sep 17 00:00:00 2001
Daniel P. Berrange e3a592
From: Daniel P. Berrange <berrange@redhat.com>
Daniel P. Berrange e3a592
Date: Mon, 14 Jun 2010 18:09:15 +0100
Daniel P. Berrange e3a592
Subject: [PATCH 05/11] Add an API for iterating over disk paths
Daniel P. Berrange e3a592
Daniel P. Berrange e3a592
There is duplicated code which iterates over disk backing stores
Daniel P. Berrange e3a592
performing some action. Provide a convenient helper for doing
Daniel P. Berrange e3a592
this to eliminate duplication & risk of mistakes with disk format
Daniel P. Berrange e3a592
probing
Daniel P. Berrange e3a592
Daniel P. Berrange e3a592
* src/conf/domain_conf.c, src/conf/domain_conf.h,
Daniel P. Berrange e3a592
  src/libvirt_private.syms: Add virDomainDiskDefForeachPath()
Daniel P. Berrange e3a592
---
Daniel P. Berrange e3a592
 src/conf/domain_conf.c   |   99 ++++++++++++++++++++++++++++++++++++++++++++++
Daniel P. Berrange e3a592
 src/conf/domain_conf.h   |   11 +++++
Daniel P. Berrange e3a592
 src/libvirt_private.syms |    1 +
Daniel P. Berrange e3a592
 3 files changed, 111 insertions(+), 0 deletions(-)
Daniel P. Berrange e3a592
Daniel P. Berrange e3a592
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
Daniel P. Berrange e3a592
index 378c06e..b20ca97 100644
Daniel P. Berrange e3a592
--- a/src/conf/domain_conf.c
Daniel P. Berrange e3a592
+++ b/src/conf/domain_conf.c
Daniel P. Berrange e3a592
@@ -45,6 +45,7 @@
Daniel P. Berrange e3a592
 #include "macvtap.h"
Daniel P. Berrange e3a592
 #include "nwfilter_conf.h"
Daniel P. Berrange e3a592
 #include "ignore-value.h"
Daniel P. Berrange e3a592
+#include "storage_file.h"
Daniel P. Berrange e3a592
 
Daniel P. Berrange e3a592
 #define VIR_FROM_THIS VIR_FROM_DOMAIN
Daniel P. Berrange e3a592
 
Daniel P. Berrange e3a592
@@ -7273,4 +7274,102 @@ done:
Daniel P. Berrange e3a592
 }
Daniel P. Berrange e3a592
 
Daniel P. Berrange e3a592
 
Daniel P. Berrange e3a592
+int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
Daniel P. Berrange e3a592
+                                bool allowProbing,
Daniel P. Berrange e3a592
+                                bool ignoreOpenFailure,
Daniel P. Berrange e3a592
+                                virDomainDiskDefPathIterator iter,
Daniel P. Berrange e3a592
+                                void *opaque)
Daniel P. Berrange e3a592
+{
Daniel P. Berrange e3a592
+    virHashTablePtr paths;
Daniel P. Berrange e3a592
+    int format;
Daniel P. Berrange e3a592
+    int ret = -1;
Daniel P. Berrange e3a592
+    size_t depth = 0;
Daniel P. Berrange e3a592
+    char *nextpath = NULL;
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+    if (!disk->src)
Daniel P. Berrange e3a592
+        return 0;
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+    if (disk->driverType) {
Daniel P. Berrange e3a592
+        const char *formatStr = disk->driverType;
Daniel P. Berrange e3a592
+        if (STREQ(formatStr, "aio"))
Daniel P. Berrange e3a592
+            formatStr = "raw"; /* Xen compat */
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+        if ((format = virStorageFileFormatTypeFromString(formatStr)) < 0) {
Daniel P. Berrange e3a592
+            virDomainReportError(VIR_ERR_INTERNAL_ERROR,
Daniel P. Berrange e3a592
+                                 _("unknown disk format '%s' for %s"),
Daniel P. Berrange e3a592
+                                 disk->driverType, disk->src);
Daniel P. Berrange e3a592
+            return -1;
Daniel P. Berrange e3a592
+        }
Daniel P. Berrange e3a592
+    } else {
Daniel P. Berrange e3a592
+        if (allowProbing) {
Daniel P. Berrange e3a592
+            format = VIR_STORAGE_FILE_AUTO;
Daniel P. Berrange e3a592
+        } else {
Daniel P. Berrange e3a592
+            virDomainReportError(VIR_ERR_INTERNAL_ERROR,
Daniel P. Berrange e3a592
+                                 _("no disk format for %s and probing is disabled"),
Daniel P. Berrange e3a592
+                                 disk->src);
Daniel P. Berrange e3a592
+            return -1;
Daniel P. Berrange e3a592
+        }
Daniel P. Berrange e3a592
+    }
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+    paths = virHashCreate(5);
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+    do {
Daniel P. Berrange e3a592
+        virStorageFileMetadata meta;
Daniel P. Berrange e3a592
+        const char *path = nextpath ? nextpath : disk->src;
Daniel P. Berrange e3a592
+        int fd;
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+        if (iter(disk, path, depth, opaque) < 0)
Daniel P. Berrange e3a592
+            goto cleanup;
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+        if (virHashLookup(paths, path)) {
Daniel P. Berrange e3a592
+            virDomainReportError(VIR_ERR_INTERNAL_ERROR,
Daniel P. Berrange e3a592
+                                 _("backing store for %s is self-referential"),
Daniel P. Berrange e3a592
+                                 disk->src);
Daniel P. Berrange e3a592
+            goto cleanup;
Daniel P. Berrange e3a592
+        }
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+        if ((fd = open(path, O_RDONLY)) < 0) {
Daniel P. Berrange e3a592
+            if (ignoreOpenFailure) {
Daniel P. Berrange e3a592
+                char ebuf[1024];
Daniel P. Berrange e3a592
+                VIR_WARN("Ignoring open failure on %s: %s", path,
Daniel P. Berrange e3a592
+                         virStrerror(errno, ebuf, sizeof(ebuf)));
Daniel P. Berrange e3a592
+                break;
Daniel P. Berrange e3a592
+            } else {
Daniel P. Berrange e3a592
+                virReportSystemError(errno,
Daniel P. Berrange e3a592
+                                     _("unable to open disk path %s"),
Daniel P. Berrange e3a592
+                                     path);
Daniel P. Berrange e3a592
+                goto cleanup;
Daniel P. Berrange e3a592
+            }
Daniel P. Berrange e3a592
+        }
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+        if (virStorageFileGetMetadataFromFD(path, fd, format, &meta) < 0) {
Daniel P. Berrange e3a592
+            close(fd);
Daniel P. Berrange e3a592
+            goto cleanup;
Daniel P. Berrange e3a592
+        }
Daniel P. Berrange e3a592
+        close(fd);
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+        if (virHashAddEntry(paths, path, (void*)0x1) < 0) {
Daniel P. Berrange e3a592
+            virReportOOMError();
Daniel P. Berrange e3a592
+            goto cleanup;
Daniel P. Berrange e3a592
+        }
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+        depth++;
Daniel P. Berrange e3a592
+        nextpath = meta.backingStore;
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+        format = meta.backingStoreFormat;
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+        if (format == VIR_STORAGE_FILE_AUTO &&
Daniel P. Berrange e3a592
+            !allowProbing)
Daniel P. Berrange e3a592
+            format = VIR_STORAGE_FILE_RAW; /* Stops further recursion */
Daniel P. Berrange e3a592
+    } while (nextpath);
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+    ret = 0;
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+cleanup:
Daniel P. Berrange e3a592
+    virHashFree(paths, NULL);
Daniel P. Berrange e3a592
+    VIR_FREE(nextpath);
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+    return ret;
Daniel P. Berrange e3a592
+}
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
 #endif /* ! PROXY */
Daniel P. Berrange e3a592
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
Daniel P. Berrange e3a592
index 01da17e..d46869e 100644
Daniel P. Berrange e3a592
--- a/src/conf/domain_conf.h
Daniel P. Berrange e3a592
+++ b/src/conf/domain_conf.h
Daniel P. Berrange e3a592
@@ -1079,6 +1079,17 @@ int virDomainChrDefForeach(virDomainDefPtr def,
Daniel P. Berrange e3a592
                            void *opaque);
Daniel P. Berrange e3a592
 
Daniel P. Berrange e3a592
 
Daniel P. Berrange e3a592
+typedef int (*virDomainDiskDefPathIterator)(virDomainDiskDefPtr disk,
Daniel P. Berrange e3a592
+                                            const char *path,
Daniel P. Berrange e3a592
+                                            size_t depth,
Daniel P. Berrange e3a592
+                                            void *opaque);
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
+int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
Daniel P. Berrange e3a592
+                                bool allowProbing,
Daniel P. Berrange e3a592
+                                bool ignoreOpenFailure,
Daniel P. Berrange e3a592
+                                virDomainDiskDefPathIterator iter,
Daniel P. Berrange e3a592
+                                void *opaque);
Daniel P. Berrange e3a592
+
Daniel P. Berrange e3a592
 VIR_ENUM_DECL(virDomainVirt)
Daniel P. Berrange e3a592
 VIR_ENUM_DECL(virDomainBoot)
Daniel P. Berrange e3a592
 VIR_ENUM_DECL(virDomainFeature)
Daniel P. Berrange e3a592
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
Daniel P. Berrange e3a592
index 4607f49..b5f3695 100644
Daniel P. Berrange e3a592
--- a/src/libvirt_private.syms
Daniel P. Berrange e3a592
+++ b/src/libvirt_private.syms
Daniel P. Berrange e3a592
@@ -225,6 +225,7 @@ virDomainSnapshotDefFormat;
Daniel P. Berrange e3a592
 virDomainSnapshotAssignDef;
Daniel P. Berrange e3a592
 virDomainObjAssignDef;
Daniel P. Berrange e3a592
 virDomainChrDefForeach;
Daniel P. Berrange e3a592
+virDomainDiskDefForeachPath;
Daniel P. Berrange e3a592
 
Daniel P. Berrange e3a592
 
Daniel P. Berrange e3a592
 # domain_event.h
Daniel P. Berrange e3a592
-- 
Daniel P. Berrange e3a592
1.7.1.1
Daniel P. Berrange e3a592