EXT4_MB_HINT_GOAL_ONLY is currently unused. This patch teaches ext4_mb_discard_preallocations() to discard only that preallocated range, which contains a specified block, in case of the flag is set. Otherwise, a preallocated range is not discarded. Signed-off-by: Kirill Tkhai <ktkhai@xxxxxxxxxxxxx> --- fs/ext4/mballoc.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 51a78eb65f3c..b1b3c5526d1a 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3894,8 +3894,8 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b, * 1) how many requested */ static noinline_for_stack int -ext4_mb_discard_group_preallocations(struct super_block *sb, - ext4_group_t group, int needed) +ext4_mb_discard_group_preallocations(struct super_block *sb, ext4_group_t group, + int needed, ext4_fsblk_t goal) { struct ext4_group_info *grp = ext4_get_group_info(sb, group); struct buffer_head *bitmap_bh = NULL; @@ -3947,6 +3947,12 @@ ext4_mb_discard_group_preallocations(struct super_block *sb, continue; } + if (goal != (ext4_fsblk_t)-1 && + (goal < pa->pa_pstart || goal >= pa->pa_pstart + pa->pa_len)) { + spin_unlock(&pa->pa_lock); + continue; + } + /* seems this one can be freed ... */ pa->pa_deleted = 1; @@ -4462,15 +4468,23 @@ static int ext4_mb_release_context(struct ext4_allocation_context *ac) return 0; } -static int ext4_mb_discard_preallocations(struct super_block *sb, int needed) +static int ext4_mb_discard_preallocations(struct super_block *sb, + struct ext4_allocation_context *ac) { - ext4_group_t i, ngroups = ext4_get_groups_count(sb); + ext4_group_t i = 0, ngroups = ext4_get_groups_count(sb); + int needed = ac->ac_o_ex.fe_len; + ext4_fsblk_t goal = (ext4_fsblk_t)-1; int ret; int freed = 0; + if (ac->ac_flags & EXT4_MB_HINT_GOAL_ONLY) { + i = ac->ac_o_ex.fe_group; + ngroups = i + 1; + goal = ext4_grp_offs_to_block(ac->ac_sb, &ac->ac_g_ex); + } trace_ext4_mb_discard_preallocations(sb, needed); - for (i = 0; i < ngroups && needed > 0; i++) { - ret = ext4_mb_discard_group_preallocations(sb, i, needed); + for (; i < ngroups && needed > 0; i++) { + ret = ext4_mb_discard_group_preallocations(sb, i, needed, goal); freed += ret; needed -= ret; } @@ -4585,7 +4599,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, ar->len = ac->ac_b_ex.fe_len; } } else { - freed = ext4_mb_discard_preallocations(sb, ac->ac_o_ex.fe_len); + freed = ext4_mb_discard_preallocations(sb, ac); if (freed) goto repeat; *errp = -ENOSPC;