]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
tune2fs: Handle fs meta-data blocks during inode resize
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Thu, 6 Aug 2009 06:12:30 +0000 (11:42 +0530)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 20 Aug 2009 17:12:49 +0000 (13:12 -0400)
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@linux.vnet.ibm.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
misc/tune2fs.c

index d2d1539080592738fd6575173a470b5c58c30152..8593510eab95c871bd732a53e17bf8b25295f776 100644 (file)
@@ -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;
@@ -1350,6 +1429,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;