[libvirt] [PATCH v2 4/5] In storageVolumeCreateXML, spawn a new thread for volbuilding, in storageVolumeDelete, generate the signal

Guannan Ren gren at redhat.com
Sun Jul 17 10:45:00 UTC 2011


---
 src/storage/storage_backend.c |    9 ++++
 src/storage/storage_driver.c  |   83 ++++++++++++++++++++++++++++++++++++-----
 2 files changed, 82 insertions(+), 10 deletions(-)

diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index f632edd..bc10933 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -1632,3 +1632,12 @@ virStorageBackendRunProgNul(virConnectPtr conn,
     return -1;
 }
 #endif /* WIN32 */
+
+void virStorageBackendVoluCleanup(void *arg)
+{
+
+    volBuildThreadPtr data = arg;
+
+    data->buildret = 0;
+    data->threadEnd = 1;
+}
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index 997b876..d8ac648 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -48,6 +48,7 @@
 #include "files.h"
 #include "fdstream.h"
 #include "configmake.h"
+#include "threads.h"
 
 #define VIR_FROM_THIS VIR_FROM_STORAGE
 
@@ -1276,6 +1277,29 @@ cleanup:
 
 static int storageVolumeDelete(virStorageVolPtr obj, unsigned int flags);
 
+static void virStorageBuildVol(void *arg)
+{
+    int ret = -1;
+    volBuildThreadPtr data = arg;
+    virStoragePoolObjPtr pool = data->pool;
+    virStorageVolDefPtr vol = data->vol;
+
+    pthread_cleanup_push(virStorageBackendVoluCleanup, data);
+
+    ret = data->buildvol(data->obj->conn, pool, vol);
+
+    pthread_cleanup_pop(0);
+
+    data->buildret = ret;
+    data->threadEnd = 1;
+}
+
+static int
+virStorageProcessJobSignals(virThreadPtr th)
+{
+    return virThreadCancel(th);
+}
+
 static virStorageVolPtr
 storageVolumeCreateXML(virStoragePoolPtr obj,
                        const char *xmldesc,
@@ -1353,28 +1377,63 @@ storageVolumeCreateXML(virStoragePoolPtr obj,
             goto cleanup;
         }
 
+        volBuildThreadPtr volbuild = NULL;
+        if (VIR_ALLOC(volbuild) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
         /* Make a shallow copy of the 'defined' volume definition, since the
          * original allocation value will change as the user polls 'info',
          * but we only need the initial requested values
          */
         memcpy(buildvoldef, voldef, sizeof(*voldef));
 
-        /* Drop the pool lock during volume allocation */
         pool->asyncjobs++;
         voldef->building = 1;
-        virStoragePoolObjUnlock(pool);
+        virThread th;
+        volbuild->buildvol = backend->buildVol;
+        volbuild->obj = obj;
+        volbuild->pool = pool;
+        volbuild->vol = buildvoldef;
+        volbuild->buildret = -1;
+
+        if (virThreadCreate(&th, true,
+                                virStorageBuildVol,
+                                volbuild) < 0){
+                virReportSystemError(errno, "%s",
+                              _("Unable to create migration thread"));
+                goto buildingend;
+
+        }
 
-        buildret = backend->buildVol(obj->conn, pool, buildvoldef);
+        while(!volbuild->threadEnd){
+                if(pool->jobSignals){
+                        if(virStorageProcessJobSignals(&th) < 0)
+                                goto buildingend;
+                }
+
+                virStoragePoolObjUnlock(pool);
+
+                storageDriverLock(driver);
+                virStoragePoolObjLock(pool);
+                storageDriverUnlock(driver);
+        }
 
-        storageDriverLock(driver);
-        virStoragePoolObjLock(pool);
-        storageDriverUnlock(driver);
 
+        virThreadJoin(&th);
+
+    buildingend:
+        buildret = volbuild->buildret;
+
+        pool->jobSignals = 0;
         voldef->building = 0;
+        virCondBroadcast(&pool->cond);
         pool->asyncjobs--;
 
         voldef = NULL;
         VIR_FREE(buildvoldef);
+        VIR_FREE(volbuild);
 
         if (buildret < 0) {
             virStoragePoolObjUnlock(pool);
@@ -1936,10 +1995,14 @@ storageVolumeDelete(virStorageVolPtr obj,
     }
 
     if (vol->building) {
-        virStorageReportError(VIR_ERR_OPERATION_INVALID,
-                              _("volume '%s' is still being allocated."),
-                              vol->name);
-        goto cleanup;
+        pool->jobSignals |= VOL_JOB_SIGNAL_CANCEL;
+        while(vol->building){
+                if(virCondWait(&pool->cond, &pool->lock) < 0){
+                        virStorageReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                              _("unable to wait on storage condition"));
+                        goto cleanup;
+                }
+        }
     }
 
     if (!backend->deleteVol) {
-- 
1.7.1




More information about the libvir-list mailing list