ext4: add new helper interface ext4_try_to_trim_range()

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: Andreas Dilger <adilger@dilger.ca>
Signed-off-by: Wang Jianchao <wangjianchao@kuaishou.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20210724074124.25731-3-jianchao.wan9@gmail.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
Wang Jianchao 2021-07-24 15:41:21 +08:00 committed by Theodore Ts'o
parent bd2eea8d0a
commit 6920b39132

View file

@ -6218,6 +6218,54 @@ __acquires(bitlock)
return ret; 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 * ext4_trim_all_free -- function to trim all free space in alloc. group
* @sb: super block for file system * @sb: super block for file system
@ -6241,10 +6289,8 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
ext4_grpblk_t start, ext4_grpblk_t max, ext4_grpblk_t start, ext4_grpblk_t max,
ext4_grpblk_t minblocks) ext4_grpblk_t minblocks)
{ {
void *bitmap;
ext4_grpblk_t next, count = 0, free_count = 0;
struct ext4_buddy e4b; struct ext4_buddy e4b;
int ret = 0; int ret;
trace_ext4_trim_all_free(sb, group, start, max); trace_ext4_trim_all_free(sb, group, start, max);
@ -6254,57 +6300,23 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
ret, group); ret, group);
return ret; return ret;
} }
bitmap = e4b.bd_bitmap;
ext4_lock_group(sb, group); 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) ? if (!EXT4_MB_GRP_WAS_TRIMMED(e4b.bd_info) ||
e4b.bd_info->bb_first_free : start; minblocks < atomic_read(&EXT4_SB(sb)->s_last_trim_minblks)) {
ret = ext4_try_to_trim_range(sb, &e4b, start, max, minblocks);
while (start <= max) { if (ret >= 0)
start = mb_find_next_zero_bit(bitmap, max + 1, start); EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info);
if (start > max) } else {
break; ret = 0;
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, 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_unlock_group(sb, group);
ext4_mb_unload_buddy(&e4b); ext4_mb_unload_buddy(&e4b);
ext4_debug("trimmed %d blocks in the group %d\n", ext4_debug("trimmed %d blocks in the group %d\n",
count, group); ret, group);
return ret; return ret;
} }