Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c71cb46a authored by Wang Jianchao's avatar Wang Jianchao Committed by Greg Kroah-Hartman
Browse files

ext4: add new helper interface ext4_try_to_trim_range()



[ Upstream commit 6920b3913235f517728bb69abe9b39047a987113 ]

There is no functional change in this patch but just split the
codes, which serachs free block and does trim, into a new function
ext4_try_to_trim_range. This is preparing for the following async
backgroup discard.

Reviewed-by: default avatarAndreas Dilger <adilger@dilger.ca>
Signed-off-by: default avatarWang Jianchao <wangjianchao@kuaishou.com>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20210724074124.25731-3-jianchao.wan9@gmail.com


Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
Stable-dep-of: 45e4ab320c9b ("ext4: move setting of trimmed bit into ext4_try_to_trim_range()")
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent b0dcbd4b
Loading
Loading
Loading
Loading
+57 −45
Original line number Diff line number Diff line
@@ -5194,6 +5194,54 @@ __acquires(bitlock)
	return ret;
}

static int ext4_try_to_trim_range(struct super_block *sb,
		struct ext4_buddy *e4b, ext4_grpblk_t start,
		ext4_grpblk_t max, ext4_grpblk_t minblocks)
{
	ext4_grpblk_t next, count, free_count;
	void *bitmap;
	int ret = 0;

	bitmap = e4b->bd_bitmap;
	start = (e4b->bd_info->bb_first_free > start) ?
		e4b->bd_info->bb_first_free : start;
	count = 0;
	free_count = 0;

	while (start <= max) {
		start = mb_find_next_zero_bit(bitmap, max + 1, start);
		if (start > max)
			break;
		next = mb_find_next_bit(bitmap, max + 1, start);

		if ((next - start) >= minblocks) {
			ret = ext4_trim_extent(sb, start, next - start, e4b);
			if (ret && ret != -EOPNOTSUPP)
				break;
			ret = 0;
			count += next - start;
		}
		free_count += next - start;
		start = next + 1;

		if (fatal_signal_pending(current)) {
			count = -ERESTARTSYS;
			break;
		}

		if (need_resched()) {
			ext4_unlock_group(sb, e4b->bd_group);
			cond_resched();
			ext4_lock_group(sb, e4b->bd_group);
		}

		if ((e4b->bd_info->bb_free - free_count) < minblocks)
			break;
	}

	return count;
}

/**
 * ext4_trim_all_free -- function to trim all free space in alloc. group
 * @sb:			super block for file system
@@ -5217,10 +5265,8 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
		   ext4_grpblk_t start, ext4_grpblk_t max,
		   ext4_grpblk_t minblocks)
{
	void *bitmap;
	ext4_grpblk_t next, count = 0, free_count = 0;
	struct ext4_buddy e4b;
	int ret = 0;
	int ret;

	trace_ext4_trim_all_free(sb, group, start, max);

@@ -5230,57 +5276,23 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
			     ret, group);
		return ret;
	}
	bitmap = e4b.bd_bitmap;

	ext4_lock_group(sb, group);
	if (EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) &&
	    minblocks >= atomic_read(&EXT4_SB(sb)->s_last_trim_minblks))
		goto out;

	start = (e4b.bd_info->bb_first_free > start) ?
		e4b.bd_info->bb_first_free : start;

	while (start <= max) {
		start = mb_find_next_zero_bit(bitmap, max + 1, start);
		if (start > max)
			break;
		next = mb_find_next_bit(bitmap, max + 1, start);

		if ((next - start) >= minblocks) {
			ret = ext4_trim_extent(sb, start, next - start, &e4b);
			if (ret && ret != -EOPNOTSUPP)
				break;
	if (!EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) ||
	    minblocks < atomic_read(&EXT4_SB(sb)->s_last_trim_minblks)) {
		ret = ext4_try_to_trim_range(sb, &e4b, start, max, minblocks);
		if (ret >= 0)
			EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info);
	} else {
		ret = 0;
			count += next - start;
	}
		free_count += next - start;
		start = next + 1;

		if (fatal_signal_pending(current)) {
			count = -ERESTARTSYS;
			break;
		}

		if (need_resched()) {
			ext4_unlock_group(sb, group);
			cond_resched();
			ext4_lock_group(sb, group);
		}

		if ((e4b.bd_info->bb_free - free_count) < minblocks)
			break;
	}

	if (!ret) {
		ret = count;
		EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info);
	}
out:
	ext4_unlock_group(sb, group);
	ext4_mb_unload_buddy(&e4b);

	ext4_debug("trimmed %d blocks in the group %d\n",
		count, group);
		ret, group);

	return ret;
}