diff --git a/src/storage/storage_backend_logical.c b/src/storage/storage_backend_logical.c index ab1e64befb..ed62c2f2ff 100644 --- a/src/storage/storage_backend_logical.c +++ b/src/storage/storage_backend_logical.c @@ -131,6 +131,15 @@ virStorageBackendLogicalMakeVol(char **const groups, goto cleanup; } + /* Mark the (s) sparse/snapshot lv, e.g. the lv created using + * the --virtualsize/-V option. We've already ignored the (t)hin + * pool definition. In the manner libvirt defines these, the + * thin pool is hidden to the lvs output, except as the name + * in brackets [] described for the groups[1] (backingStore). + */ + if (attrs[0] == 's') + vol->target.sparse = true; + /* Skips the backingStore of lv created with "--virtualsize", * its original device "/dev/$vgname/$lvname_vorigin" is * just for lvm internal use, one should never use it. @@ -752,6 +761,7 @@ virStorageBackendLogicalCreateVol(virConnectPtr conn, VIR_DIV_UP(vol->target.allocation ? vol->target.allocation : 1, 1024)); virCommandAddArg(cmd, "--virtualsize"); + vol->target.sparse = true; } virCommandAddArgFormat(cmd, "%lluK", VIR_DIV_UP(vol->target.capacity, 1024)); @@ -829,6 +839,33 @@ virStorageBackendLogicalBuildVolFrom(virConnectPtr conn, return build_func(conn, pool, vol, inputvol, flags); } +static int +virStorageBackendLogicalVolWipe(virConnectPtr conn, + virStoragePoolObjPtr pool, + virStorageVolDefPtr vol, + unsigned int algorithm, + unsigned int flags) +{ + if (!vol->target.sparse) + return virStorageBackendVolWipeLocal(conn, pool, vol, algorithm, flags); + + /* The wiping algorithms will write something to the logical volume. + * Writing to a sparse logical volume causes it to be filled resulting + * in the volume becoming INACTIVE because there is some amount of + * metadata contained within the sparse lv. Choosing to only write + * a wipe pattern to the already written portion lv based on what + * 'lvs' shows in the "Data%" column/field for the sparse lv was + * considered. However, there is no guarantee that sparse lv could + * grow or shrink outside of libvirt's knowledge and thus still render + * the volume INACTIVE. Until there is some sort of wipe function + * implemented by lvm for one of these sparse lv, we'll just return + * unsupported. + */ + virReportError(VIR_ERR_NO_SUPPORT, + _("logical volue '%s' is sparse, volume wipe not supported"), + vol->target.path); + return -1; +} virStorageBackend virStorageBackendLogical = { .type = VIR_STORAGE_POOL_LOGICAL, @@ -846,5 +883,5 @@ virStorageBackend virStorageBackendLogical = { .deleteVol = virStorageBackendLogicalDeleteVol, .uploadVol = virStorageBackendVolUploadLocal, .downloadVol = virStorageBackendVolDownloadLocal, - .wipeVol = virStorageBackendVolWipeLocal, + .wipeVol = virStorageBackendLogicalVolWipe, }; diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h index c840aa06e2..eccbf4e466 100644 --- a/src/util/virstoragefile.h +++ b/src/util/virstoragefile.h @@ -248,6 +248,7 @@ struct _virStorageSource { virBitmapPtr features; char *compat; bool nocow; + bool sparse; virStoragePermsPtr perms; virStorageTimestampsPtr timestamps;