diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2009-09-09 23:34:50 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2009-09-09 23:34:50 -0400 |
commit | f41c0750538667b87a19c93952e5d42fcc069bd7 (patch) | |
tree | 042076950064d1201e7e408aba0e96ccbd7e00e2 | |
parent | b6a758ec3af3ec236dbfdcf6a06b84ac8f94957e (diff) |
ext4: check for need init flag in ext4_mb_load_buddy
We should check for need init flag with the group's alloc_sem held, to
make sure while we are loading the buddy cache and holding a reference
to it, a file system resize can't add new blocks to same group.
The patch also drops the need init flag check in
ext4_mb_regular_allocator() because doing the check without holding
alloc_sem is racy.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
-rw-r--r-- | fs/ext4/mballoc.c | 39 |
1 files changed, 18 insertions, 21 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index fed5ac699141..484c9d10c7fa 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -1034,8 +1034,26 @@ ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group, | |||
1034 | * groups mapped by the page is blocked | 1034 | * groups mapped by the page is blocked |
1035 | * till we are done with allocation | 1035 | * till we are done with allocation |
1036 | */ | 1036 | */ |
1037 | repeat_load_buddy: | ||
1037 | down_read(e4b->alloc_semp); | 1038 | down_read(e4b->alloc_semp); |
1038 | 1039 | ||
1040 | if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) { | ||
1041 | /* we need to check for group need init flag | ||
1042 | * with alloc_semp held so that we can be sure | ||
1043 | * that new blocks didn't get added to the group | ||
1044 | * when we are loading the buddy cache | ||
1045 | */ | ||
1046 | up_read(e4b->alloc_semp); | ||
1047 | /* | ||
1048 | * we need full data about the group | ||
1049 | * to make a good selection | ||
1050 | */ | ||
1051 | ret = ext4_mb_init_group(sb, group); | ||
1052 | if (ret) | ||
1053 | return ret; | ||
1054 | goto repeat_load_buddy; | ||
1055 | } | ||
1056 | |||
1039 | /* | 1057 | /* |
1040 | * the buddy cache inode stores the block bitmap | 1058 | * the buddy cache inode stores the block bitmap |
1041 | * and buddy information in consecutive blocks. | 1059 | * and buddy information in consecutive blocks. |
@@ -2012,27 +2030,6 @@ repeat: | |||
2012 | if (grp->bb_free == 0) | 2030 | if (grp->bb_free == 0) |
2013 | continue; | 2031 | continue; |
2014 | 2032 | ||
2015 | /* | ||
2016 | * if the group is already init we check whether it is | ||
2017 | * a good group and if not we don't load the buddy | ||
2018 | */ | ||
2019 | if (EXT4_MB_GRP_NEED_INIT(grp)) { | ||
2020 | /* | ||
2021 | * we need full data about the group | ||
2022 | * to make a good selection | ||
2023 | */ | ||
2024 | err = ext4_mb_init_group(sb, group); | ||
2025 | if (err) | ||
2026 | goto out; | ||
2027 | } | ||
2028 | |||
2029 | /* | ||
2030 | * If the particular group doesn't satisfy our | ||
2031 | * criteria we continue with the next group | ||
2032 | */ | ||
2033 | if (!ext4_mb_good_group(ac, group, cr)) | ||
2034 | continue; | ||
2035 | |||
2036 | err = ext4_mb_load_buddy(sb, group, &e4b); | 2033 | err = ext4_mb_load_buddy(sb, group, &e4b); |
2037 | if (err) | 2034 | if (err) |
2038 | goto out; | 2035 | goto out; |