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.
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 <tytso@mit.edu>
+
+ * 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 <tytso@valinux.com>
* 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 @@
{
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 @@
/*
* 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 <tytso@mit.edu>
+
+ * 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 <tytso@mit.edu>
* 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 @@
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 @@
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 @@
{
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 @@
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 @@
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 @@
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 @@
*/
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 @@
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 @@
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 <tytso@mit.edu>
+
+ * 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 <tytso@snap.thunk.org>
* 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 @@
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 @@
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 @@
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 @@
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 <tytso@mit.edu>
+
+ * 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 <tytso@mit.edu>
* 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 @@
* 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 @@
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 @@
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 @@
} else
numblocks = fs->super->s_blocks_per_group;
- if (ext2fs_bg_has_super(fs, i)) {
- for (j=0; j < fs->desc_blocks+1; j++)
- ext2fs_mark_block_bitmap(fs->block_map,
- group_block + j);
- adjblocks = 1 + fs->desc_blocks;
+ 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 + has_super);
+ }
+
adjblocks += 2 + fs->inode_blocks_per_group;
numblocks -= adjblocks;
@@ -421,7 +447,8 @@
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 @@
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 @@
}
/*
+ * 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 @@
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 @@
* 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;
+ has_super = ext2fs_bg_has_super(fs, i);
+ if (has_super)
+ mark_fs_metablock(rfs, meta_bmap, i, group_blk);
- 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++;
- }
+ 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)