With file system formated for RAID arrays we can have inode bitmap and block bitmap after inode table. Make sure we move them around properly when doing inode resize. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@xxxxxxxxxxxxxxxxxx> --- Changes from v2: o Set proper retval when we failed to get a mapping block in the same group. This make sure inode resize fails if we failed to get a mapping fs meta data block in the same group. misc/tune2fs.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 84 insertions(+), 1 deletions(-) diff --git a/misc/tune2fs.c b/misc/tune2fs.c index 08fff29..966738b 100644 --- a/misc/tune2fs.c +++ b/misc/tune2fs.c @@ -1003,10 +1003,39 @@ static int get_move_bitmaps(ext2_filsys fs, int new_ino_blks_per_grp, return 0; } +static int ext2fs_is_meta_block(ext2_filsys fs, blk_t blk) +{ + dgrp_t group; + group = ext2fs_group_of_blk(fs, blk); + if (fs->group_desc[group].bg_block_bitmap == blk) + return 1; + if (fs->group_desc[group].bg_inode_bitmap == blk) + return 1; + return 0; +} + +static int ext2fs_is_block_in_group(ext2_filsys fs, dgrp_t group, blk_t blk) +{ + blk_t start_blk, end_blk; + start_blk = fs->super->s_first_data_block + + EXT2_BLOCKS_PER_GROUP(fs->super) * group; + /* + * We cannot get new block beyond end_blk for for the last block group + * so we can check with EXT2_BLOCKS_PER_GROUP even for last block group + */ + end_blk = start_blk + EXT2_BLOCKS_PER_GROUP(fs->super); + if (blk >= start_blk && blk <= end_blk) + return 1; + return 0; +} + static int move_block(ext2_filsys fs, ext2fs_block_bitmap bmap) { + char *buf; + dgrp_t group; errcode_t retval; + int meta_data = 0; blk_t blk, new_blk, goal; struct blk_move *bmv; @@ -1019,11 +1048,31 @@ static int move_block(ext2_filsys fs, ext2fs_block_bitmap bmap) if (!ext2fs_test_block_bitmap(bmap, blk)) continue; - goal = new_blk; + if (ext2fs_is_meta_block(fs, blk)) { + /* + * If the block is mapping a fs meta data block + * like group desc/block bitmap/inode bitmap. We + * should find a block in the same group and fix + * the respective fs metadata pointers. Otherwise + * fail + */ + group = ext2fs_group_of_blk(fs, blk); + goal = ext2fs_group_first_block(fs, group); + meta_data = 1; + + } else { + goal = new_blk; + } retval = ext2fs_new_block(fs, goal, NULL, &new_blk); if (retval) goto err_out; + /* new fs meta data block should be in the same group */ + if (meta_data && !ext2fs_is_block_in_group(fs, group, new_blk)) { + retval = ENOSPC; + goto err_out; + } + /* Mark this block as allocated */ ext2fs_mark_block_bitmap(fs->block_map, new_blk); @@ -1158,6 +1207,36 @@ err_out: return retval; } +/* + * We need to scan for inode and block bitmaps that may need to be + * moved. This can take place if the filesystem was formatted for + * RAID arrays using the mke2fs's extended option "stride". + */ +static int group_desc_scan_and_fix(ext2_filsys fs, ext2fs_block_bitmap bmap) +{ + dgrp_t i; + blk_t blk, new_blk; + + for (i = 0; i < fs->group_desc_count; i++) { + blk = fs->group_desc[i].bg_block_bitmap; + if (ext2fs_test_block_bitmap(bmap, blk)) { + new_blk = translate_block(blk); + if (!new_blk) + continue; + fs->group_desc[i].bg_block_bitmap = new_blk; + } + + blk = fs->group_desc[i].bg_inode_bitmap; + if (ext2fs_test_block_bitmap(bmap, blk)) { + new_blk = translate_block(blk); + if (!new_blk) + continue; + fs->group_desc[i].bg_inode_bitmap = new_blk; + } + } + return 0; +} + static int expand_inode_table(ext2_filsys fs, unsigned long new_ino_size) { dgrp_t i; @@ -1349,6 +1428,10 @@ static int resize_inode(ext2_filsys fs, unsigned long new_size) if (retval) goto err_out_undo; + retval = group_desc_scan_and_fix(fs, bmap); + if (retval) + goto err_out_undo; + retval = expand_inode_table(fs, new_size); if (retval) goto err_out_undo; -- 1.6.4.13.ge6580 -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html