--- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list