Skip to content

Commit 8ef123f

Browse files
riteshharjanitytso
authored andcommitted
ext4: mballoc: refactor ext4_mb_good_group()
ext4_mb_good_group() definition was changed some time back and now it even initializes the buddy cache (via ext4_mb_init_group()), if in case the EXT4_MB_GRP_NEED_INIT() is true for a group. Note that ext4_mb_init_group() could sleep and so should not be called under a spinlock held. This is fine as of now because ext4_mb_good_group() is called before loading the buddy bitmap without ext4_lock_group() held and again called after loading the bitmap, only this time with ext4_lock_group() held. But still this whole thing is confusing. So this patch refactors out ext4_mb_good_group_nolock() which should be called when without holding ext4_lock_group(). Also in further patches we hold the spinlock (ext4_lock_group()) while doing any calculations which involves grp->bb_free or grp->bb_fragments. Signed-off-by: Ritesh Harjani <[email protected]> Link: https://lore.kernel.org/r/d9f7d031a5fbe1c943fae6bf1ff5cdf0604ae722.1589955723.git.riteshh@linux.ibm.com Signed-off-by: Theodore Ts'o <[email protected]>
1 parent 07b5b8e commit 8ef123f

File tree

1 file changed

+50
-28
lines changed

1 file changed

+50
-28
lines changed

fs/ext4/mballoc.c

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2106,39 +2106,31 @@ void ext4_mb_scan_aligned(struct ext4_allocation_context *ac,
21062106
}
21072107

21082108
/*
2109-
* This is now called BEFORE we load the buddy bitmap.
2109+
* This is also called BEFORE we load the buddy bitmap.
21102110
* Returns either 1 or 0 indicating that the group is either suitable
2111-
* for the allocation or not. In addition it can also return negative
2112-
* error code when something goes wrong.
2111+
* for the allocation or not.
21132112
*/
2114-
static int ext4_mb_good_group(struct ext4_allocation_context *ac,
2113+
static bool ext4_mb_good_group(struct ext4_allocation_context *ac,
21152114
ext4_group_t group, int cr)
21162115
{
2117-
unsigned free, fragments;
2116+
ext4_grpblk_t free, fragments;
21182117
int flex_size = ext4_flex_bg_size(EXT4_SB(ac->ac_sb));
21192118
struct ext4_group_info *grp = ext4_get_group_info(ac->ac_sb, group);
21202119

21212120
BUG_ON(cr < 0 || cr >= 4);
21222121

21232122
free = grp->bb_free;
21242123
if (free == 0)
2125-
return 0;
2124+
return false;
21262125
if (cr <= 2 && free < ac->ac_g_ex.fe_len)
2127-
return 0;
2126+
return false;
21282127

21292128
if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(grp)))
2130-
return 0;
2131-
2132-
/* We only do this if the grp has never been initialized */
2133-
if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
2134-
int ret = ext4_mb_init_group(ac->ac_sb, group, GFP_NOFS);
2135-
if (ret)
2136-
return ret;
2137-
}
2129+
return false;
21382130

21392131
fragments = grp->bb_fragments;
21402132
if (fragments == 0)
2141-
return 0;
2133+
return false;
21422134

21432135
switch (cr) {
21442136
case 0:
@@ -2148,31 +2140,63 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
21482140
if ((ac->ac_flags & EXT4_MB_HINT_DATA) &&
21492141
(flex_size >= EXT4_FLEX_SIZE_DIR_ALLOC_SCHEME) &&
21502142
((group % flex_size) == 0))
2151-
return 0;
2143+
return false;
21522144

21532145
if ((ac->ac_2order > ac->ac_sb->s_blocksize_bits+1) ||
21542146
(free / fragments) >= ac->ac_g_ex.fe_len)
2155-
return 1;
2147+
return true;
21562148

21572149
if (grp->bb_largest_free_order < ac->ac_2order)
2158-
return 0;
2150+
return false;
21592151

2160-
return 1;
2152+
return true;
21612153
case 1:
21622154
if ((free / fragments) >= ac->ac_g_ex.fe_len)
2163-
return 1;
2155+
return true;
21642156
break;
21652157
case 2:
21662158
if (free >= ac->ac_g_ex.fe_len)
2167-
return 1;
2159+
return true;
21682160
break;
21692161
case 3:
2170-
return 1;
2162+
return true;
21712163
default:
21722164
BUG();
21732165
}
21742166

2175-
return 0;
2167+
return false;
2168+
}
2169+
2170+
/*
2171+
* This could return negative error code if something goes wrong
2172+
* during ext4_mb_init_group(). This should not be called with
2173+
* ext4_lock_group() held.
2174+
*/
2175+
static int ext4_mb_good_group_nolock(struct ext4_allocation_context *ac,
2176+
ext4_group_t group, int cr)
2177+
{
2178+
struct ext4_group_info *grp = ext4_get_group_info(ac->ac_sb, group);
2179+
ext4_grpblk_t free;
2180+
int ret = 0;
2181+
2182+
free = grp->bb_free;
2183+
if (free == 0)
2184+
goto out;
2185+
if (cr <= 2 && free < ac->ac_g_ex.fe_len)
2186+
goto out;
2187+
if (unlikely(EXT4_MB_GRP_BBITMAP_CORRUPT(grp)))
2188+
goto out;
2189+
2190+
/* We only do this if the grp has never been initialized */
2191+
if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
2192+
ret = ext4_mb_init_group(ac->ac_sb, group, GFP_NOFS);
2193+
if (ret)
2194+
return ret;
2195+
}
2196+
2197+
ret = ext4_mb_good_group(ac, group, cr);
2198+
out:
2199+
return ret;
21762200
}
21772201

21782202
static noinline_for_stack int
@@ -2260,7 +2284,7 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
22602284
group = 0;
22612285

22622286
/* This now checks without needing the buddy page */
2263-
ret = ext4_mb_good_group(ac, group, cr);
2287+
ret = ext4_mb_good_group_nolock(ac, group, cr);
22642288
if (ret <= 0) {
22652289
if (!first_err)
22662290
first_err = ret;
@@ -2278,11 +2302,9 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
22782302
* block group
22792303
*/
22802304
ret = ext4_mb_good_group(ac, group, cr);
2281-
if (ret <= 0) {
2305+
if (ret == 0) {
22822306
ext4_unlock_group(sb, group);
22832307
ext4_mb_unload_buddy(&e4b);
2284-
if (!first_err)
2285-
first_err = ret;
22862308
continue;
22872309
}
22882310

0 commit comments

Comments
 (0)