Skip to contentSkip to conversation

Add ioctl to clear unused space

PATCH In review David Sterba 3 participants 9 messages Apr 20, 2018 – Jun 7, 2018 Btrfs file system

lore
Share & tools
lore

David Sterba

author maintainer
#0 lore raw

cover Add ioctl to clear unused space

This patchset adds new ioctl similar to TRIM, that provides several other ways how to clear the unused space. The changelogs are incomplete, for preview not for inclusion yet.

It compiles and has been tested lightly, the clearing modes depend on hw capabilities (secure discard, sector unmapping instead of zeros), so I've tested only zeroing and discard.

I personally think the zeroing has a usecase and the other modes were easy to add. Further extensions can be considered, eg. WRITE_SAME, overwriting with a randomly generated pattern, or some filesystem canary patterns that can be used to report unused block read as metadata.

As this is modelled after the generic FITRIM ioctl, so this could be a new generic ioctl too. However, last time somebody wanted such ioctl, there was a pushback. I'll consider making a generic version and send it for comments to fsdevel eventually.

git://github.com/kdave/btrfs-devel dev/zero-free

David Sterba (6):
btrfs: extend trim callchain to pass the operation type
btrfs: add wrapper to switch clearing operation
btrfs: add zeroing clear operation
btrfs: add new ioctl BTRFS_IOC_CLEAR_FREE
btrfs: add discard secure to clear unused space
btrfs: add more zeroout modes for clearing unused space

 fs/btrfs/ctree.h            |   5 +-
 fs/btrfs/extent-tree.c      | 130 ++++++++++++++++++++++++++++++++++++++------
 fs/btrfs/free-space-cache.c |  22 +++++---
 fs/btrfs/free-space-cache.h |   3 +-
 fs/btrfs/ioctl.c            |  42 ++++++++++++++
 include/uapi/linux/btrfs.h  |  26 +++++++++
 6 files changed, 199 insertions(+), 29 deletions(-)
Signature · 1 line
2.16.2
author maintainer
#1 lore raw

PATCH 1/6 btrfs: extend trim callchain to pass the operation type

This is preparatory work to implement clearing free space by zeroing, much in the same way the FITRIM ioctl works. This patch simply defines a symbolic name for the current clearing operation and passes the parameter around. No functional change.

---
 fs/btrfs/ctree.h            | 11 ++++++++-
 fs/btrfs/extent-tree.c      | 54 +++++++++++++++++++++++++++++++--------------
 fs/btrfs/free-space-cache.c | 22 ++++++++++--------
 fs/btrfs/free-space-cache.h |  3 ++-
 4 files changed, 62 insertions(+), 28 deletions(-)
fs/btrfs/ctree.h +10 -1
index 5474ef14d6e6..7cde72683b8e 100644
@@ -674,6 +674,14 @@ struct btrfs_stripe_hash {
 	spinlock_t lock;
 };
 
+/*
+ * Type of operation that will be used to clear unused blocks.
+ */
+enum btrfs_clear_op_type {
+	BTRFS_CLEAR_OP_DISCARD = 0,
+	BTRFS_NR_CLEAR_OP_TYPES,
+};
+
 /* used by the raid56 code to lock stripes for read/modify/write */
 struct btrfs_stripe_hash_table {
 	struct list_head stripe_cache;
@@ -2789,7 +2797,8 @@ u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo);
 int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info,
 				   u64 start, u64 end);
 int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr,
-			 u64 num_bytes, u64 *actual_bytes);
+			 u64 num_bytes, u64 *actual_bytes,
+			 enum btrfs_clear_op_type clear);
 int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans,
 			    struct btrfs_fs_info *fs_info, u64 type);
 int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range);
fs/btrfs/extent-tree.c +37 -17

142 lines not on this page · raw message

fs/btrfs/free-space-cache.c +13 -9
index e5b569bebc73..be7bfb99df9a 100644
@@ -3102,7 +3102,8 @@ void btrfs_init_free_cluster(struct btrfs_free_cluster *cluster)
 static int do_trimming(struct btrfs_block_group_cache *block_group,
 		       u64 *total_trimmed, u64 start, u64 bytes,
 		       u64 reserved_start, u64 reserved_bytes,
-		       struct btrfs_trim_range *trim_entry)
+		       struct btrfs_trim_range *trim_entry,
+		       enum btrfs_clear_op_type clear)
 {
 	struct btrfs_space_info *space_info = block_group->space_info;
 	struct btrfs_fs_info *fs_info = block_group->fs_info;
@@ -3121,7 +3122,7 @@ static int do_trimming(struct btrfs_block_group_cache *block_group,
 	spin_unlock(&block_group->lock);
 	spin_unlock(&space_info->lock);
 
-	ret = btrfs_discard_extent(fs_info, start, bytes, &trimmed);
+	ret = btrfs_discard_extent(fs_info, start, bytes, &trimmed, clear);
 	if (!ret)
 		*total_trimmed += trimmed;
 
@@ -3145,7 +3146,8 @@ static int do_trimming(struct btrfs_block_group_cache *block_group,
 }
 
 static int trim_no_bitmap(struct btrfs_block_group_cache *block_group,
-			  u64 *total_trimmed, u64 start, u64 end, u64 minlen)
+			  u64 *total_trimmed, u64 start, u64 end, u64 minlen,
+			  enum btrfs_clear_op_type clear)
 {
 	struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
 	struct btrfs_free_space *entry;
@@ -3212,7 +3214,7 @@ static int trim_no_bitmap(struct btrfs_block_group_cache *block_group,
 		mutex_unlock(&ctl->cache_writeout_mutex);
 
 		ret = do_trimming(block_group, total_trimmed, start, bytes,
-				  extent_start, extent_bytes, &trim_entry);
+				extent_start, extent_bytes, &trim_entry, clear);
 		if (ret)
 			break;
 next:
@@ -3230,7 +3232,8 @@ static int trim_no_bitmap(struct btrfs_block_group_cache *block_group,
 }
 
 static int trim_bitmaps(struct btrfs_block_group_cache *block_group,
-			u64 *total_trimmed, u64 start, u64 end, u64 minlen)
+			u64 *total_trimmed, u64 start, u64 end, u64 minlen,
+			enum btrfs_clear_op_type clear)
 {
 	struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
 	struct btrfs_free_space *entry;
@@ -3287,7 +3290,7 @@ static int trim_bitmaps(struct btrfs_block_group_cache *block_group,
 		mutex_unlock(&ctl->cache_writeout_mutex);
 
 		ret = do_trimming(block_group, total_trimmed, start, bytes,
-				  start, bytes, &trim_entry);
+				  start, bytes, &trim_entry, clear);
 		if (ret)
 			break;
 next:
@@ -3355,7 +3358,8 @@ void btrfs_put_block_group_trimming(struct btrfs_block_group_cache *block_group)
 }
 
 int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
-			   u64 *trimmed, u64 start, u64 end, u64 minlen)
+			   u64 *trimmed, u64 start, u64 end, u64 minlen,
+			   enum btrfs_clear_op_type clear)
 {
 	int ret;
 
@@ -3369,11 +3373,11 @@ int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
 	btrfs_get_block_group_trimming(block_group);
 	spin_unlock(&block_group->lock);
 
-	ret = trim_no_bitmap(block_group, trimmed, start, end, minlen);
+	ret = trim_no_bitmap(block_group, trimmed, start, end, minlen, clear);
 	if (ret)
 		goto out;
 
-	ret = trim_bitmaps(block_group, trimmed, start, end, minlen);
+	ret = trim_bitmaps(block_group, trimmed, start, end, minlen, clear);
 out:
 	btrfs_put_block_group_trimming(block_group);
 	return ret;
fs/btrfs/free-space-cache.h +2 -1
index 15e30b93db0d..794a444c3f73 100644
@@ -107,7 +107,8 @@ int btrfs_return_cluster_to_free_space(
 			       struct btrfs_block_group_cache *block_group,
 			       struct btrfs_free_cluster *cluster);
 int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
-			   u64 *trimmed, u64 start, u64 end, u64 minlen);
+			   u64 *trimmed, u64 start, u64 end, u64 minlen,
+			   enum btrfs_clear_op_type clear);
 
 /* Support functions for running our sanity tests */
 #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
Signature · 1 line
2.16.2
author maintainer
#2 lore raw

PATCH 2/6 btrfs: add wrapper to switch clearing operation

In reply to David Sterba
---
 fs/btrfs/extent-tree.c | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)
fs/btrfs/extent-tree.c +14 -11
index ffdd3aba508c..b317f8ee42a9 100644
@@ -2034,6 +2034,18 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans,
 	return ret;
 }
 
+static int btrfs_issue_clear_op(struct block_device *bdev, u64 start, u64 size,
+		enum btrfs_clear_op_type clear)
+{
+	switch (clear) {
+	case BTRFS_CLEAR_OP_DISCARD:
+		return blkdev_issue_discard(bdev, start >> 9, size >> 9,
+				GFP_NOFS, 0);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 #define in_range(b, first, len)        ((b) >= (first) && (b) < (first) + (len))
 static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len,
 			       u64 *discarded_bytes,
@@ -2081,13 +2093,8 @@ static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len,
 			bytes_left = end - start;
 			continue;
 		}
-
 		if (size) {
-			if (clear == BTRFS_CLEAR_OP_DISCARD)
-				ret = blkdev_issue_discard(bdev, start >> 9,
-						size >> 9, GFP_NOFS, 0);
-			else
-				ret = -EOPNOTSUPP;
+			ret = btrfs_issue_clear_op(bdev, start, size, clear);
 			if (!ret)
 				*discarded_bytes += size;
 			else if (ret != -EOPNOTSUPP)
@@ -2103,11 +2110,7 @@ static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len,
 	}
 
 	if (bytes_left) {
-		if (clear == BTRFS_CLEAR_OP_DISCARD)
-			ret = blkdev_issue_discard(bdev, start >> 9,
-					bytes_left >> 9, GFP_NOFS, 0);
-		else
-			ret = -EOPNOTSUPP;
+		ret = btrfs_issue_clear_op(bdev, start, bytes_left, clear);
 		if (!ret)
 			*discarded_bytes += bytes_left;
 	}
Signature · 1 line
2.16.2
author maintainer
#3 lore raw

PATCH 3/6 btrfs: add zeroing clear operation

In reply to David Sterba
---
 fs/btrfs/ctree.h       | 1 +
 fs/btrfs/extent-tree.c | 3 +++
 2 files changed, 4 insertions(+)
fs/btrfs/ctree.h +1 -0
index 7cde72683b8e..772cb4ccc5f7 100644
@@ -679,6 +679,7 @@ struct btrfs_stripe_hash {
  */
 enum btrfs_clear_op_type {
 	BTRFS_CLEAR_OP_DISCARD = 0,
+	BTRFS_CLEAR_OP_ZERO,
 	BTRFS_NR_CLEAR_OP_TYPES,
 };
 
fs/btrfs/extent-tree.c +3 -0
index b317f8ee42a9..800aaf45e6bd 100644
@@ -2041,6 +2041,9 @@ static int btrfs_issue_clear_op(struct block_device *bdev, u64 start, u64 size,
 	case BTRFS_CLEAR_OP_DISCARD:
 		return blkdev_issue_discard(bdev, start >> 9, size >> 9,
 				GFP_NOFS, 0);
+	case BTRFS_CLEAR_OP_ZERO:
+		return blkdev_issue_zeroout(bdev, start >> 9, size >> 9,
+				GFP_NOFS, 0);
 	default:
 		return -EOPNOTSUPP;
 	}
Signature · 1 line
2.16.2
author maintainer
#4 lore raw

PATCH 4/6 btrfs: add new ioctl BTRFS_IOC_CLEAR_FREE

In reply to David Sterba

A new ioctl that will clear the free space (by writing zeros) given by the user range. Similar to the TRIM ioctl.

We need a new ioctl for that because struct fstrim_range does not provide any existing or reserved member for extensions. The new ioctl also supports TRIM as the operation type.

---
 fs/btrfs/ctree.h           | 11 ++---------
 fs/btrfs/extent-tree.c     | 48 ++++++++++++++++++++++++++++++++++++++++++++++
 fs/btrfs/ioctl.c           | 42 ++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/btrfs.h | 20 +++++++++++++++++++
 4 files changed, 112 insertions(+), 9 deletions(-)
fs/btrfs/ctree.h +2 -9
index 772cb4ccc5f7..d8cc70a6bef7 100644
@@ -674,15 +674,6 @@ struct btrfs_stripe_hash {
 	spinlock_t lock;
 };
 
-/*
- * Type of operation that will be used to clear unused blocks.
- */
-enum btrfs_clear_op_type {
-	BTRFS_CLEAR_OP_DISCARD = 0,
-	BTRFS_CLEAR_OP_ZERO,
-	BTRFS_NR_CLEAR_OP_TYPES,
-};
-
 /* used by the raid56 code to lock stripes for read/modify/write */
 struct btrfs_stripe_hash_table {
 	struct list_head stripe_cache;
@@ -2800,6 +2791,8 @@ int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info,
 int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr,
 			 u64 num_bytes, u64 *actual_bytes,
 			 enum btrfs_clear_op_type clear);
+int btrfs_clear_free_space(struct btrfs_root *root,
+		struct btrfs_ioctl_clear_free_args *args);
 int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans,
 			    struct btrfs_fs_info *fs_info, u64 type);
 int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range);
fs/btrfs/extent-tree.c +48 -0

54 lines not on this page · raw message

fs/btrfs/ioctl.c +42 -0

54 lines not on this page · raw message

include/uapi/linux/btrfs.h +20 -0
index c8d99b9ca550..860f9df01614 100644
@@ -737,6 +737,24 @@ enum btrfs_err_code {
 	BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS
 };
 
+/*
+ * Type of operation that will be used to clear unused blocks.
+ */
+enum btrfs_clear_op_type {
+	BTRFS_CLEAR_OP_DISCARD = 0,
+	BTRFS_CLEAR_OP_ZERO,
+	BTRFS_NR_CLEAR_OP_TYPES,
+};
+
+struct btrfs_ioctl_clear_free_args {
+	__u32 type;			/* in, btrfs_clear_free_op_type */
+	__u32 reserved1;		/* padding, must be zero */
+	__u64 start;			/* in */
+	__u64 length;			/* in, out */
+	__u64 minlen;			/* in */
+	__u64 reserved2[4];
+};
+
 #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
 				   struct btrfs_ioctl_vol_args)
 #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
@@ -843,5 +861,7 @@ enum btrfs_err_code {
 				   struct btrfs_ioctl_vol_args_v2)
 #define BTRFS_IOC_LOGICAL_INO_V2 _IOWR(BTRFS_IOCTL_MAGIC, 59, \
 					struct btrfs_ioctl_logical_ino_args)
+#define BTRFS_IOC_CLEAR_FREE _IOW(BTRFS_IOCTL_MAGIC, 90, \
+				struct btrfs_ioctl_clear_free_args)
 
 #endif /* _UAPI_LINUX_BTRFS_H */
Signature · 1 line
2.16.2
author maintainer
#5 lore raw

PATCH 5/6 btrfs: add discard secure to clear unused space

In reply to David Sterba
---
 fs/btrfs/extent-tree.c     | 14 ++++++++++++--
 include/uapi/linux/btrfs.h |  1 +
 2 files changed, 13 insertions(+), 2 deletions(-)
fs/btrfs/extent-tree.c +12 -2
index 21a24fff32dd..285bace8e2c6 100644
@@ -2037,10 +2037,15 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans,
 static int btrfs_issue_clear_op(struct block_device *bdev, u64 start, u64 size,
 		enum btrfs_clear_op_type clear)
 {
+	int flags = 0;
+
 	switch (clear) {
+	case BTRFS_CLEAR_OP_DISCARD_SECURE:
+		flags = BLKDEV_DISCARD_SECURE;
+		/* fall through */
 	case BTRFS_CLEAR_OP_DISCARD:
 		return blkdev_issue_discard(bdev, start >> 9, size >> 9,
-				GFP_NOFS, 0);
+				GFP_NOFS, flags);
 	case BTRFS_CLEAR_OP_ZERO:
 		return blkdev_issue_zeroout(bdev, start >> 9, size >> 9,
 				GFP_NOFS, 0);
@@ -2129,7 +2134,8 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr,
 	struct btrfs_bio *bbio = NULL;
 	int rw;
 
-	if (clear == BTRFS_CLEAR_OP_DISCARD)
+	if (clear == BTRFS_CLEAR_OP_DISCARD ||
+	    clear == BTRFS_CLEAR_OP_DISCARD_SECURE)
 		rw = BTRFS_MAP_DISCARD;
 	else
 		rw = BTRFS_MAP_WRITE;
@@ -2160,6 +2166,10 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr,
 			    !blk_queue_discard(req_q))
 				continue;
 
+			if (clear == BTRFS_CLEAR_OP_DISCARD_SECURE &&
+			    !blk_queue_secure_erase(req_q))
+				continue;
+
 			ret = btrfs_issue_discard(stripe->dev->bdev,
 						  stripe->physical,
 						  stripe->length,
include/uapi/linux/btrfs.h +1 -0
index 860f9df01614..1becbb241e53 100644
@@ -743,6 +743,7 @@ enum btrfs_err_code {
 enum btrfs_clear_op_type {
 	BTRFS_CLEAR_OP_DISCARD = 0,
 	BTRFS_CLEAR_OP_ZERO,
+	BTRFS_CLEAR_OP_DISCARD_SECURE,
 	BTRFS_NR_CLEAR_OP_TYPES,
 };
 
Signature · 1 line
2.16.2
author maintainer
#6 lore raw

PATCH 6/6 btrfs: add more zeroout modes for clearing unused space

In reply to David Sterba
---
 fs/btrfs/extent-tree.c     | 12 +++++++++++-
 include/uapi/linux/btrfs.h |  5 +++++
 2 files changed, 16 insertions(+), 1 deletion(-)
fs/btrfs/extent-tree.c +11 -1
index 285bace8e2c6..bd2ac5779998 100644
@@ -2046,9 +2046,19 @@ static int btrfs_issue_clear_op(struct block_device *bdev, u64 start, u64 size,
 	case BTRFS_CLEAR_OP_DISCARD:
 		return blkdev_issue_discard(bdev, start >> 9, size >> 9,
 				GFP_NOFS, flags);
+	case BTRFS_CLEAR_OP_ZERO_NOUNMAP:
+		flags = BLKDEV_ZERO_NOUNMAP;
+		goto zeroout;
+	case BTRFS_CLEAR_OP_ZERO_NOFALLBACK:
+		flags = BLKDEV_ZERO_NOFALLBACK;
+		goto zeroout;
+	case BTRFS_CLEAR_OP_ZERO_NOUNMAP_NOFALLBACK:
+		flags = BLKDEV_ZERO_NOUNMAP | BLKDEV_ZERO_NOFALLBACK;
+		/* fall through */
 	case BTRFS_CLEAR_OP_ZERO:
+zeroout:
 		return blkdev_issue_zeroout(bdev, start >> 9, size >> 9,
-				GFP_NOFS, 0);
+				GFP_NOFS, flags);
 	default:
 		return -EOPNOTSUPP;
 	}
include/uapi/linux/btrfs.h +5 -0
index 1becbb241e53..5d1f13045906 100644
@@ -744,6 +744,11 @@ enum btrfs_clear_op_type {
 	BTRFS_CLEAR_OP_DISCARD = 0,
 	BTRFS_CLEAR_OP_ZERO,
 	BTRFS_CLEAR_OP_DISCARD_SECURE,
+
+	/* Fine tuning for clearing by zeros, see __blkdev_issue_zeroout */
+	BTRFS_CLEAR_OP_ZERO_NOUNMAP,
+	BTRFS_CLEAR_OP_ZERO_NOFALLBACK,
+	BTRFS_CLEAR_OP_ZERO_NOUNMAP_NOFALLBACK,
 	BTRFS_NR_CLEAR_OP_TYPES,
 };
 
Signature · 1 line
2.16.2
#7 lore raw
In reply to David Sterba
Quoted 3 lines · David Sterba

This patchset adds new ioctl similar to TRIM, that provides several other ways how to clear the unused space. The changelogs are incomplete, for preview not for inclusion yet.

+1 for the idea. This will be insanely useful for certain VM setups.

Quoted 4 lines

It compiles and has been tested lightly, the clearing modes depend on hw capabilities (secure discard, sector unmapping instead of zeros), so I've tested only zeroing and discard.

I don't have specific experience with blkdev_issue_zeroout, but I think the sector unmapping may be covered by the discard support. When dealing with SCSI devices, discard operations get converted to the SCSI UNMAP command, which just based on the naming, sounds like what blkdev_issue_zeroout is issuing (at least, when dealing with SCSI devices). Pretty much, the SCSI command works just like the ATA TRIM command does on ATA devices which zero data on discard (except it's SCSI, so it can pretty much always be queued, and has some other semantics around it that give it better performance than ATA TRIM).

Assuming that is the case, the unmapping support could be tested using the QEMU PV-SCSI driver (which supports the UNMAP command) with appropriate backing storage. I can look at doing this testing myself, as I already use PV-SCSI for storage on all my QEMU VM's.

Quoted 5 lines

I personally think the zeroing has a usecase and the other modes were easy to add. Further extensions can be considered, eg. WRITE_SAME, overwriting with a randomly generated pattern, or some filesystem canary patterns that can be used to report unused block read as metadata.

Zeroing does have a use-case. It's wonderfully useful for handling compaction of VM disks when using a virtual machine manager that doesn't support discard operations for this purpose. I can also see the secure discard support being useful (though not necessarily the sector unmapping support for reasons mentioned above).

Quoted 25 lines

As this is modelled after the generic FITRIM ioctl, so this could be a new generic ioctl too. However, last time somebody wanted such ioctl, there was a pushback. I'll consider making a generic version and send it for comments to fsdevel eventually.

git://github.com/kdave/btrfs-devel dev/zero-free

David Sterba (6):
btrfs: extend trim callchain to pass the operation type
btrfs: add wrapper to switch clearing operation
btrfs: add zeroing clear operation
btrfs: add new ioctl BTRFS_IOC_CLEAR_FREE
btrfs: add discard secure to clear unused space
btrfs: add more zeroout modes for clearing unused space

  fs/btrfs/ctree.h            |   5 +-
  fs/btrfs/extent-tree.c      | 130 ++++++++++++++++++++++++++++++++++++++------
  fs/btrfs/free-space-cache.c |  22 +++++---
  fs/btrfs/free-space-cache.h |   3 +-
  fs/btrfs/ioctl.c            |  42 ++++++++++++++
  include/uapi/linux/btrfs.h  |  26 +++++++++
  6 files changed, 199 insertions(+), 29 deletions(-)
#8 lore raw
In reply to David Sterba
Quoted 21 lines · David Sterba

This patchset adds new ioctl similar to TRIM, that provides several other ways how to clear the unused space. The changelogs are incomplete, for preview not for inclusion yet.

It compiles and has been tested lightly, the clearing modes depend on hw capabilities (secure discard, sector unmapping instead of zeros), so I've tested only zeroing and discard.

I personally think the zeroing has a usecase and the other modes were easy to add. Further extensions can be considered, eg. WRITE_SAME, overwriting with a randomly generated pattern, or some filesystem canary patterns that can be used to report unused block read as metadata.

As this is modelled after the generic FITRIM ioctl, so this could be a new generic ioctl too. However, last time somebody wanted such ioctl, there was a pushback. I'll consider making a generic version and send it for comments to fsdevel eventually.

git://github.com/kdave/btrfs-devel dev/zero-free

Quoted 7 lines

David Sterba (6):
btrfs: extend trim callchain to pass the operation type
btrfs: add wrapper to switch clearing operation
btrfs: add zeroing clear operation
btrfs: add new ioctl BTRFS_IOC_CLEAR_FREE
btrfs: add discard secure to clear unused space
btrfs: add more zeroout modes for clearing unused space

For the record, this patchset has been shifted to 4.19 or later.