Commit 6f27e5f7 authored by Luca Stefani's avatar Luca Stefani Committed by Wen Zhiwei
Browse files

btrfs: split remaining space to discard in chunks

stable inclusion
from stable-v6.6.57
commit f00545e8386e228aac739588b40a6f200e0f0ffc
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IB2M97

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=f00545e8386e228aac739588b40a6f200e0f0ffc

--------------------------------

commit a99fcb0158978ed332009449b484e5f3ca2d7df4 upstream.

Per Qu Wenruo in case we have a very large disk, e.g. 8TiB device,
mostly empty although we will do the split according to our super block
locations, the last super block ends at 256G, we can submit a huge
discard for the range [256G, 8T), causing a large delay.

Split the space left to discard based on BTRFS_MAX_DISCARD_CHUNK_SIZE in
preparation of introduction of cancellation points to trim. The value
of the chunk size is arbitrary, it can be higher or derived from actual
device capabilities but we can't easily read that using
bio_discard_limit().

Link: https://bugzilla.kernel.org/show_bug.cgi?id=219180
Link: https://bugzilla.suse.com/show_bug.cgi?id=1229737


CC: stable@vger.kernel.org # 5.15+
Signed-off-by: default avatarLuca Stefani <luca.stefani.ge1@gmail.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarWen Zhiwei <wenzhiwei@kylinos.cn>
parent 53b57054
Loading
Loading
Loading
Loading
+15 −4
Original line number Diff line number Diff line
@@ -1304,13 +1304,24 @@ static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len,
		bytes_left = end - start;
	}

	if (bytes_left) {
	while (bytes_left) {
		u64 bytes_to_discard = min(BTRFS_MAX_DISCARD_CHUNK_SIZE, bytes_left);

		ret = blkdev_issue_discard(bdev, start >> SECTOR_SHIFT,
					   bytes_left >> SECTOR_SHIFT,
					   bytes_to_discard >> SECTOR_SHIFT,
					   GFP_NOFS);
		if (!ret)
			*discarded_bytes += bytes_left;

		if (ret) {
			if (ret != -EOPNOTSUPP)
				break;
			continue;
		}

		start += bytes_to_discard;
		bytes_left -= bytes_to_discard;
		*discarded_bytes += bytes_to_discard;
	}

	return ret;
}

+6 −0
Original line number Diff line number Diff line
@@ -15,6 +15,12 @@

#define BTRFS_MAX_DATA_CHUNK_SIZE	(10ULL * SZ_1G)

/*
 * Arbitratry maximum size of one discard request to limit potentially long time
 * spent in blkdev_issue_discard().
 */
#define BTRFS_MAX_DISCARD_CHUNK_SIZE	(SZ_1G)

extern struct mutex uuid_mutex;

#define BTRFS_STRIPE_LEN		SZ_64K