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(a)outscale.com>
---
src/conf/storage_conf.c | 3 +-
src/libvirt_private.syms | 1 +
src/storage/storage_backend_fs.c | 2 +-
src/storage/storage_backend_logical.c | 2 +-
src/util/virstoragefile.c | 87 ++++++++++++++++++++++++++++++++---
src/util/virstoragefile.h | 2 +
6 files changed, 87 insertions(+), 10 deletions(-)
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index a8a90b4..fc51d47 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -1340,8 +1340,9 @@ virStorageVolDefParseXML(virStoragePoolDefPtr pool,
}
if ((backingStore = virXPathString("string(./backingStore/path)", ctxt)))
{
- if (VIR_ALLOC(ret->target.backingStore) < 0)
+ if (VIR_ALLOC_N(ret->target.backingStore, 1) < 0)
goto error;
+ ret->target.nBackingStores = 1;
ret->target.backingStore->path = backingStore;
backingStore = NULL;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index dd83518..71e8625 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2002,6 +2002,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 07fd6ee..979abd3 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -107,7 +107,7 @@ virStorageBackendProbeTarget(virStorageSourcePtr target,
if (!virStorageSourceIsLocalStorage(virStorageSourceGetBackingStore(target, 0)))
{
virStorageSourceFree(virStorageSourceGetBackingStore(target, 0));
- if (VIR_ALLOC(target->backingStore) < 0)
+ if (virStorageSourcePushBackingStore(target) == false)
goto cleanup;
target->backingStore->type = VIR_STORAGE_TYPE_NETWORK;
diff --git a/src/storage/storage_backend_logical.c
b/src/storage/storage_backend_logical.c
index 300c990..edec124 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(&vol->target.backingStore->path, "%s/%s",
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
index 20f45f3..4217a80 100644
--- a/src/util/virstoragefile.c
+++ b/src/util/virstoragefile.c
@@ -1814,21 +1814,86 @@ 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)
{
- return src->backingStore;
+ 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 backing store 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)
+{
+ virStorageSourcePtr tmp;
+ virStorageSourcePtr *tmp2;
+
+ 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;
+}
+
+
+/**
+ * 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;
}
@@ -2038,6 +2103,8 @@ virStorageSourceIsEmpty(virStorageSourcePtr src)
void
virStorageSourceBackingStoreClear(virStorageSourcePtr def)
{
+ size_t i;
+
if (!def)
return;
@@ -2045,7 +2112,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 4cba66b..d28138f 100644
--- a/src/util/virstoragefile.h
+++ b/src/util/virstoragefile.h
@@ -270,6 +270,7 @@ struct _virStorageSource {
/* backing chain of the storage source */
virStorageSourcePtr backingStore;
+ size_t nBackingStores;
/* metadata for storage driver access to remote and local volumes */
virStorageDriverDataPtr drv;
@@ -293,6 +294,7 @@ virStorageSourcePtr
virStorageSourceSetBackingStore(virStorageSourcePtr src,
size_t pos);
virStorageSourcePtr virStorageSourceGetBackingStore(const virStorageSource *src,
size_t pos);
+bool virStorageSourcePushBackingStore(virStorageSourcePtr src);
int virStorageFileProbeFormat(const char *path, uid_t uid, gid_t gid);
int virStorageFileProbeFormatFromBuf(const char *path,
--
1.8.3.1