]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
storage: make it easier to find file within chain
authorEric Blake <eblake@redhat.com>
Fri, 12 Oct 2012 22:29:14 +0000 (16:29 -0600)
committerEric Blake <eblake@redhat.com>
Fri, 19 Oct 2012 23:35:10 +0000 (17:35 -0600)
In order to temporarily label files read/write during a commit
operation, we need to crawl the backing chain and find the absolute
file name that needs labeling in the first place, as well as the
name of the file that owns the backing file.

* src/util/storage_file.c (virStorageFileChainLookup): New
function.
* src/util/storage_file.h: Declare it.
* src/libvirt_private.syms (storage_file.h): Export it.

src/libvirt_private.syms
src/util/storage_file.c
src/util/storage_file.h

index 1a0c2f6ce78e5aef44614a8858c5f490a5cbd63d..160573cbd70257cf51f16a79b11d82875f7050b6 100644 (file)
@@ -1132,6 +1132,7 @@ virStorageGenerateQcowPassphrase;
 
 
 # storage_file.h
+virStorageFileChainLookup;
 virStorageFileFormatTypeFromString;
 virStorageFileFormatTypeToString;
 virStorageFileFreeMetadata;
index 2ff444c03bca92fe6049115983214fc67172b73e..882df6ef11a126a4268cf24fc913efafb425ff2e 100644 (file)
@@ -1262,3 +1262,67 @@ const char *virStorageFileGetSCSIKey(const char *path)
     return NULL;
 }
 #endif
+
+/* Given a CHAIN that starts at the named file START, return a string
+ * pointing to either START or within CHAIN that gives the preferred
+ * name for the backing file NAME within that chain.  Pass NULL for
+ * NAME to find the base of the chain.  If META is not NULL, set *META
+ * to the point in the chain that describes NAME (or to NULL if the
+ * backing element is not a file).  If PARENT is not NULL, set *PARENT
+ * to the preferred name of the parent (or to NULL if NAME matches
+ * START).  Since the results point within CHAIN, they must not be
+ * independently freed.  */
+const char *
+virStorageFileChainLookup(virStorageFileMetadataPtr chain, const char *start,
+                          const char *name, virStorageFileMetadataPtr *meta,
+                          const char **parent)
+{
+    virStorageFileMetadataPtr owner;
+    const char *tmp;
+
+    if (!parent)
+        parent = &tmp;
+
+    *parent = NULL;
+    if (name ? STREQ(start, name) || virFileLinkPointsTo(start, name) :
+        !chain->backingStore) {
+        if (meta)
+            *meta = chain;
+        return start;
+    }
+
+    owner = chain;
+    *parent = start;
+    while (owner) {
+        if (!owner->backingStore)
+            goto error;
+        if (!name) {
+            if (!owner->backingMeta ||
+                !owner->backingMeta->backingStore)
+                break;
+        } else if (STREQ_NULLABLE(name, owner->backingStoreRaw) ||
+                   STREQ(name, owner->backingStore)) {
+            break;
+        } else if (owner->backingStoreIsFile) {
+            char *absName = absolutePathFromBaseFile(*parent, name);
+            if (absName && STREQ(absName, owner->backingStore)) {
+                VIR_FREE(absName);
+                break;
+            }
+            VIR_FREE(absName);
+        }
+        *parent = owner->backingStore;
+        owner = owner->backingMeta;
+    }
+    if (!owner)
+        goto error;
+    if (meta)
+        *meta = owner->backingMeta;
+    return owner->backingStore;
+
+error:
+    *parent = NULL;
+    if (meta)
+        *meta = NULL;
+    return NULL;
+}
index 685fcb84610e7310824eefd7a88eff77e766a945..9b00dba28c9774c96b6f9608e536b0c04757f2f2 100644 (file)
@@ -78,6 +78,13 @@ virStorageFileMetadataPtr virStorageFileGetMetadataFromFD(const char *path,
                                                           int fd,
                                                           int format);
 
+const char *virStorageFileChainLookup(virStorageFileMetadataPtr chain,
+                                      const char *start,
+                                      const char *name,
+                                      virStorageFileMetadataPtr *meta,
+                                      const char **parent)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
 void virStorageFileFreeMetadata(virStorageFileMetadataPtr meta);
 
 int virStorageFileResize(const char *path, unsigned long long capacity);