diff options
author | Yongqiang Yang <xiaoqiangnk@gmail.com> | 2012-01-03 23:41:39 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-01-03 23:41:39 -0500 |
commit | 2e10e2f2e5a800a54ad2f16dfdd8c034e005958b (patch) | |
tree | db5e556ab10f5b06824b6acb96155b2190750986 /fs | |
parent | 083f5b24cc55448e0602a807a5c2872e1f3796e2 (diff) |
ext4: add a function which updates the super block during online resizing
This patch adds a function named ext4_update_super() which updates
super block so the newly created block groups are visible to the file
system. This code is copied from ext4_group_add().
The function will be used by new resize implementation.
Signed-off-by: Yongqiang Yang <xiaoqiangnk@gmail.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/resize.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 098bdb8e97cb..eb0aebcca55f 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -1142,6 +1142,100 @@ static int ext4_setup_new_descs(handle_t *handle, struct super_block *sb, | |||
1142 | return err; | 1142 | return err; |
1143 | } | 1143 | } |
1144 | 1144 | ||
1145 | /* | ||
1146 | * ext4_update_super() updates the super block so that the newly added | ||
1147 | * groups can be seen by the filesystem. | ||
1148 | * | ||
1149 | * @sb: super block | ||
1150 | * @flex_gd: new added groups | ||
1151 | */ | ||
1152 | static void ext4_update_super(struct super_block *sb, | ||
1153 | struct ext4_new_flex_group_data *flex_gd) | ||
1154 | { | ||
1155 | ext4_fsblk_t blocks_count = 0; | ||
1156 | ext4_fsblk_t free_blocks = 0; | ||
1157 | ext4_fsblk_t reserved_blocks = 0; | ||
1158 | struct ext4_new_group_data *group_data = flex_gd->groups; | ||
1159 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
1160 | struct ext4_super_block *es = sbi->s_es; | ||
1161 | int i; | ||
1162 | |||
1163 | BUG_ON(flex_gd->count == 0 || group_data == NULL); | ||
1164 | /* | ||
1165 | * Make the new blocks and inodes valid next. We do this before | ||
1166 | * increasing the group count so that once the group is enabled, | ||
1167 | * all of its blocks and inodes are already valid. | ||
1168 | * | ||
1169 | * We always allocate group-by-group, then block-by-block or | ||
1170 | * inode-by-inode within a group, so enabling these | ||
1171 | * blocks/inodes before the group is live won't actually let us | ||
1172 | * allocate the new space yet. | ||
1173 | */ | ||
1174 | for (i = 0; i < flex_gd->count; i++) { | ||
1175 | blocks_count += group_data[i].blocks_count; | ||
1176 | free_blocks += group_data[i].free_blocks_count; | ||
1177 | } | ||
1178 | |||
1179 | reserved_blocks = ext4_r_blocks_count(es) * 100; | ||
1180 | do_div(reserved_blocks, ext4_blocks_count(es)); | ||
1181 | reserved_blocks *= blocks_count; | ||
1182 | do_div(reserved_blocks, 100); | ||
1183 | |||
1184 | ext4_blocks_count_set(es, ext4_blocks_count(es) + blocks_count); | ||
1185 | le32_add_cpu(&es->s_inodes_count, EXT4_INODES_PER_GROUP(sb) * | ||
1186 | flex_gd->count); | ||
1187 | |||
1188 | /* | ||
1189 | * We need to protect s_groups_count against other CPUs seeing | ||
1190 | * inconsistent state in the superblock. | ||
1191 | * | ||
1192 | * The precise rules we use are: | ||
1193 | * | ||
1194 | * * Writers must perform a smp_wmb() after updating all | ||
1195 | * dependent data and before modifying the groups count | ||
1196 | * | ||
1197 | * * Readers must perform an smp_rmb() after reading the groups | ||
1198 | * count and before reading any dependent data. | ||
1199 | * | ||
1200 | * NB. These rules can be relaxed when checking the group count | ||
1201 | * while freeing data, as we can only allocate from a block | ||
1202 | * group after serialising against the group count, and we can | ||
1203 | * only then free after serialising in turn against that | ||
1204 | * allocation. | ||
1205 | */ | ||
1206 | smp_wmb(); | ||
1207 | |||
1208 | /* Update the global fs size fields */ | ||
1209 | sbi->s_groups_count += flex_gd->count; | ||
1210 | |||
1211 | /* Update the reserved block counts only once the new group is | ||
1212 | * active. */ | ||
1213 | ext4_r_blocks_count_set(es, ext4_r_blocks_count(es) + | ||
1214 | reserved_blocks); | ||
1215 | |||
1216 | /* Update the free space counts */ | ||
1217 | percpu_counter_add(&sbi->s_freeclusters_counter, | ||
1218 | EXT4_B2C(sbi, free_blocks)); | ||
1219 | percpu_counter_add(&sbi->s_freeinodes_counter, | ||
1220 | EXT4_INODES_PER_GROUP(sb) * flex_gd->count); | ||
1221 | |||
1222 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, | ||
1223 | EXT4_FEATURE_INCOMPAT_FLEX_BG) && | ||
1224 | sbi->s_log_groups_per_flex) { | ||
1225 | ext4_group_t flex_group; | ||
1226 | flex_group = ext4_flex_group(sbi, group_data[0].group); | ||
1227 | atomic_add(EXT4_B2C(sbi, free_blocks), | ||
1228 | &sbi->s_flex_groups[flex_group].free_clusters); | ||
1229 | atomic_add(EXT4_INODES_PER_GROUP(sb) * flex_gd->count, | ||
1230 | &sbi->s_flex_groups[flex_group].free_inodes); | ||
1231 | } | ||
1232 | |||
1233 | if (test_opt(sb, DEBUG)) | ||
1234 | printk(KERN_DEBUG "EXT4-fs: added group %u:" | ||
1235 | "%llu blocks(%llu free %llu reserved)\n", flex_gd->count, | ||
1236 | blocks_count, free_blocks, reserved_blocks); | ||
1237 | } | ||
1238 | |||
1145 | /* Add group descriptor data to an existing or new group descriptor block. | 1239 | /* Add group descriptor data to an existing or new group descriptor block. |
1146 | * Ensure we handle all possible error conditions _before_ we start modifying | 1240 | * Ensure we handle all possible error conditions _before_ we start modifying |
1147 | * the filesystem, because we cannot abort the transaction and not have it | 1241 | * the filesystem, because we cannot abort the transaction and not have it |