aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorYongqiang Yang <xiaoqiangnk@gmail.com>2012-01-03 23:41:39 -0500
committerTheodore Ts'o <tytso@mit.edu>2012-01-03 23:41:39 -0500
commit2e10e2f2e5a800a54ad2f16dfdd8c034e005958b (patch)
treedb5e556ab10f5b06824b6acb96155b2190750986 /fs
parent083f5b24cc55448e0602a807a5c2872e1f3796e2 (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.c94
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 */
1152static 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