From 76dd5e5c2842fb1a7b858aad3e68b5e9c16890c9 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 30 Oct 2002 23:07:21 -0500 Subject: [PATCH] Add support for the meta_bg feature flag to the resize2fs program. Fix bug in meta_bg support in mke2fs, e2fsck, and dumpe2fs; we were incorrectly reserving the legacy block groups desriptor blocks. --- e2fsck/ChangeLog | 6 ++ e2fsck/pass1.c | 8 ++- lib/ext2fs/ChangeLog | 10 +++ lib/ext2fs/alloc_tables.c | 41 +++++------ lib/ext2fs/closefs.c | 11 +-- lib/ext2fs/initialize.c | 13 ++-- misc/ChangeLog | 9 +++ misc/dumpe2fs.c | 25 +++---- misc/mke2fs.c | 2 +- resize/ChangeLog | 10 +++ resize/main.c | 3 +- resize/resize2fs.c | 173 ++++++++++++++++++++++++++++++++++------------ 12 files changed, 213 insertions(+), 98 deletions(-) diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog index 9de2cdd..f781678 100644 --- a/e2fsck/ChangeLog +++ b/e2fsck/ChangeLog @@ -1,3 +1,9 @@ +2002-10-30 Theodore Ts'o + + * pass1.c (mark_table_blocks): Fix bug in meta_bg support; only + mark blocks legacy group descriptor blocks up to + s_first_meta_bg. + 2002-10-20 Theodore Ts'o * pass1.c (mark_table_blocks): Add support for the meta_blockgroup diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index c685581..f25be76 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -1793,12 +1793,16 @@ static void mark_table_blocks(e2fsck_t ctx) { ext2_filsys fs = ctx->fs; blk_t block, b; - int i, j, has_super, meta_bg, meta_bg_size; + int i, j, has_super, meta_bg, meta_bg_size, old_desc_blocks; struct problem_context pctx; clear_problem_context(&pctx); block = fs->super->s_first_data_block; + if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) + old_desc_blocks = fs->super->s_first_meta_bg; + else + old_desc_blocks = fs->desc_blocks; for (i = 0; i < fs->group_desc_count; i++) { pctx.group = i; @@ -1819,7 +1823,7 @@ static void mark_table_blocks(e2fsck_t ctx) /* * Mark this group's copy of the descriptors */ - for (j = 0; j < fs->desc_blocks; j++) { + for (j = 0; j < old_desc_blocks; j++) { ext2fs_mark_block_bitmap(ctx->block_found_map, block + j + 1); } diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index 079615c..57e1d85 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,3 +1,13 @@ +2002-10-30 Theodore Ts'o + + * alloc_tables.c (ext2fs_allocate_group_table): Allocate the inode + table so that it buts up against the bitmap blocks, to + avoid block fragmentation. + + * closefs.c (write_bgdesc), initalize.c (ext2fs_initialize): Fix + bug; only allocate group descriptor blocks up to + s_first_meta_bg. + 2002-10-25 Theodore Ts'o * ext2_fs.h: Add a new superblock field, s_mkfs_time, so that we diff --git a/lib/ext2fs/alloc_tables.c b/lib/ext2fs/alloc_tables.c index ca274cc..0326321 100644 --- a/lib/ext2fs/alloc_tables.c +++ b/lib/ext2fs/alloc_tables.c @@ -41,38 +41,17 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, if (last_blk >= fs->super->s_blocks_count) last_blk = fs->super->s_blocks_count - 1; - start_blk = group_blk + 3 + fs->desc_blocks; - if (start_blk > last_blk) - start_blk = group_blk; - if (!bmap) bmap = fs->block_map; /* - * Allocate the inode table - */ - if (!fs->group_desc[group].bg_inode_table) { - retval = ext2fs_get_free_blocks(fs, start_blk, last_blk, - fs->inode_blocks_per_group, - bmap, &new_blk); - if (retval) - return retval; - for (j=0, blk = new_blk; - j < fs->inode_blocks_per_group; - j++, blk++) - ext2fs_mark_block_bitmap(bmap, blk); - fs->group_desc[group].bg_inode_table = new_blk; - } - - /* * Allocate the block and inode bitmaps, if necessary */ if (fs->stride) { - start_blk += fs->inode_blocks_per_group; + start_blk = group_blk + fs->inode_blocks_per_group; start_blk += ((fs->stride * group) % (last_blk - start_blk)); if (start_blk > last_blk) - /* should never happen */ start_blk = group_blk; } else start_blk = group_blk; @@ -100,6 +79,24 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, ext2fs_mark_block_bitmap(bmap, new_blk); fs->group_desc[group].bg_inode_bitmap = new_blk; } + + /* + * Allocate the inode table + */ + if (!fs->group_desc[group].bg_inode_table) { + retval = ext2fs_get_free_blocks(fs, group_blk, last_blk, + fs->inode_blocks_per_group, + bmap, &new_blk); + if (retval) + return retval; + for (j=0, blk = new_blk; + j < fs->inode_blocks_per_group; + j++, blk++) + ext2fs_mark_block_bitmap(bmap, blk); + fs->group_desc[group].bg_inode_table = new_blk; + } + + return 0; } diff --git a/lib/ext2fs/closefs.c b/lib/ext2fs/closefs.c index dcf244b..c96b7ab 100644 --- a/lib/ext2fs/closefs.c +++ b/lib/ext2fs/closefs.c @@ -122,18 +122,21 @@ static errcode_t write_bgdesc(ext2_filsys fs, dgrp_t group, blk_t group_block, { errcode_t retval; char *group_ptr = (char *) group_shadow; - int j; + int j, old_desc_blocks; int has_super = ext2fs_bg_has_super(fs, group); dgrp_t meta_bg_size, meta_bg; - blk_t blk; meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc)); meta_bg = group / meta_bg_size; + if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) + old_desc_blocks = fs->super->s_first_meta_bg; + else + old_desc_blocks = fs->desc_blocks; if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) || (meta_bg < fs->super->s_first_meta_bg)) { if (!has_super) return 0; - for (j=0; j < fs->desc_blocks; j++) { + for (j=0; j < old_desc_blocks; j++) { retval = io_channel_write_blk(fs->io, group_block+1+j, 1, group_ptr); @@ -180,7 +183,6 @@ errcode_t ext2fs_flush(ext2_filsys fs) dgrp_t i,j,maxgroup; blk_t group_block; errcode_t retval; - char *group_ptr; unsigned long fs_state; struct ext2_super_block *super_shadow = 0; struct ext2_group_desc *group_shadow = 0; @@ -277,7 +279,6 @@ errcode_t ext2fs_flush(ext2_filsys fs) group_shadow))) goto errout; } - next_group: group_block += EXT2_BLOCKS_PER_GROUP(fs->super); } fs->super->s_block_group_nr = 0; diff --git a/lib/ext2fs/initialize.c b/lib/ext2fs/initialize.c index ecb27d7..f5552e6 100644 --- a/lib/ext2fs/initialize.c +++ b/lib/ext2fs/initialize.c @@ -67,7 +67,7 @@ errcode_t ext2fs_initialize(const char *name, int flags, int i, j; blk_t numblocks; char *buf; - int meta_bg_size, meta_bg, has_super; + int meta_bg_size, meta_bg, has_super, old_desc_blocks; if (!param || !param->s_blocks_count) return EXT2_ET_INVALID_ARGUMENT; @@ -293,6 +293,10 @@ retry: */ group_block = super->s_first_data_block; super->s_free_blocks_count = 0; + if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) + old_desc_blocks = fs->super->s_first_meta_bg; + else + old_desc_blocks = fs->desc_blocks; for (i = 0; i < fs->group_desc_count; i++) { if (i == fs->group_desc_count-1) { numblocks = (fs->super->s_blocks_count - @@ -317,10 +321,10 @@ retry: EXT2_FEATURE_INCOMPAT_META_BG) || (meta_bg < fs->super->s_first_meta_bg)) { if (has_super) { - for (j=0; j < fs->desc_blocks; j++) + for (j=0; j < old_desc_blocks; j++) ext2fs_mark_block_bitmap(fs->block_map, group_block + j + 1); - numblocks -= fs->desc_blocks; + numblocks -= old_desc_blocks; } } else { if (has_super) @@ -357,6 +361,3 @@ cleanup: ext2fs_free(fs); return retval; } - - - diff --git a/misc/ChangeLog b/misc/ChangeLog index 6f6d29f..57e6bc1 100644 --- a/misc/ChangeLog +++ b/misc/ChangeLog @@ -1,3 +1,12 @@ +2002-10-30 Theodore Ts'o + + * dumpe2fs.c (list_desc): Fix bug in algorithm which determined + which blocks are used as backup superblock and block group + descriptors. + + * mke2fs.c (PRS): Fix bug which checked the tmp pointer + erreoneously (and needlessly). + 2002-10-28 * fsck.c (main): Fix bug reported by Gregory Mutt. Multiple diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c index d1308ef..073238e 100644 --- a/misc/dumpe2fs.c +++ b/misc/dumpe2fs.c @@ -87,8 +87,7 @@ static void list_desc (ext2_filsys fs) long diff; blk_t group_blk, next_blk; char *block_bitmap=NULL, *inode_bitmap=NULL; - int inode_blocks_per_group; - int group_desc_blocks; + int inode_blocks_per_group, old_desc_blocks; int meta_bg, meta_bg_size, has_super; if (fs->block_map) @@ -100,15 +99,12 @@ static void list_desc (ext2_filsys fs) EXT2_INODE_SIZE(fs->super)) + EXT2_BLOCK_SIZE(fs->super) - 1) / EXT2_BLOCK_SIZE(fs->super); - group_desc_blocks = ((fs->super->s_blocks_count - - fs->super->s_first_data_block + - EXT2_BLOCKS_PER_GROUP(fs->super) - 1) / - EXT2_BLOCKS_PER_GROUP(fs->super) + - EXT2_DESC_PER_BLOCK(fs->super) - 1) / - EXT2_DESC_PER_BLOCK(fs->super); - fputc('\n', stdout); group_blk = fs->super->s_first_data_block; + if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) + old_desc_blocks = fs->super->s_first_meta_bg; + else + old_desc_blocks = fs->desc_blocks; for (i = 0; i < fs->group_desc_count; i++) { next_blk = group_blk + fs->super->s_blocks_per_group; if (next_blk > fs->super->s_blocks_count) @@ -128,11 +124,12 @@ static void list_desc (ext2_filsys fs) if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) || (meta_bg < fs->super->s_first_meta_bg)) { - fputc(has_super ? ',' : ' ', stdout); - printf(_(" Group descriptors at ")); - printf(range_format, group_blk+1, - group_blk + group_desc_blocks); - fputc('\n', stdout); + if (has_super) { + printf(_(", Group descriptors at ")); + printf(range_format, group_blk+1, + group_blk + old_desc_blocks); + fputc('\n', stdout); + } } else { if (has_super) has_super = 1; diff --git a/misc/mke2fs.c b/misc/mke2fs.c index 1c83d9f..0371c37 100644 --- a/misc/mke2fs.c +++ b/misc/mke2fs.c @@ -1175,7 +1175,7 @@ static void PRS(int argc, char *argv[]) if (param.s_blocks_per_group) { if (param.s_blocks_per_group < 256 || - param.s_blocks_per_group > group_blk_max || *tmp) { + param.s_blocks_per_group > group_blk_max) { com_err(program_name, 0, _("blocks per group count out of range")); exit(1); diff --git a/resize/ChangeLog b/resize/ChangeLog index 5c6f663..54f0ae9 100644 --- a/resize/ChangeLog +++ b/resize/ChangeLog @@ -1,3 +1,13 @@ +2002-10-30 Theodore Ts'o + + * resize2fs.c (adjust_superblock, mark_table_blocks, + blocks_to_move): Add support for resizing filesystems that + use the meta block group layout. + + * main.c (main): Fixed bug that erroneously (and + needlessly) checked the incompat feature flag field + against the supported ro_compat feature set. + 2002-10-03 Theodore Ts'o * resize2fs.8.in: Fix typo in man page. diff --git a/resize/main.c b/resize/main.c index 7808b1d..841f4bd 100644 --- a/resize/main.c +++ b/resize/main.c @@ -204,8 +204,7 @@ int main (int argc, char ** argv) * Check for compatibility with the feature sets. We need to * be more stringent than ext2fs_open(). */ - if ((fs->super->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) || - (fs->super->s_feature_incompat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) { + if (fs->super->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) { com_err(program_name, EXT2_ET_UNSUPP_FEATURE, "(%s)", device_name); exit(1); diff --git a/resize/resize2fs.c b/resize/resize2fs.c index 4dd2b33..cc2fda4 100644 --- a/resize/resize2fs.c +++ b/resize/resize2fs.c @@ -179,6 +179,7 @@ static errcode_t adjust_superblock(ext2_resize_t rfs, blk_t new_size) blk_t blk, group_block; unsigned long i, j; int old_numblocks, numblocks, adjblocks; + int has_super, meta_bg, meta_bg_size, old_desc_blocks; unsigned long max_group; fs = rfs->new_fs; @@ -341,6 +342,10 @@ retry: if (retval) goto errout; } + if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) + old_desc_blocks = fs->super->s_first_meta_bg; + else + old_desc_blocks = fs->desc_blocks; for (i = rfs->old_fs->group_desc_count; i < fs->group_desc_count; i++) { memset(&fs->group_desc[i], 0, @@ -356,12 +361,33 @@ retry: } else numblocks = fs->super->s_blocks_per_group; - if (ext2fs_bg_has_super(fs, i)) { - for (j=0; j < fs->desc_blocks+1; j++) + has_super = ext2fs_bg_has_super(fs, i); + if (has_super) { + ext2fs_mark_block_bitmap(fs->block_map, group_block); + adjblocks++; + } + meta_bg_size = (fs->blocksize / + sizeof (struct ext2_group_desc)); + meta_bg = i / meta_bg_size; + if (!(fs->super->s_feature_incompat & + EXT2_FEATURE_INCOMPAT_META_BG) || + (meta_bg < fs->super->s_first_meta_bg)) { + if (has_super) { + for (j=0; j < old_desc_blocks; j++) + ext2fs_mark_block_bitmap(fs->block_map, + group_block + 1 + j); + adjblocks += old_desc_blocks; + } + } else { + if (has_super) + has_super = 1; + if (((i % meta_bg_size) == 0) || + ((i % meta_bg_size) == 1) || + ((i % meta_bg_size) == (meta_bg_size-1))) ext2fs_mark_block_bitmap(fs->block_map, - group_block + j); - adjblocks = 1 + fs->desc_blocks; + group_block + has_super); } + adjblocks += 2 + fs->inode_blocks_per_group; numblocks -= adjblocks; @@ -421,7 +447,8 @@ static errcode_t mark_table_blocks(ext2_filsys fs, ext2fs_block_bitmap *ret_bmap) { blk_t block, b; - int i,j; + int i,j, has_super, meta_bg, meta_bg_size; + int old_desc_blocks; ext2fs_block_bitmap bmap; errcode_t retval; @@ -430,21 +457,43 @@ static errcode_t mark_table_blocks(ext2_filsys fs, if (retval) return retval; + meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc)); block = fs->super->s_first_data_block; + if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) + old_desc_blocks = fs->super->s_first_meta_bg; + else + old_desc_blocks = fs->desc_blocks; for (i = 0; i < fs->group_desc_count; i++) { - if (ext2fs_bg_has_super(fs, i)) { + has_super = ext2fs_bg_has_super(fs, i); + if (has_super) /* * Mark this group's copy of the superblock */ ext2fs_mark_block_bitmap(bmap, block); - /* - * Mark this group's copy of the descriptors - */ - for (j = 0; j < fs->desc_blocks; j++) - ext2fs_mark_block_bitmap(bmap, block + j + 1); - } + meta_bg = i / meta_bg_size; + if (!(fs->super->s_feature_incompat & + EXT2_FEATURE_INCOMPAT_META_BG) || + (meta_bg < fs->super->s_first_meta_bg)) { + if (has_super) { + /* + * Mark this group's copy of the descriptors + */ + for (j = 0; j < old_desc_blocks; j++) + ext2fs_mark_block_bitmap(bmap, + block + j + 1); + } + } else { + if (has_super) + has_super = 1; + if (((i % meta_bg_size) == 0) || + ((i % meta_bg_size) == 1) || + ((i % meta_bg_size) == (meta_bg_size-1))) + ext2fs_mark_block_bitmap(bmap, + block + has_super); + } + /* * Mark the blocks used for the inode table */ @@ -470,13 +519,49 @@ static errcode_t mark_table_blocks(ext2_filsys fs, } /* + * This function checks to see if a particular block (either a + * superblock or a block group descriptor) overlaps with an inode or + * block bitmap block, or with the inode table. + */ +static void mark_fs_metablock(ext2_resize_t rfs, + ext2fs_block_bitmap meta_bmap, + int group, blk_t blk) +{ + ext2_filsys fs = rfs->new_fs; + + ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk); + ext2fs_mark_block_bitmap(fs->block_map, blk); + + /* + * Check to see if we overlap with the inode or block bitmap, + * or the inode tables. If not, and the block is in use, then + * mark it as a block to be moved. + */ + if (IS_BLOCK_BM(fs, group, blk)) { + FS_BLOCK_BM(fs, group) = 0; + rfs->needed_blocks++; + } else if (IS_INODE_BM(fs, group, blk)) { + FS_INODE_BM(fs, group) = 0; + rfs->needed_blocks++; + } else if (IS_INODE_TB(fs, group, blk)) { + FS_INODE_TB(fs, group) = 0; + rfs->needed_blocks++; + } else if (ext2fs_test_block_bitmap(rfs->old_fs->block_map, blk) && + !ext2fs_test_block_bitmap(meta_bmap, blk)) { + ext2fs_mark_block_bitmap(rfs->move_blocks, blk); + rfs->needed_blocks++; + } +} + + +/* * This routine marks and unmarks reserved blocks in the new block * bitmap. It also determines which blocks need to be moved and * places this information into the move_blocks bitmap. */ static errcode_t blocks_to_move(ext2_resize_t rfs) { - int i, j, max_groups; + int i, j, max_groups, has_super, meta_bg, meta_bg_size; blk_t blk, group_blk; unsigned long old_blocks, new_blocks; errcode_t retval; @@ -518,9 +603,14 @@ static errcode_t blocks_to_move(ext2_resize_t rfs) ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk); } - old_blocks = old_fs->desc_blocks; - new_blocks = fs->desc_blocks; - + if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) { + old_blocks = old_fs->super->s_first_meta_bg; + new_blocks = fs->super->s_first_meta_bg; + } else { + old_blocks = old_fs->desc_blocks; + new_blocks = fs->desc_blocks; + } + if (old_blocks == new_blocks) { retval = 0; goto errout; @@ -556,38 +646,29 @@ static errcode_t blocks_to_move(ext2_resize_t rfs) * If we're increasing the number of descriptor blocks, life * gets interesting.... */ + meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc)); for (i = 0; i < max_groups; i++) { - if (!ext2fs_bg_has_super(fs, i)) - goto next_group; - - for (blk = group_blk; - blk < group_blk + 1 + new_blocks; blk++) { - ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk); - ext2fs_mark_block_bitmap(fs->block_map, blk); - - /* - * Check to see if we overlap with the inode - * or block bitmap, or the inode tables. If - * not, and the block is in use, then mark it - * as a block to be moved. - */ - if (IS_BLOCK_BM(fs, i, blk)) { - FS_BLOCK_BM(fs, i) = 0; - rfs->needed_blocks++; - } else if (IS_INODE_BM(fs, i, blk)) { - FS_INODE_BM(fs, i) = 0; - rfs->needed_blocks++; - } else if (IS_INODE_TB(fs, i, blk)) { - FS_INODE_TB(fs, i) = 0; - rfs->needed_blocks++; - } else if (ext2fs_test_block_bitmap(old_fs->block_map, - blk) && - !ext2fs_test_block_bitmap(meta_bmap, blk)) { - ext2fs_mark_block_bitmap(rfs->move_blocks, - blk); - rfs->needed_blocks++; - } + has_super = ext2fs_bg_has_super(fs, i); + if (has_super) + mark_fs_metablock(rfs, meta_bmap, i, group_blk); + + meta_bg = i / meta_bg_size; + if (!(fs->super->s_feature_incompat & + EXT2_FEATURE_INCOMPAT_META_BG) || + (meta_bg < fs->super->s_first_meta_bg)) { + for (blk = group_blk+1; + blk < group_blk + 1 + new_blocks; blk++) + mark_fs_metablock(rfs, meta_bmap, i, blk); + } else { + if (has_super) + has_super = 1; + if (((i % meta_bg_size) == 0) || + ((i % meta_bg_size) == 1) || + ((i % meta_bg_size) == (meta_bg_size-1))) + mark_fs_metablock(rfs, meta_bmap, i, + group_blk + has_super); } + if (fs->group_desc[i].bg_inode_table && fs->group_desc[i].bg_inode_bitmap && fs->group_desc[i].bg_block_bitmap) -- 1.8.3.1