[libvirt] [PATCH] storage: Refresh storage pool after upload

John Ferlan jferlan at redhat.com
Mon Jul 28 13:24:39 UTC 2014


https://bugzilla.redhat.com/show_bug.cgi?id=1072653

Upon successful upload of a volume, the target volume and storage pool
were not updated to reflect any changes as a result of the upload. Make
use of the existing stream close callback mechanism to force a backend
pool refresh to occur once the stream closes.

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 src/libvirt.c                |  8 +++++
 src/libvirt_private.syms     |  1 +
 src/storage/storage_driver.c | 78 ++++++++++++++++++++++++++++++++++++++++++++
 tools/virsh.pod              |  3 ++
 4 files changed, 90 insertions(+)

diff --git a/src/libvirt.c b/src/libvirt.c
index 143d319..992e4f2 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -13960,6 +13960,14 @@ virStorageVolDownload(virStorageVolPtr vol,
  * detect any errors. The results will be unpredictable if
  * another active stream is writing to the storage volume.
  *
+ * When the data stream is closed whether the upload is successful
+ * or not the target storage pool will be refreshed to reflect pool
+ * and volume changes as a result of the upload. Depending on
+ * the target volume storage backend and the source stream type
+ * for a successful upload, the target volume may take on the
+ * characteristics from the source stream such as format type,
+ * capacity, and allocation.
+ *
  * Returns 0, or -1 upon error.
  */
 int
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index b1fb7c9..7ef68a1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -825,6 +825,7 @@ virFDStreamCreateFile;
 virFDStreamOpen;
 virFDStreamOpenFile;
 virFDStreamOpenPTY;
+virFDStreamSetInternalCloseCb;
 
 
 # libvirt_internal.h
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index efbe5ff..5fd5514 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -59,6 +59,12 @@ static virStorageDriverStatePtr driverState;
 
 static int storageStateCleanup(void);
 
+typedef struct _virStorageVolStreamInfo virStorageVolStreamInfo;
+typedef virStorageVolStreamInfo *virStorageVolStreamInfoPtr;
+struct _virStorageVolStreamInfo {
+    char *pool_name;
+};
+
 static void storageDriverLock(virStorageDriverStatePtr driver)
 {
     virMutexLock(&driver->lock);
@@ -1956,6 +1962,52 @@ storageVolDownload(virStorageVolPtr obj,
 }
 
 
+/**
+ * Frees opaque data provided for the stream closing callback
+ *
+ * @opaque Data to be freed.
+ */
+static void virStorageVolFDStreamCloseCbFree(void *opaque)
+{
+    virStorageVolStreamInfoPtr cbdata = opaque;
+
+    VIR_FREE(cbdata->pool_name);
+    VIR_FREE(cbdata);
+}
+
+/**
+ * Callback being called if a FDstream is closed. Frees device entries
+ * from data structures and removes lockfiles.
+ *
+ * @st Pointer to stream being closed.
+ * @opaque Domain's device information structure.
+ */
+static void virStorageVolFDStreamCloseCb(virStreamPtr st ATTRIBUTE_UNUSED,
+                                         void *opaque)
+{
+
+    virStorageVolStreamInfoPtr cbdata = opaque;
+    virStoragePoolObjPtr pool = NULL;
+    virStorageBackendPtr backend;
+
+    storageDriverLock(driverState);
+    if (!(pool = virStoragePoolObjFindByName(&driverState->pools,
+                                             cbdata->pool_name)))
+        goto cleanup;
+
+    if (!(backend = virStorageBackendForType(pool->def->type)))
+        goto cleanup;
+
+    virStoragePoolObjClearVols(pool);
+    if (backend->refreshPool(NULL, pool) < 0)
+        VIR_DEBUG("Failed to refresh storage pool");
+
+ cleanup:
+    if (pool)
+        virStoragePoolObjUnlock(pool);
+    storageDriverUnlock(driverState);
+}
+
 static int
 storageVolUpload(virStorageVolPtr obj,
                  virStreamPtr stream,
@@ -1966,6 +2018,7 @@ storageVolUpload(virStorageVolPtr obj,
     virStorageBackendPtr backend;
     virStoragePoolObjPtr pool = NULL;
     virStorageVolDefPtr vol = NULL;
+    virStorageVolStreamInfoPtr cbdata = NULL;
     int ret = -1;
 
     virCheckFlags(0, -1);
@@ -1996,11 +2049,36 @@ storageVolUpload(virStorageVolPtr obj,
         goto cleanup;
     }
 
+    /* If we have a refreshPool, use the callback routine in order to
+     * refresh the pool after the volume upload stream closes. This way
+     * we make sure the volume and pool data are refreshed without user
+     * interaction and we can just lookup the backend in the callback
+     * routine in order to call the refresh API.
+     */
+    if (backend->refreshPool) {
+        if (VIR_ALLOC(cbdata) < 0 ||
+            VIR_STRDUP(cbdata->pool_name, pool->def->name) < 0)
+            goto cleanup;
+    }
+
     ret = backend->uploadVol(obj->conn, pool, vol, stream,
                              offset, length, flags);
 
+    /* Add cleanup callback - call after uploadVol since the stream
+     * is then fully set up
+     */
+    if (cbdata) {
+        virFDStreamSetInternalCloseCb(stream,
+                                      virStorageVolFDStreamCloseCb,
+                                      cbdata,
+                                      virStorageVolFDStreamCloseCbFree);
+        cbdata = NULL;
+    }
+
  cleanup:
     virStoragePoolObjUnlock(pool);
+    if (cbdata)
+        virStorageVolFDStreamCloseCbFree(cbdata);
 
     return ret;
 }
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 849ae31..e377df9 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2981,6 +2981,9 @@ of the amount of data to be uploaded. A negative value is interpreted
 as an unsigned long long value to essentially include everything from
 the offset to the end of the volume.
 An error will occur if the I<local-file> is greater than the specified length.
+See the description for the libvirt virStorageVolUpload API for details
+regarding possible target volume and pool changes as a result of the
+pool refresh when the upload is attempted.
 
 =item B<vol-download> [I<--pool> I<pool-or-uuid>] [I<--offset> I<bytes>]
 [I<--length> I<bytes>] I<vol-name-or-key-or-path> I<local-file>
-- 
1.9.3




More information about the libvir-list mailing list