On 06/12/2014 09:02 AM, Peter Krempa wrote:
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 | 150 ++++++++++++++++++++++++++++++++++++++++++++++
src/util/virstoragefile.h | 2 +
3 files changed, 153 insertions(+)
+virStorageSourcePtr
+virStorageSourceCopy(const virStorageSource *src,
+ bool backingChain)
+{
+ size_t i;
+ 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->backingRelative = src->backingRelative;
If I'm not mistaken, backingRelative disappears in your other series;
I'm guessing you plan on rebasing that on top of this to pick up on the
easier semantics.
+
+ /* storage driver metadata are not copied */
+ ret->drv = NULL;
Seems okay, particularly since doing a deep copy of that would require
callback functions in the storage drivers.
+
+ 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->relDir, src->relDir) < 0 ||
+ VIR_STRDUP(ret->backingStoreRaw, src->backingStoreRaw) < 0 ||
+ VIR_STRDUP(ret->compat, src->compat) < 0 ||
+ VIR_STRDUP(ret->auth.username, src->auth.username) < 0)
+ goto error;
...
+
+ ret->auth.secretType = src->auth.secretType;
+ switch ((virStorageSecretType) src->auth.secretType) {
+ case VIR_STORAGE_SECRET_TYPE_NONE:
+ case VIR_STORAGE_SECRET_TYPE_LAST:
+ break;
It might be worth adding an intermediate patch to break out the embedded
auth struct into a formal top-level struct, then add a function that
copies an auth struct, rather than having to inline all the nested
struct work here. But for now I can live with it.
+ if (backingChain && src->backingStore) {
+ if (!(ret->backingStore = virStorageSourceCopy(src->backingStore,
+ true)))
+ goto error;
+ }
Nice - we have the choice of shallow or deep chain copy.
Random thought - I wonder if it would be better to make
virStorageSourcePtr inherit from virObject, and make it
reference-counted, so that we can share a single object among multiple
users rather than copying users right and left. But even if it is a
good idea, it's enough refactoring that I don't think we need to tackle
it right away.
+
+ ret->nseclabels = src->nseclabels;
+ if (VIR_ALLOC_N(ret->seclabels, ret->nseclabels) < 0)
+ goto error;
Maybe consider swapping those two lines. Unlike my comment in patch
1/5, in _this_ case, we were careful enough that virStorageSourceClear
checks seclabels for non-NULL before paying attention to nseclabels.
But as we are not consistently careful in the clear/free functions, it's
more robust to just get in the habit of setting the count after the
allocation is successful without having to check a particular free
function. Hmm - do I dare suggest simplifying virStorageSourceClear to
unconditionally iterate over nseclabels instead of hiding it in an 'if
(def->seclabels)' block? Or is it better form to suggest that all
cleanup functions be audited to be robust to non-zero count but NULL arrays?
+++ b/src/util/virstoragefile.h
@@ -324,6 +324,8 @@ int virStorageSourceGetActualType(virStorageSourcePtr def);
void virStorageSourceFree(virStorageSourcePtr def);
void virStorageSourceClearBackingStore(virStorageSourcePtr def);
virStorageSourcePtr virStorageSourceNewFromBacking(virStorageSourcePtr parent);
+virStorageSourcePtr virStorageSourceCopy(const virStorageSource *src,
+ bool backingChain);
ATTRIBUTE_NONNULL(1)
ACK
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library
http://libvirt.org