[libvirt] [PATCHv2 15/33] storage: Switch metadata crawler to use storage driver to get unique path

Peter Krempa pkrempa at redhat.com
Thu May 22 13:47:54 UTC 2014


Use the virStorageFileGetUniqueIdentifier() function to get a unique
identifier regardless of the target storage type instead of relying on
canonicalize_path().

A new function that checks wether we support a given image is introduced
to avoid errors for unimplemented backends.
---
 src/storage/storage_driver.c | 77 +++++++++++++++++++++++++++++++-------------
 1 file changed, 54 insertions(+), 23 deletions(-)

diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index cd4c6b5..eebb7ee 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -2788,6 +2788,30 @@ virStorageFileIsInitialized(virStorageSourcePtr src)
     return !!src->drv;
 }

+
+static bool
+virStorageFileSupportsBackingChainTraversal(virStorageSourcePtr src)
+{
+    int actualType = virStorageSourceGetActualType(src);
+    virStorageFileBackendPtr backend;
+
+    if (!src)
+        return false;
+
+    if (src->drv) {
+        backend = src->drv->backend;
+    } else {
+        if (!(backend = virStorageFileBackendForTypeInternal(actualType,
+                                                             src->protocol,
+                                                             false)))
+            return false;
+    }
+
+    return backend->storageFileGetUniqueIdentifier &&
+           backend->storageFileReadHeader &&
+           backend->storageFileAccess;
+}
+
 void
 virStorageFileDeinit(virStorageSourcePtr src)
 {
@@ -3104,7 +3128,6 @@ virFindBackingFile(const char *start, const char *path,
 /* Recursive workhorse for virStorageFileGetMetadata.  */
 static int
 virStorageFileGetMetadataRecurse(virStorageSourcePtr src,
-                                 const char *canonPath,
                                  uid_t uid, gid_t gid,
                                  bool allow_probe,
                                  virHashTablePtr cycle)
@@ -3112,49 +3135,63 @@ virStorageFileGetMetadataRecurse(virStorageSourcePtr src,
     int fd;
     int ret = -1;
     struct stat st;
+    const char *uniqueName;
     virStorageSourcePtr backingStore = NULL;
     int backingFormat;

-    VIR_DEBUG("path=%s canonPath=%s dir=%s format=%d uid=%d gid=%d probe=%d",
-              src->path, canonPath, NULLSTR(src->relDir), src->format,
+    VIR_DEBUG("path=%s dir=%s format=%d uid=%d gid=%d probe=%d",
+              src->path, NULLSTR(src->relDir), src->format,
               (int)uid, (int)gid, allow_probe);

-    if (virHashLookup(cycle, canonPath)) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("backing store for %s is self-referential"),
-                       src->path);
+    /* exit if we can't load information about the current image */
+    if (!virStorageFileSupportsBackingChainTraversal(src))
+        return 0;
+
+    if (virStorageFileInitAs(src, uid, gid) < 0)
         return -1;
+
+    if (!(uniqueName = virStorageFileGetUniqueIdentifier(src)))
+        goto cleanup;
+
+    if (virHashLookup(cycle, uniqueName)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("backing store for %s (%s) is self-referential"),
+                       src->path, uniqueName);
+        goto cleanup;
     }

-    if (virHashAddEntry(cycle, canonPath, (void *)1) < 0)
-        return -1;
+    if (virHashAddEntry(cycle, uniqueName, (void *)1) < 0)
+        goto cleanup;

     if (virStorageSourceGetActualType(src) != VIR_STORAGE_TYPE_NETWORK) {
         if ((fd = virFileOpenAs(src->path, O_RDONLY, 0, uid, gid, 0)) < 0) {
             virReportSystemError(-fd, _("Failed to open file '%s'"),
                                  src->path);
-            return -1;
+            goto cleanup;
         }

         if (virStorageFileGetMetadataFromFDInternal(src, fd,
                                                     &backingFormat) < 0) {
             VIR_FORCE_CLOSE(fd);
-            return -1;
+            goto cleanup;
         }

         if (VIR_CLOSE(fd) < 0)
             VIR_WARN("could not close file %s", src->path);
     } else {
         /* TODO: currently we call this only for local storage */
-        return 0;
+        ret = 0;
+        goto cleanup;
     }

     /* check whether we need to go deeper */
-    if (!src->backingStoreRaw)
-        return 0;
+    if (!src->backingStoreRaw) {
+        ret = 0;
+        goto cleanup;
+    }

     if (VIR_ALLOC(backingStore) < 0)
-        return -1;
+        goto cleanup;

     if (VIR_STRDUP(backingStore->relPath, src->backingStoreRaw) < 0)
         goto cleanup;
@@ -3201,7 +3238,6 @@ virStorageFileGetMetadataRecurse(virStorageSourcePtr src,
         backingStore->format = backingFormat;

     if (virStorageFileGetMetadataRecurse(backingStore,
-                                         backingStore->path,
                                          uid, gid, allow_probe,
                                          cycle) < 0) {
         /* if we fail somewhere midway, just accept and return a
@@ -3215,6 +3251,7 @@ virStorageFileGetMetadataRecurse(virStorageSourcePtr src,
     ret = 0;

  cleanup:
+    virStorageFileDeinit(src);
     virStorageSourceFree(backingStore);
     return ret;
 }
@@ -3253,12 +3290,6 @@ virStorageFileGetMetadata(virStorageSourcePtr src,
         return -1;

     if (virStorageSourceGetActualType(src) != VIR_STORAGE_TYPE_NETWORK) {
-        if (!(canonPath = canonicalize_file_name(src->path))) {
-            virReportSystemError(errno, _("unable to resolve '%s'"),
-                                 src->path);
-            goto cleanup;
-        }
-
         if (!src->relPath &&
             VIR_STRDUP(src->relPath, src->path) < 0)
             goto cleanup;
@@ -3277,7 +3308,7 @@ virStorageFileGetMetadata(virStorageSourcePtr src,
     if (src->format <= VIR_STORAGE_FILE_NONE)
         src->format = allow_probe ? VIR_STORAGE_FILE_AUTO : VIR_STORAGE_FILE_RAW;

-    ret = virStorageFileGetMetadataRecurse(src, canonPath, uid, gid,
+    ret = virStorageFileGetMetadataRecurse(src, uid, gid,
                                            allow_probe, cycle);

  cleanup:
-- 
1.9.3




More information about the libvir-list mailing list