---
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