From patchwork Wed Mar 12 11:12:18 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Sterba X-Patchwork-Id: 14013371 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 853AB1E3DDE for ; Wed, 12 Mar 2025 11:12:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741777943; cv=none; b=qTmcTWwRXNKb2QSTU+N5urO78gizu+XDPhBZ6JcE167dngf/9c8Tslb5eSWOhtG9pNxxm6tkXBQWUmbHAuA5bAGMRU0IJHAAh6VF6KhURHALUd0lfO6e3fSGGdSOuE2pvZ6xFRwN496QwTn4/rXAVsCw1IrPlZc06hXVWdRoIjc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741777943; c=relaxed/simple; bh=VRqCDkOFNH6PSA/psYnR3X65vc1a68Fo2IHjk+6LZC4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iFmvHRdd4wOTMNCVfAbXP0t3KehH7HdvfU89CD6n3bz5/4PGZaY/zSOEL0p5g6mKnhsOR+PjKePbe1HFClaohXffAWBp+XyS9e7JxZuUnqF8KMYYXPgwJPFKNhlGgllV1rQ/jBQcv9xFuudOcXSSjn6PCUf5qwxuCe3z7Oc+dI0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=H7ArntQK; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=H7ArntQK; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="H7ArntQK"; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="H7ArntQK" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id B629521169; Wed, 12 Mar 2025 11:12:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1741777938; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8+faLwUQNDhbfGx+S4F/uP54P11bMk2wIcji1kjVfoY=; b=H7ArntQKdCoe35v/XvU+FQyA6iYkb6TUngkhQaTw3QEtGnal/9xYaaiJEbhb+4FH9ENclD 97LZZqEDnxoBkVmANfQLI7nPkrJxXIjzTlGV9S7DbFEvVv/AcZMckaUabiW/UWknaVIx1I JcXY2uXWQ91anT/go0gFkPJqbfaSvOA= Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1741777938; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8+faLwUQNDhbfGx+S4F/uP54P11bMk2wIcji1kjVfoY=; b=H7ArntQKdCoe35v/XvU+FQyA6iYkb6TUngkhQaTw3QEtGnal/9xYaaiJEbhb+4FH9ENclD 97LZZqEDnxoBkVmANfQLI7nPkrJxXIjzTlGV9S7DbFEvVv/AcZMckaUabiW/UWknaVIx1I JcXY2uXWQ91anT/go0gFkPJqbfaSvOA= Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id AE660132CB; Wed, 12 Mar 2025 11:12:18 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id MjyRKhJs0WccNgAAD6G6ig (envelope-from ); Wed, 12 Mar 2025 11:12:18 +0000 From: David Sterba To: linux-btrfs@vger.kernel.org Cc: David Sterba Subject: [PATCH v2 1/6] btrfs: extend trim callchains to pass the operation type Date: Wed, 12 Mar 2025 12:12:18 +0100 Message-ID: <713849f40a6ec90dce4732a8f69153033952c323.1741777050.git.dsterba@suse.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Score: -2.80 X-Spamd-Result: default: False [-2.80 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; RCPT_COUNT_TWO(0.00)[2]; RCVD_VIA_SMTP_AUTH(0.00)[]; MIME_TRACE(0.00)[0:+]; ARC_NA(0.00)[]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; FUZZY_BLOCKED(0.00)[rspamd.com]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.com:mid,suse.com:email,imap1.dmz-prg2.suse.org:helo]; RCVD_TLS_ALL(0.00)[] X-Spam-Flag: NO X-Spam-Level: Preparatory work for more than trim/discard operation that can be performed on the unused space from an ioctl. As FITRIM is not extensible, we'll need a new one. Now we extend any caller that takes part in the trim/discard to take one parameter defining the type of operation. The operation multiplexer btrfs_issue_clear_op() will be extended in followup patches. Signed-off-by: David Sterba --- fs/btrfs/discard.c | 4 +-- fs/btrfs/extent-tree.c | 51 +++++++++++++++++++++++-------------- fs/btrfs/extent-tree.h | 3 ++- fs/btrfs/free-space-cache.c | 29 +++++++++++---------- fs/btrfs/free-space-cache.h | 8 +++--- fs/btrfs/inode.c | 2 +- fs/btrfs/volumes.c | 3 ++- include/uapi/linux/btrfs.h | 8 ++++++ 8 files changed, 68 insertions(+), 40 deletions(-) diff --git a/fs/btrfs/discard.c b/fs/btrfs/discard.c index d6eef4bd9e9d..4515548b107b 100644 --- a/fs/btrfs/discard.c +++ b/fs/btrfs/discard.c @@ -524,13 +524,13 @@ static void btrfs_discard_workfn(struct work_struct *work) btrfs_trim_block_group_bitmaps(block_group, &trimmed, block_group->discard_cursor, btrfs_block_group_end(block_group), - minlen, maxlen, true); + minlen, maxlen, true, BTRFS_CLEAR_OP_DISCARD); discard_ctl->discard_bitmap_bytes += trimmed; } else { btrfs_trim_block_group_extents(block_group, &trimmed, block_group->discard_cursor, btrfs_block_group_end(block_group), - minlen, true); + minlen, true, BTRFS_CLEAR_OP_DISCARD); discard_ctl->discard_extent_bytes += trimmed; } diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 957230abd827..dcc16ca91f11 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -1247,8 +1247,20 @@ 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 >> SECTOR_SHIFT, + size >> SECTOR_SHIFT, GFP_NOFS); + default: + return -EOPNOTSUPP; + } +} + static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len, - u64 *discarded_bytes) + u64 *discarded_bytes, enum btrfs_clear_op_type clear) { int j, ret = 0; u64 bytes_left, end; @@ -1293,11 +1305,8 @@ static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len, bytes_left = end - start; continue; } - if (size) { - ret = blkdev_issue_discard(bdev, start >> SECTOR_SHIFT, - size >> SECTOR_SHIFT, - GFP_NOFS); + ret = btrfs_issue_clear_op(bdev, start, size, clear); if (!ret) *discarded_bytes += size; else if (ret != -EOPNOTSUPP) @@ -1315,9 +1324,7 @@ static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len, while (bytes_left) { u64 bytes_to_discard = min(BTRFS_MAX_DISCARD_CHUNK_SIZE, bytes_left); - ret = blkdev_issue_discard(bdev, start >> SECTOR_SHIFT, - bytes_to_discard >> SECTOR_SHIFT, - GFP_NOFS); + ret = btrfs_issue_clear_op(bdev, start, bytes_left, clear); if (ret) { if (ret != -EOPNOTSUPP) @@ -1338,7 +1345,8 @@ static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len, return ret; } -static int do_discard_extent(struct btrfs_discard_stripe *stripe, u64 *bytes) +static int do_discard_extent(struct btrfs_discard_stripe *stripe, u64 *bytes, + enum btrfs_clear_op_type clear) { struct btrfs_device *dev = stripe->dev; struct btrfs_fs_info *fs_info = dev->fs_info; @@ -1367,7 +1375,7 @@ static int do_discard_extent(struct btrfs_discard_stripe *stripe, u64 *bytes) &discarded); discarded += src_disc; } else if (bdev_max_discard_sectors(stripe->dev->bdev)) { - ret = btrfs_issue_discard(dev->bdev, phys, len, &discarded); + ret = btrfs_issue_discard(dev->bdev, phys, len, &discarded, clear); } else { ret = 0; *bytes = 0; @@ -1379,7 +1387,8 @@ static int do_discard_extent(struct btrfs_discard_stripe *stripe, u64 *bytes) } 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 ret = 0; u64 discarded_bytes = 0; @@ -1418,7 +1427,7 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr, &stripe->dev->dev_state)) continue; - ret = do_discard_extent(stripe, &bytes); + ret = do_discard_extent(stripe, &bytes, clear); if (ret) { /* * Keep going if discard is not supported by the @@ -2837,7 +2846,8 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans) if (btrfs_test_opt(fs_info, DISCARD_SYNC)) ret = btrfs_discard_extent(fs_info, start, - end + 1 - start, NULL); + end + 1 - start, NULL, + BTRFS_CLEAR_OP_DISCARD); clear_extent_dirty(unpin, start, end, &cached_state); ret = unpin_extent_range(fs_info, start, end, true); @@ -2866,7 +2876,8 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans) ret = btrfs_discard_extent(fs_info, block_group->start, block_group->length, - &trimmed); + &trimmed, + BTRFS_CLEAR_OP_DISCARD); /* * Not strictly necessary to lock, as the block_group should be @@ -6368,7 +6379,8 @@ void btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info, u64 start, u6 * it while performing the free space search since we have already * held back allocations. */ -static int btrfs_trim_free_extents(struct btrfs_device *device, u64 *trimmed) +static int btrfs_trim_free_extents(struct btrfs_device *device, u64 *trimmed, + enum btrfs_clear_op_type clear) { u64 start = BTRFS_DEVICE_RANGE_RESERVED, len = 0, end = 0; int ret; @@ -6433,8 +6445,7 @@ static int btrfs_trim_free_extents(struct btrfs_device *device, u64 *trimmed) break; } - ret = btrfs_issue_discard(device->bdev, start, len, - &bytes); + ret = btrfs_issue_discard(device->bdev, start, len, &bytes, clear); if (!ret) set_extent_bit(&device->alloc_state, start, start + bytes - 1, CHUNK_TRIMMED, NULL); @@ -6516,7 +6527,8 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range) &group_trimmed, start, end, - range->minlen); + range->minlen, + BTRFS_CLEAR_OP_DISCARD); trimmed += group_trimmed; if (ret) { @@ -6537,7 +6549,8 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range) if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)) continue; - ret = btrfs_trim_free_extents(device, &group_trimmed); + ret = btrfs_trim_free_extents(device, &group_trimmed, + BTRFS_CLEAR_OP_DISCARD); trimmed += group_trimmed; if (ret) { diff --git a/fs/btrfs/extent-tree.h b/fs/btrfs/extent-tree.h index 0ed682d9ed7b..c8e1a30309ab 100644 --- a/fs/btrfs/extent-tree.h +++ b/fs/btrfs/extent-tree.h @@ -163,7 +163,8 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans, struct extent_buffer *parent); void 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_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range); #endif diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 05e173311c1a..05066cf485d0 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -3652,7 +3652,8 @@ static int do_trimming(struct btrfs_block_group *block_group, u64 *total_trimmed, u64 start, u64 bytes, u64 reserved_start, u64 reserved_bytes, enum btrfs_trim_state reserved_trim_state, - 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; @@ -3674,7 +3675,7 @@ static int do_trimming(struct btrfs_block_group *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; trim_state = BTRFS_TRIM_STATE_TRIMMED; @@ -3711,7 +3712,7 @@ static int do_trimming(struct btrfs_block_group *block_group, */ static int trim_no_bitmap(struct btrfs_block_group *block_group, u64 *total_trimmed, u64 start, u64 end, u64 minlen, - bool async) + bool async, enum btrfs_clear_op_type clear) { struct btrfs_discard_ctl *discard_ctl = &block_group->fs_info->discard_ctl; @@ -3800,7 +3801,7 @@ static int trim_no_bitmap(struct btrfs_block_group *block_group, ret = do_trimming(block_group, total_trimmed, start, bytes, extent_start, extent_bytes, extent_trim_state, - &trim_entry); + &trim_entry, clear); if (ret) { block_group->discard_cursor = start + bytes; break; @@ -3877,7 +3878,7 @@ static void end_trimming_bitmap(struct btrfs_free_space_ctl *ctl, */ static int trim_bitmaps(struct btrfs_block_group *block_group, u64 *total_trimmed, u64 start, u64 end, u64 minlen, - u64 maxlen, bool async) + u64 maxlen, bool async, enum btrfs_clear_op_type clear) { struct btrfs_discard_ctl *discard_ctl = &block_group->fs_info->discard_ctl; @@ -3986,7 +3987,7 @@ static int trim_bitmaps(struct btrfs_block_group *block_group, mutex_unlock(&ctl->cache_writeout_mutex); ret = do_trimming(block_group, total_trimmed, start, bytes, - start, bytes, 0, &trim_entry); + start, bytes, 0, &trim_entry, clear); if (ret) { reset_trimming_bitmap(ctl, offset); block_group->discard_cursor = @@ -4020,7 +4021,8 @@ static int trim_bitmaps(struct btrfs_block_group *block_group, } int btrfs_trim_block_group(struct btrfs_block_group *block_group, - u64 *trimmed, u64 start, u64 end, u64 minlen) + u64 *trimmed, u64 start, u64 end, u64 minlen, + enum btrfs_clear_op_type clear) { struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; int ret; @@ -4038,11 +4040,11 @@ int btrfs_trim_block_group(struct btrfs_block_group *block_group, btrfs_freeze_block_group(block_group); spin_unlock(&block_group->lock); - ret = trim_no_bitmap(block_group, trimmed, start, end, minlen, false); + ret = trim_no_bitmap(block_group, trimmed, start, end, minlen, false, clear); if (ret) goto out; - ret = trim_bitmaps(block_group, trimmed, start, end, minlen, 0, false); + ret = trim_bitmaps(block_group, trimmed, start, end, minlen, 0, false, clear); div64_u64_rem(end, BITS_PER_BITMAP * ctl->unit, &rem); /* If we ended in the middle of a bitmap, reset the trimming flag */ if (rem) @@ -4054,7 +4056,7 @@ int btrfs_trim_block_group(struct btrfs_block_group *block_group, int btrfs_trim_block_group_extents(struct btrfs_block_group *block_group, u64 *trimmed, u64 start, u64 end, u64 minlen, - bool async) + bool async, enum btrfs_clear_op_type clear) { int ret; @@ -4068,7 +4070,7 @@ int btrfs_trim_block_group_extents(struct btrfs_block_group *block_group, btrfs_freeze_block_group(block_group); spin_unlock(&block_group->lock); - ret = trim_no_bitmap(block_group, trimmed, start, end, minlen, async); + ret = trim_no_bitmap(block_group, trimmed, start, end, minlen, async, clear); btrfs_unfreeze_block_group(block_group); return ret; @@ -4076,7 +4078,8 @@ int btrfs_trim_block_group_extents(struct btrfs_block_group *block_group, int btrfs_trim_block_group_bitmaps(struct btrfs_block_group *block_group, u64 *trimmed, u64 start, u64 end, u64 minlen, - u64 maxlen, bool async) + u64 maxlen, bool async, + enum btrfs_clear_op_type clear) { int ret; @@ -4091,7 +4094,7 @@ int btrfs_trim_block_group_bitmaps(struct btrfs_block_group *block_group, spin_unlock(&block_group->lock); ret = trim_bitmaps(block_group, trimmed, start, end, minlen, maxlen, - async); + async, clear); btrfs_unfreeze_block_group(block_group); diff --git a/fs/btrfs/free-space-cache.h b/fs/btrfs/free-space-cache.h index 9f1dbfdee8ca..c4c2e5571355 100644 --- a/fs/btrfs/free-space-cache.h +++ b/fs/btrfs/free-space-cache.h @@ -159,13 +159,15 @@ void btrfs_return_cluster_to_free_space( struct btrfs_block_group *block_group, struct btrfs_free_cluster *cluster); int btrfs_trim_block_group(struct btrfs_block_group *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 btrfs_trim_block_group_extents(struct btrfs_block_group *block_group, u64 *trimmed, u64 start, u64 end, u64 minlen, - bool async); + bool async, enum btrfs_clear_op_type clear); int btrfs_trim_block_group_bitmaps(struct btrfs_block_group *block_group, u64 *trimmed, u64 start, u64 end, u64 minlen, - u64 maxlen, bool async); + u64 maxlen, bool async, + enum btrfs_clear_op_type clear); bool btrfs_free_space_cache_v1_active(struct btrfs_fs_info *fs_info); int btrfs_set_free_space_cache_v1_active(struct btrfs_fs_info *fs_info, bool active); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index b4efd0c00f21..4c368e1516b8 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -3307,7 +3307,7 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent) btrfs_discard_extent(fs_info, ordered_extent->disk_bytenr, ordered_extent->disk_num_bytes, - NULL); + NULL, BTRFS_CLEAR_OP_DISCARD); btrfs_free_reserved_extent(fs_info, ordered_extent->disk_bytenr, ordered_extent->disk_num_bytes, 1); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index e6761ccd8187..f1b1d7446b20 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -3534,7 +3534,8 @@ int btrfs_relocate_chunk(struct btrfs_fs_info *fs_info, u64 chunk_offset) * filesystem's point of view. */ if (btrfs_is_zoned(fs_info)) { - ret = btrfs_discard_extent(fs_info, chunk_offset, length, NULL); + ret = btrfs_discard_extent(fs_info, chunk_offset, length, NULL, + BTRFS_CLEAR_OP_DISCARD); if (ret) btrfs_info(fs_info, "failed to reset zone %llu after relocation", diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index dd02160015b2..aab7fac56d32 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -1096,6 +1096,14 @@ enum btrfs_err_code { BTRFS_ERROR_DEV_RAID1C4_MIN_NOT_MET, }; +/* + * Type of operation that will be used to clear unused blocks. + */ +enum btrfs_clear_op_type { + BTRFS_CLEAR_OP_DISCARD, + BTRFS_NR_CLEAR_OP_TYPES, +}; + #define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ struct btrfs_ioctl_vol_args) #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ From patchwork Wed Mar 12 11:12:20 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Sterba X-Patchwork-Id: 14013372 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 354E323A99A for ; Wed, 12 Mar 2025 11:12:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741777950; cv=none; b=FojmqPQUIW1dZ8KrN/d6Zm8xcqZmVGDdRFFUvWP6FnlvfSYlsJrDXN52YVbK3pPIYY62WwXZfBXk+1Sx0bXSdg8B6lr17WsqWAv9zq1aU8EzqG6iySQq8zoj1Lxnarmv4R+kgLf3C3cSXnb0v40pM/YzICzMAPyzxwYErne+LWs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741777950; c=relaxed/simple; bh=aD/Msc8wY2CenEqlsbPN23rqrUa8c2KgCJBb+7YQG9E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Aifq3MwPCMO1BvtsxoqLXJ6CGgphPbP+tB9XR+vqwHXKatDAOGsGdDENqLjx460o/4M0Sacd3dNYVicRrKIW0P0fvmkpe9V9HxZuykVk0Ab0tyXTnvvcpTxrM7F0T0zmHdzH+D0KUDTSYasd8/1LvWtSWPN3ejzsFOtdyLSKyHQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=dEZY0GiL; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=dEZY0GiL; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="dEZY0GiL"; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="dEZY0GiL" Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 1AC4021169; Wed, 12 Mar 2025 11:12:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1741777945; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rMlw5EaYUH26IW0p1Nsq7CGzz+Eh4zQVcbbmqRiHd88=; b=dEZY0GiLrEWpGHhJNTrGqozwlgW47TMncQQxzgN6BWFywE5pWLM5tc8i4JA0cO6S8xPSaw 7lQfTGd0VoZt+r3aCggT89J4Hvm8eSDV2cZpTLg4KkrYe/5HYNb4zpDHbEk0IwO/P4U8cS Mk103jIJH4acyuROUJf7ImPQrrE8ah4= Authentication-Results: smtp-out1.suse.de; dkim=pass header.d=suse.com header.s=susede1 header.b=dEZY0GiL DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1741777945; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rMlw5EaYUH26IW0p1Nsq7CGzz+Eh4zQVcbbmqRiHd88=; b=dEZY0GiLrEWpGHhJNTrGqozwlgW47TMncQQxzgN6BWFywE5pWLM5tc8i4JA0cO6S8xPSaw 7lQfTGd0VoZt+r3aCggT89J4Hvm8eSDV2cZpTLg4KkrYe/5HYNb4zpDHbEk0IwO/P4U8cS Mk103jIJH4acyuROUJf7ImPQrrE8ah4= Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 13A55132CB; Wed, 12 Mar 2025 11:12:25 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id OCfKBBls0WceNgAAD6G6ig (envelope-from ); Wed, 12 Mar 2025 11:12:25 +0000 From: David Sterba To: linux-btrfs@vger.kernel.org Cc: David Sterba Subject: [PATCH v2 2/6] btrfs: add new ioctl CLEAR_FREE Date: Wed, 12 Mar 2025 12:12:20 +0100 Message-ID: X-Mailer: git-send-email 2.47.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Rspamd-Queue-Id: 1AC4021169 X-Spam-Score: -3.01 X-Rspamd-Action: no action X-Spamd-Result: default: False [-3.01 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; R_DKIM_ALLOW(-0.20)[suse.com:s=susede1]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; MX_GOOD(-0.01)[]; ARC_NA(0.00)[]; RCPT_COUNT_TWO(0.00)[2]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; MIME_TRACE(0.00)[0:+]; FUZZY_BLOCKED(0.00)[rspamd.com]; TO_DN_SOME(0.00)[]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[2a07:de40:b281:104:10:150:64:97:from]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; FROM_HAS_DN(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[2a07:de40:b281:106:10:150:64:167:received]; FROM_EQ_ENVFROM(0.00)[]; ASN(0.00)[asn:25478, ipnet:::/0, country:RU]; RCVD_TLS_ALL(0.00)[]; DKIM_TRACE(0.00)[suse.com:+]; SPAMHAUS_XBL(0.00)[2a07:de40:b281:104:10:150:64:97:from]; DBL_BLOCKED_OPENRESOLVER(0.00)[imap1.dmz-prg2.suse.org:rdns,imap1.dmz-prg2.suse.org:helo,suse.com:dkim,suse.com:mid,suse.com:email] X-Rspamd-Server: rspamd1.dmz-prg2.suse.org X-Spam-Flag: NO X-Spam-Level: Add a new ioctl that is an extensible version of FITRIM. It currently does only the trim/discard and will be extended by other modes like zeroing or block unmapping. 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. Signed-off-by: David Sterba --- fs/btrfs/extent-tree.c | 92 ++++++++++++++++++++++++++++++++++++++ fs/btrfs/extent-tree.h | 2 + fs/btrfs/ioctl.c | 49 ++++++++++++++++++++ include/uapi/linux/btrfs.h | 20 +++++++++ 4 files changed, 163 insertions(+) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index dcc16ca91f11..942584b9018a 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -6570,3 +6570,95 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range) return bg_ret; return dev_ret; } + +int btrfs_clear_free_space(struct btrfs_fs_info *fs_info, + struct btrfs_ioctl_clear_free_args *args) +{ + struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; + struct btrfs_device *device; + struct btrfs_block_group *cache = NULL; + u64 group_cleared; + u64 range_end = U64_MAX; + u64 start; + u64 end; + u64 cleared = 0; + u64 bg_failed = 0; + u64 dev_failed = 0; + int bg_ret = 0; + int dev_ret = 0; + int ret = 0; + + if (args->start == U64_MAX) + return -EINVAL; + + /* + * Check range overflow if args->length is set. The default args->length + * is U64_MAX. + */ + if (args->length != U64_MAX && + check_add_overflow(args->start, args->length, &range_end)) + return -EINVAL; + + cache = btrfs_lookup_first_block_group(fs_info, args->start); + for (; cache; cache = btrfs_next_block_group(cache)) { + if (cache->start >= range_end) { + btrfs_put_block_group(cache); + break; + } + + start = max(args->start, cache->start); + end = min(range_end, cache->start + cache->length); + + if (end - start >= args->minlen) { + if (!btrfs_block_group_done(cache)) { + ret = btrfs_cache_block_group(cache, true); + if (ret) { + bg_failed++; + bg_ret = ret; + continue; + } + } + ret = btrfs_trim_block_group(cache, &group_cleared, + start, end, args->minlen, + args->type); + + cleared += group_cleared; + if (ret) { + bg_failed++; + bg_ret = ret; + continue; + } + } + } + + if (bg_failed) + btrfs_warn(fs_info, + "failed to clear %llu block group(s), last error %d", + bg_failed, bg_ret); + + mutex_lock(&fs_devices->device_list_mutex); + list_for_each_entry(device, &fs_devices->devices, dev_list) { + if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)) + continue; + + ret = btrfs_trim_free_extents(device, &group_cleared, args->type); + if (ret) { + dev_failed++; + dev_ret = ret; + break; + } + + cleared += group_cleared; + } + mutex_unlock(&fs_devices->device_list_mutex); + + if (dev_failed) + btrfs_warn(fs_info, + "failed to trim %llu device(s), last error %d", + dev_failed, dev_ret); + args->length = cleared; + if (bg_ret) + return bg_ret; + + return dev_ret; +} diff --git a/fs/btrfs/extent-tree.h b/fs/btrfs/extent-tree.h index c8e1a30309ab..e0702b276825 100644 --- a/fs/btrfs/extent-tree.h +++ b/fs/btrfs/extent-tree.h @@ -166,5 +166,7 @@ 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_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range); +int btrfs_clear_free_space(struct btrfs_fs_info *fs_info, + struct btrfs_ioctl_clear_free_args *args); #endif diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index a13d81bb56a0..e84db3929763 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -5211,6 +5211,53 @@ static int btrfs_ioctl_subvol_sync(struct btrfs_fs_info *fs_info, void __user *a return 0; } +static int btrfs_ioctl_clear_free(struct file *file, void __user *arg) +{ + struct btrfs_fs_info *fs_info = inode_to_fs_info(file_inode(file)); + struct btrfs_ioctl_clear_free_args args; + u64 total_bytes; + int ret; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + /* + * This can be relaxed to support conventional zones or zones that can + * be reset. Otherwise the assumptions of write pointer are not + * compatible with zeroout or trim. + */ + if (btrfs_is_zoned(fs_info)) + return -EOPNOTSUPP; + + if (copy_from_user(&args, arg, sizeof(args))) + return -EFAULT; + + if (args.type >= BTRFS_NR_CLEAR_OP_TYPES) + return -EOPNOTSUPP; + + ret = mnt_want_write_file(file); + if (ret) + return ret; + + total_bytes = btrfs_super_total_bytes(fs_info->super_copy); + if (args.start > total_bytes) { + ret = -EINVAL; + goto out_drop_write; + } + + ret = btrfs_clear_free_space(fs_info, &args); + if (ret < 0) + goto out_drop_write; + + if (copy_to_user(arg, &args, sizeof(args))) + ret = -EFAULT; + +out_drop_write: + mnt_drop_write_file(file); + + return ret; +} + long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -5366,6 +5413,8 @@ long btrfs_ioctl(struct file *file, unsigned int #endif case BTRFS_IOC_SUBVOL_SYNC_WAIT: return btrfs_ioctl_subvol_sync(fs_info, argp); + case BTRFS_IOC_CLEAR_FREE: + return btrfs_ioctl_clear_free(file, argp); } return -ENOTTY; diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index aab7fac56d32..cfa1136815f1 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -1104,6 +1104,24 @@ enum btrfs_clear_op_type { BTRFS_NR_CLEAR_OP_TYPES, }; +struct btrfs_ioctl_clear_free_args { + /* In, type of clearing operation, enumerated in btrfs_clear_free_op_type. */ + __u32 type; + /* Reserved must be zero. */ + __u32 reserved1; + /* + * In. Starting offset to clear from in the logical address space (same + * as fstrim_range::start). + */ + __u64 start; /* in */ + /* In, out. Length from the start to clear (same as fstrim_range::length). */ + __u64 length; + /* In. Minimal length to clear (same as fstrim_range::minlen). */ + __u64 minlen; + /* Reserved, must be zero. */ + __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, \ @@ -1224,6 +1242,8 @@ enum btrfs_clear_op_type { struct btrfs_ioctl_encoded_io_args) #define BTRFS_IOC_SUBVOL_SYNC_WAIT _IOW(BTRFS_IOCTL_MAGIC, 65, \ struct btrfs_ioctl_subvol_wait) +#define BTRFS_IOC_CLEAR_FREE _IOWR(BTRFS_IOCTL_MAGIC, 66, \ + struct btrfs_ioctl_clear_free_args) #ifdef __cplusplus } From patchwork Wed Mar 12 11:12:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Sterba X-Patchwork-Id: 14013373 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4576A23AE83 for ; Wed, 12 Mar 2025 11:12:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741777959; cv=none; b=JHTGYNEHFtX/PYhYdOIyjKjkqOM6vj55ncDxYsotKwPCugCNrXONN/qfWqwq0iCJBrKfeZyKCLK/1S1Q+71Y4/AxgagQWeHXKf8t0dP/VW7FxidpUDAw93LgUGntTduQHslvUKq89YHujLhv4ZgzLMf+EH34sGsF+mXa+pGLPIo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741777959; c=relaxed/simple; bh=U02vXfZJDSo9drfUkuauaMRnlZDUJXJZKuBX6c5YjiA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eggMUDKspVI+tTrIe5dToHWkOhSa0JEzyLtvLk7ljcP+uSiZbrzEqR4OVLSQsQGlSsZOq94nZXR381eKHhMAI8oJjTqyHLVSeTWsDLfB2l3qX0M+5noyjInJB3kDSJYI8JPb8RYkL3QjgMZX9uviGD4hGg5IDj1r0QbS+w0RrIE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=IfMXPJ2V; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=IfMXPJ2V; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="IfMXPJ2V"; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="IfMXPJ2V" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 75DFC21169; Wed, 12 Mar 2025 11:12:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1741777955; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=SAvxe78/aoUyEQPUIUtC3sY6CELAzVMsyV+xu9y+IV0=; b=IfMXPJ2VLtQ2hZp2iKfltqfGF1XtVAgsZkmdw8V3pr3BLrwIOIS6Gq20jR0ftmbLdgYznh mOqyfiHI7mmJDy7EBkype8exUYOE2ZBVSg4yH9nu/3IRWyAe4LTuDbvnHTAa34No1PkCFG ED4TBqyoabyITY5BB0W/GtgwXYRvibo= Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1741777955; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=SAvxe78/aoUyEQPUIUtC3sY6CELAzVMsyV+xu9y+IV0=; b=IfMXPJ2VLtQ2hZp2iKfltqfGF1XtVAgsZkmdw8V3pr3BLrwIOIS6Gq20jR0ftmbLdgYznh mOqyfiHI7mmJDy7EBkype8exUYOE2ZBVSg4yH9nu/3IRWyAe4LTuDbvnHTAa34No1PkCFG ED4TBqyoabyITY5BB0W/GtgwXYRvibo= Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 6F1F7132CB; Wed, 12 Mar 2025 11:12:35 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id q0AfGyNs0Wc5NgAAD6G6ig (envelope-from ); Wed, 12 Mar 2025 11:12:35 +0000 From: David Sterba To: linux-btrfs@vger.kernel.org Cc: David Sterba Subject: [PATCH v2 3/6] btrfs: add zeroout mode to CLEAR_FREE ioctl Date: Wed, 12 Mar 2025 12:12:27 +0100 Message-ID: X-Mailer: git-send-email 2.47.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Level: X-Spamd-Result: default: False [-2.80 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; RCPT_COUNT_TWO(0.00)[2]; RCVD_VIA_SMTP_AUTH(0.00)[]; MIME_TRACE(0.00)[0:+]; ARC_NA(0.00)[]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; FUZZY_BLOCKED(0.00)[rspamd.com]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[imap1.dmz-prg2.suse.org:helo,suse.com:email,suse.com:mid]; RCVD_TLS_ALL(0.00)[] X-Spam-Score: -2.80 X-Spam-Flag: NO Add new type of clearing that will write zeros to the unused space (similar to what trim/discard would do). The mode is implemented by blkdev_issue_zeroout() that can write zeros to the blocks explicitly unless the hardware implements UNMAP command that unmaps the blocks that effectively appear as zeroed. This is handled transparently. As a special case of thin provisioning device, the UNMAP is usually handled and can free the underlying space. Signed-off-by: David Sterba --- fs/btrfs/extent-tree.c | 6 ++++++ include/uapi/linux/btrfs.h | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 942584b9018a..35bef44f069d 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -1250,10 +1250,16 @@ 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) { + unsigned int flags = BLKDEV_ZERO_KILLABLE; + switch (clear) { case BTRFS_CLEAR_OP_DISCARD: return blkdev_issue_discard(bdev, start >> SECTOR_SHIFT, size >> SECTOR_SHIFT, GFP_NOFS); + case BTRFS_CLEAR_OP_ZERO: + return blkdev_issue_zeroout(bdev, start >> SECTOR_SHIFT, + size >> SECTOR_SHIFT, GFP_NOFS, + flags); default: return -EOPNOTSUPP; } diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index cfa1136815f1..7529bc0c6efa 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -1101,6 +1101,12 @@ enum btrfs_err_code { */ enum btrfs_clear_op_type { BTRFS_CLEAR_OP_DISCARD, + /* + * Write zeros to the range, either overwrite or with hardware offload + * that can unmap the blocks internally. + * (Same as blkdev_issue_zeroout() with 0 flags). + */ + BTRFS_CLEAR_OP_ZERO, BTRFS_NR_CLEAR_OP_TYPES, }; From patchwork Wed Mar 12 11:12:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Sterba X-Patchwork-Id: 14013374 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B96D71E3DDE for ; Wed, 12 Mar 2025 11:12:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741777965; cv=none; b=BW8RZ4shkxyufBFVGe8Z+TT8M919D5jq+F3Kcd+mZuiGm58qPsrucZBcjO4I6KRcEE+Nb8wn9tFnIUXtFkyxOcLy8tgy8M+DDsuPm2hzs1FNNYHAwOQtPXTt4maGHnI58SQbEtlBF7B24+p/92+mqSfRfujuXAN4Y+Gfnyx9FEk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741777965; c=relaxed/simple; bh=BPxvemC2PRqbl8OmkUee+16knfdJvfGyuURD1rTPsbs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=M/R9Fe/ORJPG1o+rYfL3S/D+QrDlFMtug+QY86ufXvrwLt3jLxyHUjZNv3T5LxaEec634hxaGcLD1tZSgMf6sBXokkSwSgnMg5RMPYCymU6/kiIYDmuBhcVbl7IYeblELPOvFmIDJCueH3o4WrZrbRfM39S30kBkADCv5dPXkt0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=OtBLg4Eg; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=OtBLg4Eg; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="OtBLg4Eg"; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="OtBLg4Eg" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id D4D9121187; Wed, 12 Mar 2025 11:12:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1741777957; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=H5Z4qlnor8GV/e5Lygriv5tzmfe68+UFpE7ys2IuXWU=; b=OtBLg4EgLIMr6K1evfqrTH6rFm9emGuZvk3gD3rcJzkwhXhbQarb/Itg4MNS4Wuj01u4RJ KqjMKwlbGLjjrUV/QYHAZKwHJcOEeqWpQXE5Jw+a61be3MNYgCYH2wMyPHCBRj6j+C1TLV gPX+nst4N4ShpQ8r8k6HmTTSPNEOyZs= Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1741777957; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=H5Z4qlnor8GV/e5Lygriv5tzmfe68+UFpE7ys2IuXWU=; b=OtBLg4EgLIMr6K1evfqrTH6rFm9emGuZvk3gD3rcJzkwhXhbQarb/Itg4MNS4Wuj01u4RJ KqjMKwlbGLjjrUV/QYHAZKwHJcOEeqWpQXE5Jw+a61be3MNYgCYH2wMyPHCBRj6j+C1TLV gPX+nst4N4ShpQ8r8k6HmTTSPNEOyZs= Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id CC8F7132CB; Wed, 12 Mar 2025 11:12:37 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id 3UjuMSVs0Wc+NgAAD6G6ig (envelope-from ); Wed, 12 Mar 2025 11:12:37 +0000 From: David Sterba To: linux-btrfs@vger.kernel.org Cc: David Sterba Subject: [PATCH v2 4/6] btrfs: add secure erase mode to CLEAR_FREE ioctl Date: Wed, 12 Mar 2025 12:12:37 +0100 Message-ID: X-Mailer: git-send-email 2.47.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Score: -2.80 X-Spamd-Result: default: False [-2.80 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; RCPT_COUNT_TWO(0.00)[2]; RCVD_VIA_SMTP_AUTH(0.00)[]; MIME_TRACE(0.00)[0:+]; ARC_NA(0.00)[]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; FUZZY_BLOCKED(0.00)[rspamd.com]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.com:mid,suse.com:email,imap1.dmz-prg2.suse.org:helo]; RCVD_TLS_ALL(0.00)[] X-Spam-Flag: NO X-Spam-Level: Add another type of clearing that will do secure erase on the unused space. This requires hardware support and works as a regular discard while also deleting any copied or cached blocks. Same as "blkdiscard --secure". The unused space ranges may not be aligned to the secure erase block or be of a sufficient length, the exact result depends on the device. Some blocks may still contain valid data even after this ioctl. Signed-off-by: David Sterba --- fs/btrfs/extent-tree.c | 3 +++ include/uapi/linux/btrfs.h | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 35bef44f069d..1e2fe403ee89 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -1253,6 +1253,9 @@ static int btrfs_issue_clear_op(struct block_device *bdev, u64 start, u64 size, unsigned int flags = BLKDEV_ZERO_KILLABLE; switch (clear) { + case BTRFS_CLEAR_OP_SECURE_ERASE: + return blkdev_issue_secure_erase(bdev, start >> SECTOR_SHIFT, + size >> SECTOR_SHIFT, GFP_NOFS); case BTRFS_CLEAR_OP_DISCARD: return blkdev_issue_discard(bdev, start >> SECTOR_SHIFT, size >> SECTOR_SHIFT, GFP_NOFS); diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index 7529bc0c6efa..229a07843965 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -1107,6 +1107,13 @@ enum btrfs_clear_op_type { * (Same as blkdev_issue_zeroout() with 0 flags). */ BTRFS_CLEAR_OP_ZERO, + /* + * Do a secure erase operation on the range. If supported by the + * underlying hardware, this works as regular discard except that all + * copies of the discarded blocks that were possibly created by + * garbage collection must also be erased. + */ + BTRFS_CLEAR_OP_SECURE_ERASE, BTRFS_NR_CLEAR_OP_TYPES, }; From patchwork Wed Mar 12 11:12:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Sterba X-Patchwork-Id: 14013376 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5F3F823AE83 for ; Wed, 12 Mar 2025 11:12:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741777972; cv=none; b=JUhDsx9fE2toGI3h5Grls++x73iNnzKKIVW+n7sYSZoMxGVftLxgmu5nl9jZMMHcQ0qodf8iVPufpnYWAiE1w/xP3qYYyRg6zPYKgC0uMlfMvxw72aHFP06ICOGi6GE3JhkziEfLxAaOS7XlQbT9F2FFxrgLIHX1NgJa1v2S4YE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741777972; c=relaxed/simple; bh=u51y2eHwjTtxt68gjgwGVIiR38qfRhRG+TtaHxzz6kA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jiwVCx8EX0OmwrRp1KaDHgC4FwEgTm7nOh7YC5pATAlW//unMHl3XrPO8JSJG2IoxPcQpmNdJWJIynIw1A5xj8izLN6J5Y6eU5CTnDpeQf/+/Sc4KCxi4pU9QN8pjzrDJ+R5mdWZ4q3GEp5VjEZIRPo/Mv27CDr/hnysuhMsAyY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=qHTnir3l; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=qHTnir3l; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="qHTnir3l"; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="qHTnir3l" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 3804D21169; Wed, 12 Mar 2025 11:12:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1741777960; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ik4vWLFtYIlWv2HmhLmCzgZ1F/5/uQlsWwmkG3Y3yfw=; b=qHTnir3lamDh+wFMB6ney4TQgRNkN5L4sj1epYh73QqaS/VZptf0E6Mv2UFabbZGtNAFf/ mgSD3YYmng/+zGKNaiOEAmEhSpg3PK3gRA5C5Ed9ac2MqD6WMrpaddveFpZ9v6j7J2MHsX S+DBwCtKL+Mv4MovT5mRW8+dcZCVcwY= Authentication-Results: smtp-out1.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1741777960; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ik4vWLFtYIlWv2HmhLmCzgZ1F/5/uQlsWwmkG3Y3yfw=; b=qHTnir3lamDh+wFMB6ney4TQgRNkN5L4sj1epYh73QqaS/VZptf0E6Mv2UFabbZGtNAFf/ mgSD3YYmng/+zGKNaiOEAmEhSpg3PK3gRA5C5Ed9ac2MqD6WMrpaddveFpZ9v6j7J2MHsX S+DBwCtKL+Mv4MovT5mRW8+dcZCVcwY= Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 31659132CB; Wed, 12 Mar 2025 11:12:40 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id QcQLDChs0WdFNgAAD6G6ig (envelope-from ); Wed, 12 Mar 2025 11:12:40 +0000 From: David Sterba To: linux-btrfs@vger.kernel.org Cc: David Sterba Subject: [PATCH v2 5/6] btrfs: add more zeroout modes to CLEAR_FREE ioctl Date: Wed, 12 Mar 2025 12:12:39 +0100 Message-ID: X-Mailer: git-send-email 2.47.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Level: X-Spamd-Result: default: False [-2.80 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; RCPT_COUNT_TWO(0.00)[2]; RCVD_VIA_SMTP_AUTH(0.00)[]; MIME_TRACE(0.00)[0:+]; ARC_NA(0.00)[]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; FUZZY_BLOCKED(0.00)[rspamd.com]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[imap1.dmz-prg2.suse.org:helo,suse.com:email,suse.com:mid]; RCVD_TLS_ALL(0.00)[] X-Spam-Score: -2.80 X-Spam-Flag: NO The zeroing mode BTRFS_CLEAR_OP_ZERO is safe for use regardless of the underlying device capabilities, either zeros are written or the device will unmap the blocks. This a safe behaviour. In case it's desired to do one or the another add modes that can enforce that or fail when unsupported; - CLEAR_OP_ZERO - overwrite by zero blocks, forbid unmapping blocks by the device - CLEAR_OP_ZERO_NOFALLBACK - unmap the blocks by device and do not fall back to overwriting by zeros Implemented by __blkdev_issue_zeroout() and also documented there. Signed-off-by: David Sterba --- fs/btrfs/extent-tree.c | 11 +++++++++-- include/uapi/linux/btrfs.h | 5 +++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 1e2fe403ee89..f287184ae663 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -1259,10 +1259,17 @@ 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 >> SECTOR_SHIFT, size >> SECTOR_SHIFT, GFP_NOFS); + case BTRFS_CLEAR_OP_ZERO_NOUNMAP: + flags |= BLKDEV_ZERO_NOUNMAP; + return blkdev_issue_zeroout(bdev, start >> SECTOR_SHIFT, + size >> SECTOR_SHIFT, GFP_NOFS, flags); + case BTRFS_CLEAR_OP_ZERO_NOFALLBACK: + flags |= BLKDEV_ZERO_NOFALLBACK; + return blkdev_issue_zeroout(bdev, start >> SECTOR_SHIFT, + size >> SECTOR_SHIFT, GFP_NOFS, flags); case BTRFS_CLEAR_OP_ZERO: return blkdev_issue_zeroout(bdev, start >> SECTOR_SHIFT, - size >> SECTOR_SHIFT, GFP_NOFS, - flags); + size >> SECTOR_SHIFT, GFP_NOFS, flags); default: return -EOPNOTSUPP; } diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index 229a07843965..e2f16733c53f 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -1114,6 +1114,11 @@ enum btrfs_clear_op_type { * garbage collection must also be erased. */ BTRFS_CLEAR_OP_SECURE_ERASE, + + /* Overwrite by zeros, do not try to unmap blocks. */ + BTRFS_CLEAR_OP_ZERO_NOUNMAP, + /* Request unmapping the blocks and don't fall back to writing zeros. */ + BTRFS_CLEAR_OP_ZERO_NOFALLBACK, BTRFS_NR_CLEAR_OP_TYPES, }; From patchwork Wed Mar 12 11:12:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Sterba X-Patchwork-Id: 14013375 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 741ED4207F for ; Wed, 12 Mar 2025 11:12:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741777966; cv=none; b=g864pDLSr+lQh+M/skpJHSUOCONyIFCookv/WCsu7j9yUp12l1su7y+NfPyBcLhMjhTnzR+ZM8+dPxSIuW1F5pOH+G2sbiZYmUXg1/PBqDrdR9jM2senb2rr9/OMkCffqPSTvLaqevVitxo3xvT+1xx4ZlN1epUxRRooB9PbN5c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741777966; c=relaxed/simple; bh=s0dW5nUBT91sHXZesTTTCQH/gvwhk3R2VFjInWTWPSQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fJUAsGUEkPBJkrUq4YOYmBMyPMDSacJUtHAd5sXGPsTTBLE5xfXU3lh2E+cfjikXdMsOMLMkMBg4sFsMMoOwmIQrJBYpPWvSzj4x0oxENwOhU3BzGL+jWMN9xexKzF0XT3BgzgL/ygRIoFw0h7pvnecLro1Q618Sr1Xjztx4Jms= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com; spf=pass smtp.mailfrom=suse.com; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=tlMSOuv9; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b=tlMSOuv9; arc=none smtp.client-ip=195.135.223.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="tlMSOuv9"; dkim=pass (1024-bit key) header.d=suse.com header.i=@suse.com header.b="tlMSOuv9" Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 96BCE1F385; Wed, 12 Mar 2025 11:12:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1741777962; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cWor71mLXLT8AE0MNHs3VKizKq5sg/fL3sTN8CjQI0E=; b=tlMSOuv9Oi7hRdwqKusfkd39aukS9K0zF6iofS2nxLoKpl94C+XYYbypyUEqnyHmmRVRds nKjn8ygb9/j+/a6NjYS9806TzUxqv7+yNP/aMUXFKe9bSyl35JTQlTW4TfbYPHU4rnLM0C jG5KbscZYmZyvUoSjKpizOd3S08ci14= Authentication-Results: smtp-out2.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1741777962; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cWor71mLXLT8AE0MNHs3VKizKq5sg/fL3sTN8CjQI0E=; b=tlMSOuv9Oi7hRdwqKusfkd39aukS9K0zF6iofS2nxLoKpl94C+XYYbypyUEqnyHmmRVRds nKjn8ygb9/j+/a6NjYS9806TzUxqv7+yNP/aMUXFKe9bSyl35JTQlTW4TfbYPHU4rnLM0C jG5KbscZYmZyvUoSjKpizOd3S08ci14= Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 8F978132CB; Wed, 12 Mar 2025 11:12:42 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id 5x8MIyps0WdLNgAAD6G6ig (envelope-from ); Wed, 12 Mar 2025 11:12:42 +0000 From: David Sterba To: linux-btrfs@vger.kernel.org Cc: David Sterba Subject: [PATCH v2 6/6] btrfs: add mode to clear chunk map status to CLEAR_FREE ioctl Date: Wed, 12 Mar 2025 12:12:42 +0100 Message-ID: <4208ea4c7e515fe38fd5e3d451180a349a595cf1.1741777050.git.dsterba@suse.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-btrfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Level: X-Spamd-Result: default: False [-2.80 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; RCPT_COUNT_TWO(0.00)[2]; RCVD_VIA_SMTP_AUTH(0.00)[]; MIME_TRACE(0.00)[0:+]; ARC_NA(0.00)[]; DKIM_SIGNED(0.00)[suse.com:s=susede1]; FUZZY_BLOCKED(0.00)[rspamd.com]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; TO_DN_SOME(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.com:email,suse.com:mid,imap1.dmz-prg2.suse.org:helo]; RCVD_TLS_ALL(0.00)[] X-Spam-Score: -2.80 X-Spam-Flag: NO The trim status is tracked for each chunk in the fs_info::mapping_tree and updated as trim is called either manually by 'fstrim' or automatically when discard=async is enabled. With the new modes it's necessary to allow clearing the cache otherwise on a fully or partially trimmed filesystem the ioctl won't work as expected. Add separate clear free operation to reset just the trim status bits from all chunks. This should be called namely when the clearing operation is *not* trim (e.g. zeroout or secure erase). Signed-off-by: David Sterba --- fs/btrfs/ioctl.c | 13 +++++++++++++ fs/btrfs/volumes.c | 5 +++++ fs/btrfs/volumes.h | 1 + include/uapi/linux/btrfs.h | 7 +++++++ 4 files changed, 26 insertions(+) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index e84db3929763..f965f7fc1fa8 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -5235,6 +5235,19 @@ static int btrfs_ioctl_clear_free(struct file *file, void __user *arg) if (args.type >= BTRFS_NR_CLEAR_OP_TYPES) return -EOPNOTSUPP; + if (args.type == BTRFS_CLEAR_OP_RESET_CHUNK_STATUS_CACHE) { + write_lock(&fs_info->mapping_tree_lock); + for (struct rb_node *node = rb_first_cached(&fs_info->mapping_tree); + node; node = rb_next(node)) { + struct btrfs_chunk_map *map; + + map = rb_entry(node, struct btrfs_chunk_map, rb_node); + btrfs_chunk_map_clear_bits(map, CHUNK_TRIMMED); + } + write_unlock(&fs_info->mapping_tree_lock); + return 0; + } + ret = mnt_want_write_file(file); if (ret) return ret; diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index f1b1d7446b20..786b93c18a22 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -8079,6 +8079,11 @@ static int verify_chunk_dev_extent_mapping(struct btrfs_fs_info *fs_info) return ret; } +void btrfs_chunk_map_clear_bits(struct btrfs_chunk_map *map, unsigned int bits) +{ + chunk_map_device_clear_bits(map, bits); +} + /* * Ensure that all dev extents are mapped to correct chunk, otherwise * later chunk allocation/free would cause unexpected behavior. diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index e247d551da67..0e793b9776d6 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -785,6 +785,7 @@ struct btrfs_chunk_map *btrfs_find_chunk_map_nolock(struct btrfs_fs_info *fs_inf u64 logical, u64 length); struct btrfs_chunk_map *btrfs_get_chunk_map(struct btrfs_fs_info *fs_info, u64 logical, u64 length); +void btrfs_chunk_map_clear_bits(struct btrfs_chunk_map *map, unsigned int bits); void btrfs_remove_chunk_map(struct btrfs_fs_info *fs_info, struct btrfs_chunk_map *map); void btrfs_release_disk_super(struct btrfs_super_block *super); diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index e2f16733c53f..605108ab21f3 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -1119,6 +1119,13 @@ enum btrfs_clear_op_type { BTRFS_CLEAR_OP_ZERO_NOUNMAP, /* Request unmapping the blocks and don't fall back to writing zeros. */ BTRFS_CLEAR_OP_ZERO_NOFALLBACK, + + /* + * Only reset status of previously cleared (by any operation) chunks, + * tracked in memory since the last mount. Without that repeated calls + * to clear will skip already processed chunks. + */ + BTRFS_CLEAR_OP_RESET_CHUNK_STATUS_CACHE, BTRFS_NR_CLEAR_OP_TYPES, };