Whamcloud - gitweb
e2fsck: Teach new_table_block() to allocate new itables/bitmaps with FLEX_BG
authorTheodore Ts'o <tytso@mit.edu>
Wed, 19 Aug 2009 02:27:42 +0000 (22:27 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Wed, 19 Aug 2009 03:06:30 +0000 (23:06 -0400)
If the filesystem feature FLEX_BG is enabled, the inode table and
bitmap blocks can be located anywhere in the inode table.  So for
FLEX_BG filesystems, new_table_block() now tries allocate in the block
group's flex_bg first, and if there is no space in the local flex_bg,
then try to allocate from the whole filesystem.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
e2fsck/pass1.c

index 518c2ff..5672122 100644 (file)
@@ -2376,9 +2376,10 @@ static void new_table_block(e2fsck_t ctx, blk_t first_block, int group,
                            const char *name, int num, blk_t *new_block)
 {
        ext2_filsys fs = ctx->fs;
+       dgrp_t          last_grp;
        blk_t           old_block = *new_block;
        blk_t           last_block;
-       int             i;
+       int             i, is_flexbg, flexbg, flexbg_size;
        char            *buf;
        struct problem_context  pctx;
 
@@ -2388,19 +2389,44 @@ static void new_table_block(e2fsck_t ctx, blk_t first_block, int group,
        pctx.blk = old_block;
        pctx.str = name;
 
-       last_block = ext2fs_group_last_block(fs, group);
+       /*
+        * For flex_bg filesystems, first try to allocate the metadata
+        * within the flex_bg, and if that fails then try finding the
+        * space anywhere in the filesystem.
+        */
+       is_flexbg = EXT2_HAS_INCOMPAT_FEATURE(fs->super,
+                                             EXT4_FEATURE_INCOMPAT_FLEX_BG);
+       if (is_flexbg) {
+               flexbg_size = 1 << fs->super->s_log_groups_per_flex;
+               flexbg = group / flexbg_size;
+               first_block = ext2fs_group_first_block(fs,
+                                                      flexbg_size * flexbg);
+               last_grp = group | (flexbg_size - 1);
+               if (last_grp > fs->group_desc_count)
+                       last_grp = fs->group_desc_count;
+               last_block = ext2fs_group_last_block(fs, last_grp);
+       } else
+               last_block = ext2fs_group_last_block(fs, group);
        pctx.errcode = ext2fs_get_free_blocks(fs, first_block, last_block,
-                                       num, ctx->block_found_map, new_block);
+                                             num, ctx->block_found_map,
+                                             new_block);
+       if (is_flexbg && (pctx.errcode == EXT2_ET_BLOCK_ALLOC_FAIL))
+               pctx.errcode = ext2fs_get_free_blocks(fs,
+                               fs->super->s_first_data_block,
+                               fs->super->s_blocks_count,
+                               num, ctx->block_found_map, new_block);
        if (pctx.errcode) {
                pctx.num = num;
                fix_problem(ctx, PR_1_RELOC_BLOCK_ALLOCATE, &pctx);
                ext2fs_unmark_valid(fs);
+               ctx->flags |= E2F_FLAG_ABORT;
                return;
        }
        pctx.errcode = ext2fs_get_mem(fs->blocksize, &buf);
        if (pctx.errcode) {
                fix_problem(ctx, PR_1_RELOC_MEMORY_ALLOCATE, &pctx);
                ext2fs_unmark_valid(fs);
+               ctx->flags |= E2F_FLAG_ABORT;
                return;
        }
        ext2fs_mark_super_dirty(fs);