[libvirt] [PATCHv2 11/16] storage: make it easier to find file within chain

Laine Stump laine at laine.org
Tue Oct 16 15:55:19 UTC 2012


On 10/13/2012 06:00 PM, Eric Blake wrote:
> 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 |  1 +
>  src/util/storage_file.c  | 63 ++++++++++++++++++++++++++++++++++++++++++++++++
>  src/util/storage_file.h  |  7 ++++++
>  3 files changed, 71 insertions(+)
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index fe31bbe..e40d630 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -1125,6 +1125,7 @@ virStorageGenerateQcowPassphrase;
>
>
>  # storage_file.h
> +virStorageFileChainLookup;
>  virStorageFileFormatTypeFromString;
>  virStorageFileFormatTypeToString;
>  virStorageFileFreeMetadata;
> diff --git a/src/util/storage_file.c b/src/util/storage_file.c
> index 6f299c0..218891e 100644
> --- a/src/util/storage_file.c
> +++ b/src/util/storage_file.c
> @@ -1260,3 +1260,66 @@ const char *virStorageFileGetSCSIKey(const char *path)
>      return NULL;
>  }
>  #endif
> +
> +/* Given a CHAIN that starts at the named file START, return the
> + * canonical name for the backing file NAME within that chain, or pass
> + * NULL to find the base of the chain.  If *META is not NULL, set it
> + * 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 it to
> + * the canonical name of the parent (or to NULL if NAME matches
> + * START).  The results point within CHAIN, and 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) {

Hmm. First time I've ever seen ?: used inside an if statement (since for
me the entire purpose of ?: is to eliminate the need for an if). Maybe
this would be more quickly parseable as (the admittedly longer):

     if ((name & (STREQ(start, name) || virFileLinkPointsTo(start,
name))) ||
         (!name && !chain->backingStore)) {

Not mandatory though.

> +        if (meta)
> +            *meta = chain;
> +        return start;

Don't you need to make sure start is an absolute path?


> +    }
> +
> +    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 *abs = absolutePathFromBaseFile(*parent, name);
> +            if (abs && STREQ(abs, owner->backingStore)) {
> +                VIR_FREE(abs);
> +                break;
> +            }
> +            VIR_FREE(abs);
> +        }
> +        *parent = owner->backingStore;
> +        owner = owner->backingMeta;
> +    }
> +    if (!owner)
> +        goto error;
> +    if (meta)
> +        *meta = owner->backingMeta;
> +    return owner->backingStore;

and I'm recalling from the previous patch that owner->backingStore is
already stored in its canonical form, right?

> +
> +error:
> +    *parent = NULL;
> +    if (meta)
> +        *meta = NULL;
> +    return NULL;
> +}
> diff --git a/src/util/storage_file.h b/src/util/storage_file.h
> index 685fcb8..9b00dba 100644
> --- a/src/util/storage_file.h
> +++ b/src/util/storage_file.h
> @@ -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);

ACK as-is if start doesn't need to be canonicalized (i.e. if I didn't
understand :-), otherwise ACK with that change.




More information about the libvir-list mailing list