[libvirt] [PATCHv5 07/28] util: storagefile: Add deep copy for struct virStorageSource

Peter Krempa pkrempa at redhat.com
Fri Jul 4 11:29:22 UTC 2014


Now that we have pointers to store disk source information and thus can
easily exchange the structs behind we need a function to copy all the
data.
---
 src/libvirt_private.syms  |   1 +
 src/util/virstoragefile.c | 194 ++++++++++++++++++++++++++++++++++++++++++++--
 src/util/virstoragefile.h |   3 +
 3 files changed, 190 insertions(+), 8 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 29e9db9..918b6d2 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1919,6 +1919,7 @@ virStorageNetHostTransportTypeToString;
 virStorageNetProtocolTypeToString;
 virStorageSourceBackingStoreClear;
 virStorageSourceClear;
+virStorageSourceCopy;
 virStorageSourceFree;
 virStorageSourceGetActualType;
 virStorageSourceGetSecurityLabelDef;
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
index 9208b77..3037435 100644
--- a/src/util/virstoragefile.c
+++ b/src/util/virstoragefile.c
@@ -1719,6 +1719,189 @@ virStorageSourceGetSecurityLabelDef(virStorageSourcePtr src,
 }


+static void
+virStorageSourceSeclabelsClear(virStorageSourcePtr def)
+{
+    size_t i;
+
+    if (def->seclabels) {
+        for (i = 0; i < def->nseclabels; i++)
+            virSecurityDeviceLabelDefFree(def->seclabels[i]);
+        VIR_FREE(def->seclabels);
+    }
+}
+
+
+static int
+virStorageSourceSeclabelsCopy(virStorageSourcePtr to,
+                              const virStorageSource *from)
+{
+    size_t i;
+
+    if (from->nseclabels == 0)
+        return 0;
+
+    if (VIR_ALLOC_N(to->seclabels, from->nseclabels) < 0)
+        return -1;
+    to->nseclabels = from->nseclabels;
+
+    for (i = 0; i < to->nseclabels; i++) {
+        if (!(to->seclabels[i] = virSecurityDeviceLabelDefCopy(from->seclabels[i])))
+            goto error;
+    }
+
+    return 0;
+
+ error:
+    virStorageSourceSeclabelsClear(to);
+    return -1;
+}
+
+
+static virStorageTimestampsPtr
+virStorageTimestampsCopy(const virStorageTimestamps *src)
+{
+    virStorageTimestampsPtr ret;
+
+    if (VIR_ALLOC(ret) < 0)
+        return NULL;
+
+    memcpy(ret, src, sizeof(*src));
+
+    return ret;
+}
+
+
+static virStoragePermsPtr
+virStoragePermsCopy(const virStoragePerms *src)
+{
+    virStoragePermsPtr ret;
+
+    if (VIR_ALLOC(ret) < 0)
+        return NULL;
+
+    ret->mode = src->mode;
+    ret->uid = src->uid;
+    ret->gid = src->gid;
+
+    if (VIR_STRDUP(ret->label, src->label))
+        goto error;
+
+    return ret;
+
+ error:
+    virStoragePermsFree(ret);
+    return NULL;
+}
+
+
+static virStorageSourcePoolDefPtr
+virStorageSourcePoolDefCopy(const virStorageSourcePoolDef *src)
+{
+    virStorageSourcePoolDefPtr ret;
+
+    if (VIR_ALLOC(ret) < 0)
+        return NULL;
+
+    ret->voltype = src->voltype;
+    ret->pooltype = src->pooltype;
+    ret->actualtype = src->actualtype;
+    ret->mode = src->mode;
+
+    if (VIR_STRDUP(ret->pool, src->pool) < 0 ||
+        VIR_STRDUP(ret->volume, src->volume) < 0)
+        goto error;
+
+    return ret;
+
+ error:
+    virStorageSourcePoolDefFree(ret);
+    return NULL;
+}
+
+
+/**
+ * virStorageSourcePtr:
+ *
+ * Deep-copies a virStorageSource structure. If @backing chain is true
+ * then also copies the backing chain recursively, otherwise just
+ * the top element is copied. This function doesn't copy the
+ * storage driver access structure and thus the struct needs to be initialized
+ * separately.
+ */
+virStorageSourcePtr
+virStorageSourceCopy(const virStorageSource *src,
+                     bool backingChain)
+{
+    virStorageSourcePtr ret = NULL;
+
+    if (VIR_ALLOC(ret) < 0)
+        return NULL;
+
+    ret->type = src->type;
+    ret->protocol = src->protocol;
+    ret->format = src->format;
+    ret->allocation = src->allocation;
+    ret->capacity = src->capacity;
+    ret->readonly = src->readonly;
+    ret->shared = src->shared;
+
+    /* storage driver metadata are not copied */
+    ret->drv = NULL;
+
+    if (VIR_STRDUP(ret->path, src->path) < 0 ||
+        VIR_STRDUP(ret->volume, src->volume) < 0 ||
+        VIR_STRDUP(ret->driverName, src->driverName) < 0 ||
+        VIR_STRDUP(ret->relPath, src->relPath) < 0 ||
+        VIR_STRDUP(ret->backingStoreRaw, src->backingStoreRaw) < 0 ||
+        VIR_STRDUP(ret->compat, src->compat) < 0)
+        goto error;
+
+    if (!(ret->hosts = virStorageNetHostDefCopy(src->nhosts, src->hosts)))
+        goto error;
+    ret->nhosts = src->nhosts;
+
+    if (src->srcpool &&
+        !(ret->srcpool = virStorageSourcePoolDefCopy(src->srcpool)))
+        goto error;
+
+    if (src->features &&
+        !(ret->features = virBitmapNewCopy(src->features)))
+        goto error;
+
+    if (src->encryption &&
+        !(ret->encryption = virStorageEncryptionCopy(src->encryption)))
+        goto error;
+
+    if (src->perms &&
+        !(ret->perms = virStoragePermsCopy(src->perms)))
+        goto error;
+
+    if (src->timestamps &&
+        !(ret->timestamps = virStorageTimestampsCopy(src->timestamps)))
+        goto error;
+
+    if (virStorageSourceSeclabelsCopy(ret, src) < 0)
+        goto error;
+
+    if (src->auth &&
+        !(ret->auth = virStorageAuthDefCopy(src->auth)))
+        goto error;
+
+    if (backingChain && src->backingStore) {
+        if (!(ret->backingStore = virStorageSourceCopy(src->backingStore,
+                                                       true)))
+            goto error;
+    }
+
+    return ret;
+
+ error:
+    virStorageSourceFree(ret);
+    return NULL;
+}
+
+
 void
 virStorageSourcePoolDefFree(virStorageSourcePoolDefPtr def)
 {
@@ -1771,11 +1954,11 @@ virStorageSourceBackingStoreClear(virStorageSourcePtr def)
 }


+
+
 void
 virStorageSourceClear(virStorageSourcePtr def)
 {
-    size_t i;
-
     if (!def)
         return;

@@ -1786,12 +1969,7 @@ virStorageSourceClear(virStorageSourcePtr def)
     virBitmapFree(def->features);
     VIR_FREE(def->compat);
     virStorageEncryptionFree(def->encryption);
-
-    if (def->seclabels) {
-        for (i = 0; i < def->nseclabels; i++)
-            virSecurityDeviceLabelDefFree(def->seclabels[i]);
-        VIR_FREE(def->seclabels);
-    }
+    virStorageSourceSeclabelsClear(def);
     virStoragePermsFree(def->perms);
     VIR_FREE(def->timestamps);

diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
index 63950ec..5c0460b 100644
--- a/src/util/virstoragefile.h
+++ b/src/util/virstoragefile.h
@@ -349,6 +349,9 @@ bool virStorageSourceIsLocalStorage(virStorageSourcePtr src);
 void virStorageSourceFree(virStorageSourcePtr def);
 void virStorageSourceBackingStoreClear(virStorageSourcePtr def);
 virStorageSourcePtr virStorageSourceNewFromBacking(virStorageSourcePtr parent);
+virStorageSourcePtr virStorageSourceCopy(const virStorageSource *src,
+                                         bool backingChain)
+    ATTRIBUTE_NONNULL(1);

 typedef int
 (*virStorageFileSimplifyPathReadlinkCallback)(const char *path,
-- 
1.9.3




More information about the libvir-list mailing list