When creating a new volume, it is possible to copy data into it from another already existing volume (referred to as @origvol). Obviously, the read-only access to @origvol is required, which is thread safe (probably not performance-wise though). However, with current code both @newvol and @origvol are marked as building for the time of copying data from the @origvol to @newvol. The rationale behind is to disallow some operations on both @origvol and @newvol, e.g. vol-wipe, vol-delete, vol-download. While it makes sense to not allow such operations on partly copied mirror, but it doesn't make sense to disallow vol-create on the source (@origvol). Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> --- diff to v2: - changed the error message if volume is in use - reworded commit message src/conf/storage_conf.h | 1 + src/storage/storage_driver.c | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h index 9ad38e1..eae959c 100644 --- a/src/conf/storage_conf.h +++ b/src/conf/storage_conf.h @@ -64,6 +64,7 @@ struct _virStorageVolDef { int type; /* enum virStorageVolType */ unsigned int building; + unsigned int in_use; virStorageVolSource source; virStorageSource target; diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index 2cb8347..542b382 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -1640,6 +1640,13 @@ storageVolDelete(virStorageVolPtr obj, if (virStorageVolDeleteEnsureACL(obj->conn, pool->def, vol) < 0) goto cleanup; + if (vol->in_use) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("volume '%s' is still in use."), + vol->name); + goto cleanup; + } + if (vol->building) { virReportError(VIR_ERR_OPERATION_INVALID, _("volume '%s' is still being allocated."), @@ -1912,8 +1919,8 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj, /* Drop the pool lock during volume allocation */ pool->asyncjobs++; - origvol->building = 1; newvol->building = 1; + origvol->in_use++; virStoragePoolObjUnlock(pool); if (origpool) { @@ -1929,7 +1936,7 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj, virStoragePoolObjLock(origpool); storageDriverUnlock(driver); - origvol->building = 0; + origvol->in_use--; newvol->building = 0; allocation = newvol->target.allocation; pool->asyncjobs--; @@ -2076,6 +2083,13 @@ storageVolUpload(virStorageVolPtr obj, if (virStorageVolUploadEnsureACL(obj->conn, pool->def, vol) < 0) goto cleanup; + if (vol->in_use) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("volume '%s' is still in use."), + vol->name); + goto cleanup; + } + if (vol->building) { virReportError(VIR_ERR_OPERATION_INVALID, _("volume '%s' is still being allocated."), @@ -2167,6 +2181,13 @@ storageVolResize(virStorageVolPtr obj, if (virStorageVolResizeEnsureACL(obj->conn, pool->def, vol) < 0) goto cleanup; + if (vol->in_use) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("volume '%s' is still in use."), + vol->name); + goto cleanup; + } + if (vol->building) { virReportError(VIR_ERR_OPERATION_INVALID, _("volume '%s' is still being allocated."), @@ -2474,6 +2495,13 @@ storageVolWipePattern(virStorageVolPtr obj, if (virStorageVolWipePatternEnsureACL(obj->conn, pool->def, vol) < 0) goto cleanup; + if (vol->in_use) { + virReportError(VIR_ERR_OPERATION_INVALID, + _("volume '%s' is still in use."), + vol->name); + goto cleanup; + } + if (vol->building) { virReportError(VIR_ERR_OPERATION_INVALID, _("volume '%s' is still being allocated."), -- 1.9.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list