diff options
author | Yongqiang Yang <xiaoqiangnk@gmail.com> | 2012-01-03 23:44:38 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-01-03 23:44:38 -0500 |
commit | 4bac1f8cef7bfd2c62793f75aba66a5b8357dede (patch) | |
tree | 0cef082f69c53b66ec84af8bfdd65e8ddbad9f32 /fs/ext4/resize.c | |
parent | 3fbea4b3683a5dfa86489ef7799cbe55e8003dfa (diff) |
ext4: add a new function which adds a flex group to a fs
This patch adds a new function named ext4_flex_group_add() which adds a
flex group to a fs. The function is used by 64bit-resize interface.
Signed-off-by: Yongqiang Yang <xiaoqiangnk@gmail.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/resize.c')
-rw-r--r-- | fs/ext4/resize.c | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index a4075de73c72..dac23561f3eb 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -1348,6 +1348,88 @@ static void ext4_update_super(struct super_block *sb, | |||
1348 | blocks_count, free_blocks, reserved_blocks); | 1348 | blocks_count, free_blocks, reserved_blocks); |
1349 | } | 1349 | } |
1350 | 1350 | ||
1351 | /* Add a flex group to an fs. Ensure we handle all possible error conditions | ||
1352 | * _before_ we start modifying the filesystem, because we cannot abort the | ||
1353 | * transaction and not have it write the data to disk. | ||
1354 | */ | ||
1355 | static int ext4_flex_group_add(struct super_block *sb, | ||
1356 | struct inode *resize_inode, | ||
1357 | struct ext4_new_flex_group_data *flex_gd) | ||
1358 | { | ||
1359 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
1360 | struct ext4_super_block *es = sbi->s_es; | ||
1361 | ext4_fsblk_t o_blocks_count; | ||
1362 | ext4_grpblk_t last; | ||
1363 | ext4_group_t group; | ||
1364 | handle_t *handle; | ||
1365 | unsigned reserved_gdb; | ||
1366 | int err = 0, err2 = 0, credit; | ||
1367 | |||
1368 | BUG_ON(!flex_gd->count || !flex_gd->groups || !flex_gd->bg_flags); | ||
1369 | |||
1370 | reserved_gdb = le16_to_cpu(es->s_reserved_gdt_blocks); | ||
1371 | o_blocks_count = ext4_blocks_count(es); | ||
1372 | ext4_get_group_no_and_offset(sb, o_blocks_count, &group, &last); | ||
1373 | BUG_ON(last); | ||
1374 | |||
1375 | err = setup_new_flex_group_blocks(sb, flex_gd); | ||
1376 | if (err) | ||
1377 | goto exit; | ||
1378 | /* | ||
1379 | * We will always be modifying at least the superblock and GDT | ||
1380 | * block. If we are adding a group past the last current GDT block, | ||
1381 | * we will also modify the inode and the dindirect block. If we | ||
1382 | * are adding a group with superblock/GDT backups we will also | ||
1383 | * modify each of the reserved GDT dindirect blocks. | ||
1384 | */ | ||
1385 | credit = flex_gd->count * 4 + reserved_gdb; | ||
1386 | handle = ext4_journal_start_sb(sb, credit); | ||
1387 | if (IS_ERR(handle)) { | ||
1388 | err = PTR_ERR(handle); | ||
1389 | goto exit; | ||
1390 | } | ||
1391 | |||
1392 | err = ext4_journal_get_write_access(handle, sbi->s_sbh); | ||
1393 | if (err) | ||
1394 | goto exit_journal; | ||
1395 | |||
1396 | group = flex_gd->groups[0].group; | ||
1397 | BUG_ON(group != EXT4_SB(sb)->s_groups_count); | ||
1398 | err = ext4_add_new_descs(handle, sb, group, | ||
1399 | resize_inode, flex_gd->count); | ||
1400 | if (err) | ||
1401 | goto exit_journal; | ||
1402 | |||
1403 | err = ext4_setup_new_descs(handle, sb, flex_gd); | ||
1404 | if (err) | ||
1405 | goto exit_journal; | ||
1406 | |||
1407 | ext4_update_super(sb, flex_gd); | ||
1408 | |||
1409 | err = ext4_handle_dirty_super(handle, sb); | ||
1410 | |||
1411 | exit_journal: | ||
1412 | err2 = ext4_journal_stop(handle); | ||
1413 | if (!err) | ||
1414 | err = err2; | ||
1415 | |||
1416 | if (!err) { | ||
1417 | int i; | ||
1418 | update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es, | ||
1419 | sizeof(struct ext4_super_block)); | ||
1420 | for (i = 0; i < flex_gd->count; i++, group++) { | ||
1421 | struct buffer_head *gdb_bh; | ||
1422 | int gdb_num; | ||
1423 | gdb_num = group / EXT4_BLOCKS_PER_GROUP(sb); | ||
1424 | gdb_bh = sbi->s_group_desc[gdb_num]; | ||
1425 | update_backups(sb, gdb_bh->b_blocknr, gdb_bh->b_data, | ||
1426 | gdb_bh->b_size); | ||
1427 | } | ||
1428 | } | ||
1429 | exit: | ||
1430 | return err; | ||
1431 | } | ||
1432 | |||
1351 | /* Add group descriptor data to an existing or new group descriptor block. | 1433 | /* Add group descriptor data to an existing or new group descriptor block. |
1352 | * Ensure we handle all possible error conditions _before_ we start modifying | 1434 | * Ensure we handle all possible error conditions _before_ we start modifying |
1353 | * the filesystem, because we cannot abort the transaction and not have it | 1435 | * the filesystem, because we cannot abort the transaction and not have it |