From 8a9f7cbecd91932eff669830fd26e775a240afd6 Mon Sep 17 00:00:00 2001 From: John Ferlan Date: Thu, 17 Jul 2014 12:41:43 -0400 Subject: [PATCH] storage: Disallow vol_wipe for sparse logical volumes https://bugzilla.redhat.com/show_bug.cgi?id=1091866 Add a new boolean 'sparse'. This will be used by the logical backend storage driver to determine whether the target volume is sparse or not (also known by a snapshot or thin logical volume). Although setting sparse to true at creation could be seen as duplicitous to setting during virStorageBackendLogicalMakeVol() in case there are ever other code paths between Create and FindLVs that need to know about the volume be sparse. Use the 'sparse' in a new virStorageBackendLogicalVolWipe() to decide whether to attempt to wipe the logical volume or not. For now, I have found no means to wipe the volume without writing to it. Writing to the sparse volume causes it to be filled. A sparse logical volume is not completely writeable as there exists metadata which if overwritten will cause the sparse lv to go INACTIVE which means pool-refresh will not find it. Access to whatever lvm uses to manage data blocks is not provided by any API I could find. --- src/storage/storage_backend_logical.c | 39 ++++++++++++++++++++++++++- src/util/virstoragefile.h | 1 + 2 files changed, 39 insertions(+), 1 deletion(-) 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;