Skip to content

Commit 9937783

Browse files
riteshharjanitytso
authored andcommitted
ext4: mballoc: use lock for checking free blocks while retrying
Currently while doing block allocation grp->bb_free may be getting modified if discard is happening in parallel. For e.g. consider a case where there are lot of threads who have preallocated lot of blocks and there is a thread which is trying to discard all of this group's PA. Now it could happen that we see all of those group's bb_free is zero and fail the allocation while there is sufficient space if we free up all the PA. So this patch adds another flag "EXT4_MB_STRICT_CHECK" which will be set if we are unable to allocate any blocks in the first try (since we may not have considered blocks about to be discarded from PA lists). So during retry attempt to allocate blocks we will use ext4_lock_group() for checking if the group is good or not. Signed-off-by: Ritesh Harjani <[email protected]> Link: https://lore.kernel.org/r/9cb740a117c958c36596f167b12af1beae9a68b7.1589955723.git.riteshh@linux.ibm.com Signed-off-by: Theodore Ts'o <[email protected]>
1 parent 8ef123f commit 9937783

File tree

3 files changed

+16
-2
lines changed

3 files changed

+16
-2
lines changed

fs/ext4/ext4.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ enum SHIFT_DIRECTION {
150150
#define EXT4_MB_USE_ROOT_BLOCKS 0x1000
151151
/* Use blocks from reserved pool */
152152
#define EXT4_MB_USE_RESERVED 0x2000
153+
/* Do strict check for free blocks while retrying block allocation */
154+
#define EXT4_MB_STRICT_CHECK 0x4000
153155

154156
struct ext4_allocation_request {
155157
/* target inode for block we're allocating */

fs/ext4/mballoc.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2176,16 +2176,22 @@ static int ext4_mb_good_group_nolock(struct ext4_allocation_context *ac,
21762176
ext4_group_t group, int cr)
21772177
{
21782178
struct ext4_group_info *grp = ext4_get_group_info(ac->ac_sb, group);
2179+
struct super_block *sb = ac->ac_sb;
2180+
bool should_lock = ac->ac_flags & EXT4_MB_STRICT_CHECK;
21792181
ext4_grpblk_t free;
21802182
int ret = 0;
21812183

2184+
if (should_lock)
2185+
ext4_lock_group(sb, group);
21822186
free = grp->bb_free;
21832187
if (free == 0)
21842188
goto out;
21852189
if (cr <= 2 && free < ac->ac_g_ex.fe_len)
21862190
goto out;
21872191
if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(grp)))
21882192
goto out;
2193+
if (should_lock)
2194+
ext4_unlock_group(sb, group);
21892195

21902196
/* We only do this if the grp has never been initialized */
21912197
if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
@@ -2194,8 +2200,12 @@ static int ext4_mb_good_group_nolock(struct ext4_allocation_context *ac,
21942200
return ret;
21952201
}
21962202

2203+
if (should_lock)
2204+
ext4_lock_group(sb, group);
21972205
ret = ext4_mb_good_group(ac, group, cr);
21982206
out:
2207+
if (should_lock)
2208+
ext4_unlock_group(sb, group);
21992209
return ret;
22002210
}
22012211

@@ -4610,7 +4620,8 @@ static bool ext4_mb_discard_preallocations_should_retry(struct super_block *sb,
46104620
goto out_dbg;
46114621
}
46124622
seq_retry = ext4_get_discard_pa_seq_sum();
4613-
if (seq_retry != *seq) {
4623+
if (!(ac->ac_flags & EXT4_MB_STRICT_CHECK) || seq_retry != *seq) {
4624+
ac->ac_flags |= EXT4_MB_STRICT_CHECK;
46144625
*seq = seq_retry;
46154626
ret = true;
46164627
}

include/trace/events/ext4.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ struct partial_cluster;
3535
{ EXT4_MB_DELALLOC_RESERVED, "DELALLOC_RESV" }, \
3636
{ EXT4_MB_STREAM_ALLOC, "STREAM_ALLOC" }, \
3737
{ EXT4_MB_USE_ROOT_BLOCKS, "USE_ROOT_BLKS" }, \
38-
{ EXT4_MB_USE_RESERVED, "USE_RESV" })
38+
{ EXT4_MB_USE_RESERVED, "USE_RESV" }, \
39+
{ EXT4_MB_STRICT_CHECK, "STRICT_CHECK" })
3940

4041
#define show_map_flags(flags) __print_flags(flags, "|", \
4142
{ EXT4_GET_BLOCKS_CREATE, "CREATE" }, \

0 commit comments

Comments
 (0)