On Wed, Jan 28, 2015 at 11:10 AM, Michal Privoznik <mprivozn@xxxxxxxxxx> 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@xxxxxxxxxxxx> >> --- >> 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list