[libvirt] [PATCH v2 5/9] virstoragefile: Treat backingStore as a pointer or an array

Matthias Gatto matthias.gatto at outscale.com
Wed Jan 28 11:01:33 UTC 2015


On Wed, Jan 28, 2015 at 11:10 AM, Michal Privoznik <mprivozn at redhat.com> wrote:
> On 21.01.2015 16:29, Matthias Gatto wrote:
>> As explain in the former patchs, backingStore can be treat an array or
>> a pointer.
>> If we have only one backingStore we have to use it as a normal ptr
>> but if there is more backing store, we use it as a pointer's array.
>>
>> Because it would be complicated to expend backingStore manually, and do
>> the convertion from a pointer to an array, I've created the
>> virStorageSourcePushBackingStore function to help.
>>
>> This function allocate an array of pointer only if there is more than 1 bs.
>>
>> Because we can not remove a child from a quorum, i didn't create the function
>> virStorageSourcePopBackingStore.
>>
>> I've changed virStorageSourceBackingStoreClear, virStorageSourceSetBackingStore
>> and virStorageSourceGetBackingStore to handle the case where backingStore
>> is an array.
>>
>> Signed-off-by: Matthias Gatto <matthias.gatto at outscale.com>
>> ---
>>  src/conf/storage_conf.c               |  7 ++-
>>  src/libvirt_private.syms              |  1 +
>>  src/storage/storage_backend_fs.c      |  2 +
>>  src/storage/storage_backend_logical.c |  2 +-
>>  src/util/virstoragefile.c             | 89 ++++++++++++++++++++++++++++++++---
>>  src/util/virstoragefile.h             |  2 +
>>  6 files changed, 94 insertions(+), 9 deletions(-)
>>
>> diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
>> index fac85fa..41887eb 100644
>> --- a/src/conf/storage_conf.c
>> +++ b/src/conf/storage_conf.c
>> @@ -1343,7 +1343,12 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool,
>>          if (VIR_ALLOC(backingStorePtr) < 0)
>>              goto error;
>>
>> -        backingStorePtr = virStorageSourceSetBackingStore(&ret->target, backingStorePtr, 0);
>> +        if (!virStorageSourcePushBackingStore(&ret->target))
>> +            goto error;
>> +
>> +        backingStorePtr = virStorageSourceSetBackingStore(&ret->target,
>> +                                                          backingStorePtr,
>> +                                                          ret->target.nBackingStores - 1);
>>          backingStorePtr->path = backingStore;
>>          backingStore = NULL;
>>
>> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
>> index 980235b..5752907 100644
>> --- a/src/libvirt_private.syms
>> +++ b/src/libvirt_private.syms
>> @@ -2033,6 +2033,7 @@ virStorageSourceParseRBDColonString;
>>  virStorageSourcePoolDefFree;
>>  virStorageSourcePoolModeTypeFromString;
>>  virStorageSourcePoolModeTypeToString;
>> +virStorageSourcePushBackingStore;
>>  virStorageSourceSetBackingStore;
>>  virStorageTypeFromString;
>>  virStorageTypeToString;
>> diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
>> index a3b6688..0d8c5ad 100644
>> --- a/src/storage/storage_backend_fs.c
>> +++ b/src/storage/storage_backend_fs.c
>> @@ -112,6 +112,8 @@ virStorageBackendProbeTarget(virStorageSourcePtr target,
>>
>>              if (VIR_ALLOC(backingStore) < 0)
>>                  goto cleanup;
>> +            if (virStorageSourcePushBackingStore(target) == false)
>> +                goto cleanup;
>>              virStorageSourceSetBackingStore(target, backingStore, 0);
>>              backingStore->type = VIR_STORAGE_TYPE_NETWORK;
>>              backingStore->path = meta->backingStoreRaw;
>> diff --git a/src/storage/storage_backend_logical.c b/src/storage/storage_backend_logical.c
>> index fcec31f..cd8de85 100644
>> --- a/src/storage/storage_backend_logical.c
>> +++ b/src/storage/storage_backend_logical.c
>> @@ -148,7 +148,7 @@ virStorageBackendLogicalMakeVol(char **const groups,
>>       *  lv is created with "--virtualsize").
>>       */
>>      if (groups[1] && !STREQ(groups[1], "") && (groups[1][0] != '[')) {
>> -        if (VIR_ALLOC(vol->target.backingStore) < 0)
>> +        if (virStorageSourcePushBackingStore(&vol->target) == false)
>>              goto cleanup;
>>
>>          if (virAsprintf(&virStorageSourceGetBackingStore(&vol->target, 0)->path, "%s/%s",
>> diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
>> index ba38827..554aa8b 100644
>> --- a/src/util/virstoragefile.c
>> +++ b/src/util/virstoragefile.c
>> @@ -1798,21 +1798,88 @@ virStorageSourcePoolDefCopy(const virStorageSourcePoolDef *src)
>>  }
>>
>>
>> +/**
>> + * virStorageSourceGetBackingStore:
>> + * @src: virStorageSourcePtr containing the backing stores
>> + * @pos: position of the backing store to get
>> + *
>> + * return the backingStore at the position of @pos
>> + */
>>  virStorageSourcePtr
>> -virStorageSourceGetBackingStore(const virStorageSource *src,
>> -                                size_t pos ATTRIBUTE_UNUSED)
>> +virStorageSourceGetBackingStore(const virStorageSource *src, size_t pos)
>> +{
>> +    if (!src->backingStore || (pos > 1 && pos >= src->nBackingStores))
>> +        return NULL;
>> +    if (src->nBackingStores < 2)
>> +        return src->backingStore;
>> +    return ((virStorageSourcePtr *)src->backingStore)[pos];
>> +}
>> +
>> +
>> +/**
>> + * virStorageSourcePushBackingStore:
>> + * @src: virStorageSourcePtr to allocate the new backing store
>> + *
>> + * Allocate size for a new backingStorePtr in src->backingStore
>> + * and update src->nBackingStores
>> + * If we have less than 2 backing stores, we treat src->backingStore
>> + * as a pointer otherwise we treat it as an array of virStorageSourcePtr
>> + */
>> +bool
>> +virStorageSourcePushBackingStore(virStorageSourcePtr src)
>>  {
>> -    return src->backingStore;
>> +    virStorageSourcePtr     tmp;
>> +    virStorageSourcePtr     *tmp2;
>> +
>> +    if (!src)
>> +        return false;
>> +    if (src->nBackingStores == 1) {
>> +        /* If we need more than one backing store we need an array
>> +         * Because we don't want to lose our data from the old Backing Store
>> +         * we copy the pointer from src->backingStore to src->backingStore[0] */
>> +        tmp = src->backingStore;
>> +        if (VIR_ALLOC_N(tmp2, 1) < 0)
>> +            return false;
>> +        src->backingStore = (virStorageSourcePtr)tmp2;
>> +        src->nBackingStores += 1;
>> +        virStorageSourceSetBackingStore(src, tmp, 0);
>> +    } else if (src->nBackingStores > 1) {
>> +        tmp2 = ((virStorageSourcePtr *)src->backingStore);
>> +        if (VIR_EXPAND_N(tmp2, src->nBackingStores, 1) < 0)
>> +            return false;
>> +        src->backingStore = (virStorageSourcePtr)tmp2;
>> +    } else {
>> +        /* Most of the time we use only one backingStore
>> +         * So we don't need to allocate an array */
>> +        src->nBackingStores += 1;
>> +    }
>> +    return true;
>
> I must say I find this logic very hard to read. What's the problem with
> really using src->backingStore as an array?
>
>>  }
>>
>>
>> +/**
>> + * virStorageSourceSetBackingStore:
>> + * @src: virStorageSourcePtr to hold @backingStore
>> + * @backingStore: backingStore to store
>> + * @pos: position of the backing store to store
>> + *
>> + * Set @backingStore at @pos in src->backingStore
>> + */
>>  virStorageSourcePtr
>>  virStorageSourceSetBackingStore(virStorageSourcePtr src,
>>                                  virStorageSourcePtr backingStore,
>> -                                size_t pos ATTRIBUTE_UNUSED)
>> +                                size_t pos)
>>  {
>> -    src->backingStore = backingStore;
>> -    return src->backingStore;
>> +    if (!src || (pos > 1 && pos >= src->nBackingStores))
>> +        goto error;
>> +    if (src->nBackingStores > 1) {
>> +        ((virStorageSourcePtr *)src->backingStore)[pos] = backingStore;
>> +    } else {
>> +        src->backingStore = backingStore;
>> +    }
>> +    return backingStore;
>> + error:
>> +    return NULL;
>>  }
>>
>>
>> @@ -2023,6 +2090,8 @@ virStorageSourceIsEmpty(virStorageSourcePtr src)
>>  void
>>  virStorageSourceBackingStoreClear(virStorageSourcePtr def)
>>  {
>> +    size_t i;
>> +
>>      if (!def)
>>          return;
>>
>> @@ -2030,7 +2099,13 @@ virStorageSourceBackingStoreClear(virStorageSourcePtr def)
>>      VIR_FREE(def->backingStoreRaw);
>>
>>      /* recursively free backing chain */
>> -    virStorageSourceFree(virStorageSourceGetBackingStore(def, 0));
>> +    for (i = 0; i < def->nBackingStores; ++i)
>> +        virStorageSourceFree(virStorageSourceGetBackingStore(def, i));
>> +    if (def->nBackingStores > 1) {
>> +        /* in this case def->backingStores is treat as an array so we have to free it*/
>> +        VIR_FREE(def->backingStore);
>> +    }
>> +    def->nBackingStores = 0;
>>      virStorageSourceSetBackingStore(def, NULL, 0);
>>  }
>>
>> diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
>> index d5cf7e6..74c363b 100644
>> --- a/src/util/virstoragefile.h
>> +++ b/src/util/virstoragefile.h
>> @@ -271,6 +271,7 @@ struct _virStorageSource {
>>
>>      /* backing chain of the storage source */
>>      virStorageSourcePtr backingStore;
>> +    size_t      nBackingStores;
>
> How can this fly? In the code you're still accessing it as an array of
> pointers, but here it's defined as array of structs. So you're just
> lucky the struct is bigger than a pointer. This should rather be:
>
> diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
> index 74c363b..11fb96d 100644
> --- a/src/util/virstoragefile.h
> +++ b/src/util/virstoragefile.h
> @@ -270,8 +270,8 @@ struct _virStorageSource {
>      bool shared;
>
>      /* backing chain of the storage source */
> -    virStorageSourcePtr backingStore;
> -    size_t      nBackingStores;
> +    virStorageSourcePtr *backingStore;
> +    size_t nBackingStores;
>
>      /* metadata for storage driver access to remote and local volumes */
>      virStorageDriverDataPtr drv;
>
>
> I'm stopping my review here until the time I get some clarification here.
>
> Michal

I was trying to follow this:
http://www.redhat.com/archives/libvir-list/2014-May/msg00546.html ,
and I think I've
misunderstand this: "PtrPtr doesn't make sense.  Just keep it as a
single pointer, but add an
nBackingStores field and treat it as an array (all existing callers are
now an array of 1, quorum is a new array of N)"

But if I can use a 'Ptr *' I wil, change my code.

Thanks you for the review.

Matthias




More information about the libvir-list mailing list