From 617446e4aad5acdc82bad8bb36d896f9ad480cf8 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 18 Aug 2009 22:27:42 -0400 Subject: [PATCH] e2fsck: Teach new_table_block() to allocate new itables/bitmaps with FLEX_BG 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" --- e2fsck/pass1.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 518c2ff..5672122 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -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); -- 1.8.3.1