Skip to content

Commit

Permalink
ext4: add a new function which adds a flex group to a fs
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Yongqiang Yang authored and Theodore Ts'o committed Jan 4, 2012
1 parent 3fbea4b commit 4bac1f8
Showing 1 changed file with 82 additions and 0 deletions.
82 changes: 82 additions & 0 deletions fs/ext4/resize.c
Original file line number Diff line number Diff line change
Expand Up @@ -1348,6 +1348,88 @@ static void ext4_update_super(struct super_block *sb,
blocks_count, free_blocks, reserved_blocks);
}

/* Add a flex group to an fs. Ensure we handle all possible error conditions
* _before_ we start modifying the filesystem, because we cannot abort the
* transaction and not have it write the data to disk.
*/
static int ext4_flex_group_add(struct super_block *sb,
struct inode *resize_inode,
struct ext4_new_flex_group_data *flex_gd)
{
struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_super_block *es = sbi->s_es;
ext4_fsblk_t o_blocks_count;
ext4_grpblk_t last;
ext4_group_t group;
handle_t *handle;
unsigned reserved_gdb;
int err = 0, err2 = 0, credit;

BUG_ON(!flex_gd->count || !flex_gd->groups || !flex_gd->bg_flags);

reserved_gdb = le16_to_cpu(es->s_reserved_gdt_blocks);
o_blocks_count = ext4_blocks_count(es);
ext4_get_group_no_and_offset(sb, o_blocks_count, &group, &last);
BUG_ON(last);

err = setup_new_flex_group_blocks(sb, flex_gd);
if (err)
goto exit;
/*
* We will always be modifying at least the superblock and GDT
* block. If we are adding a group past the last current GDT block,
* we will also modify the inode and the dindirect block. If we
* are adding a group with superblock/GDT backups we will also
* modify each of the reserved GDT dindirect blocks.
*/
credit = flex_gd->count * 4 + reserved_gdb;
handle = ext4_journal_start_sb(sb, credit);
if (IS_ERR(handle)) {
err = PTR_ERR(handle);
goto exit;
}

err = ext4_journal_get_write_access(handle, sbi->s_sbh);
if (err)
goto exit_journal;

group = flex_gd->groups[0].group;
BUG_ON(group != EXT4_SB(sb)->s_groups_count);
err = ext4_add_new_descs(handle, sb, group,
resize_inode, flex_gd->count);
if (err)
goto exit_journal;

err = ext4_setup_new_descs(handle, sb, flex_gd);
if (err)
goto exit_journal;

ext4_update_super(sb, flex_gd);

err = ext4_handle_dirty_super(handle, sb);

exit_journal:
err2 = ext4_journal_stop(handle);
if (!err)
err = err2;

if (!err) {
int i;
update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es,
sizeof(struct ext4_super_block));
for (i = 0; i < flex_gd->count; i++, group++) {
struct buffer_head *gdb_bh;
int gdb_num;
gdb_num = group / EXT4_BLOCKS_PER_GROUP(sb);
gdb_bh = sbi->s_group_desc[gdb_num];
update_backups(sb, gdb_bh->b_blocknr, gdb_bh->b_data,
gdb_bh->b_size);
}
}
exit:
return err;
}

/* Add group descriptor data to an existing or new group descriptor block.
* Ensure we handle all possible error conditions _before_ we start modifying
* the filesystem, because we cannot abort the transaction and not have it
Expand Down

0 comments on commit 4bac1f8

Please sign in to comment.