]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
storage: Disallow vol_wipe for sparse logical volumes
authorJohn Ferlan <jferlan@redhat.com>
Thu, 17 Jul 2014 16:41:43 +0000 (12:41 -0400)
committerJohn Ferlan <jferlan@redhat.com>
Thu, 17 Jul 2014 20:28:59 +0000 (16:28 -0400)
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
src/util/virstoragefile.h

index ab1e64befbb13076289ca8ca73081d49b7a6cfaa..ed62c2f2ff2685f02532e6e592437b3d475aae2b 100644 (file)
@@ -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,
 };
index c840aa06e249a576b1efe2911c3e75749de735e1..eccbf4e4664476a81816867569f7beabcf67588c 100644 (file)
@@ -248,6 +248,7 @@ struct _virStorageSource {
     virBitmapPtr features;
     char *compat;
     bool nocow;
+    bool sparse;
 
     virStoragePermsPtr perms;
     virStorageTimestampsPtr timestamps;