E2fsck will now check the individual block group inode and block free counts,

as well as the filesystem-wide inode and block free counts.  If any of the
free counts is too large, force a full filesystem check.  (Addresses 
Debian Bug #291571)
bitmap-optimize
Theodore Ts'o 2005-01-25 03:09:24 -05:00
parent fbc3514623
commit 550a4afa24
9 changed files with 110 additions and 39 deletions

View File

@ -1,3 +1,15 @@
2005-01-25 Theodore Ts'o <tytso@mit.edu>
* unix.c (main, check_if_skip): Set the valid flag earlier, and if
it is cleared by the superblock tests, then assume that
the filesystem contains errors and must be checked.
* super.c (check_super_block): Check the individual block group
inode and block free counts, as well as the filesystem
inode and block free counts. If any of the block/inode
free counts is too large, force a full filesystem check.
(Addresses Debian Bug: #291571)
2005-01-21 Theodore Ts'o <tytso@mit.edu>
* super.c (check_resize_inode): If resize feature is set, but

View File

@ -431,6 +431,7 @@ void check_super_block(e2fsck_t ctx)
ext2_filsys fs = ctx->fs;
blk_t first_block, last_block;
struct ext2_super_block *sb = fs->super;
struct ext2_group_desc *gd;
blk_t blocks_per_group = fs->super->s_blocks_per_group;
blk_t bpg_max;
int inodes_per_block;
@ -542,56 +543,86 @@ void check_super_block(e2fsck_t ctx)
/*
* Verify the group descriptors....
*/
first_block = fs->super->s_first_data_block;
first_block = sb->s_first_data_block;
last_block = first_block + blocks_per_group;
for (i = 0; i < fs->group_desc_count; i++) {
for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
pctx.group = i;
if (i == fs->group_desc_count - 1)
last_block = fs->super->s_blocks_count;
if ((fs->group_desc[i].bg_block_bitmap < first_block) ||
(fs->group_desc[i].bg_block_bitmap >= last_block)) {
pctx.blk = fs->group_desc[i].bg_block_bitmap;
last_block = sb->s_blocks_count;
if ((gd->bg_block_bitmap < first_block) ||
(gd->bg_block_bitmap >= last_block)) {
pctx.blk = gd->bg_block_bitmap;
if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
fs->group_desc[i].bg_block_bitmap = 0;
gd->bg_block_bitmap = 0;
}
if (fs->group_desc[i].bg_block_bitmap == 0) {
if (gd->bg_block_bitmap == 0) {
ctx->invalid_block_bitmap_flag[i]++;
ctx->invalid_bitmaps++;
}
if ((fs->group_desc[i].bg_inode_bitmap < first_block) ||
(fs->group_desc[i].bg_inode_bitmap >= last_block)) {
pctx.blk = fs->group_desc[i].bg_inode_bitmap;
if ((gd->bg_inode_bitmap < first_block) ||
(gd->bg_inode_bitmap >= last_block)) {
pctx.blk = gd->bg_inode_bitmap;
if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
fs->group_desc[i].bg_inode_bitmap = 0;
gd->bg_inode_bitmap = 0;
}
if (fs->group_desc[i].bg_inode_bitmap == 0) {
if (gd->bg_inode_bitmap == 0) {
ctx->invalid_inode_bitmap_flag[i]++;
ctx->invalid_bitmaps++;
}
if ((fs->group_desc[i].bg_inode_table < first_block) ||
((fs->group_desc[i].bg_inode_table +
if ((gd->bg_inode_table < first_block) ||
((gd->bg_inode_table +
fs->inode_blocks_per_group - 1) >= last_block)) {
pctx.blk = fs->group_desc[i].bg_inode_table;
pctx.blk = gd->bg_inode_table;
if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
fs->group_desc[i].bg_inode_table = 0;
gd->bg_inode_table = 0;
}
if (fs->group_desc[i].bg_inode_table == 0) {
if (gd->bg_inode_table == 0) {
ctx->invalid_inode_table_flag[i]++;
ctx->invalid_bitmaps++;
}
free_blocks += fs->group_desc[i].bg_free_blocks_count;
free_inodes += fs->group_desc[i].bg_free_inodes_count;
first_block += fs->super->s_blocks_per_group;
last_block += fs->super->s_blocks_per_group;
free_blocks += gd->bg_free_blocks_count;
free_inodes += gd->bg_free_inodes_count;
first_block += sb->s_blocks_per_group;
last_block += sb->s_blocks_per_group;
if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
(gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
(gd->bg_used_dirs_count > sb->s_inodes_per_group))
ext2fs_unmark_valid(fs);
}
/*
* Update the global counts from the block group counts. This
* is needed for an experimental patch which eliminates
* locking the entire filesystem when allocating blocks or
* inodes; if the filesystem is not unmounted cleanly, the
* global counts may not be accurate.
*/
if ((free_blocks != sb->s_free_blocks_count) ||
(free_inodes != sb->s_free_inodes_count)) {
if (ctx->options & E2F_OPT_READONLY)
ext2fs_unmark_valid(fs);
else {
sb->s_free_blocks_count = free_blocks;
sb->s_free_inodes_count = free_inodes;
ext2fs_mark_super_dirty(fs);
}
}
if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
(sb->s_free_inodes_count > sb->s_inodes_count))
ext2fs_unmark_valid(fs);
/*
* If we have invalid bitmaps, set the error state of the
* filesystem.
*/
if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
fs->super->s_state &= ~EXT2_VALID_FS;
sb->s_state &= ~EXT2_VALID_FS;
ext2fs_mark_super_dirty(fs);
}
@ -610,21 +641,6 @@ void check_super_block(e2fsck_t ctx)
}
#endif
/*
* Update the global counts from the block group counts. This
* is needed for an experimental patch which eliminates
* locking the entire filesystem when allocating blocks or
* inodes; if the filesystem is not unmounted cleanly, the
* global counts may not be accurate.
*/
if (!(ctx->options & E2F_OPT_READONLY) &&
((free_blocks != fs->super->s_free_blocks_count) ||
(free_inodes != fs->super->s_free_inodes_count))) {
fs->super->s_free_blocks_count = free_blocks;
fs->super->s_free_inodes_count = free_inodes;
ext2fs_mark_super_dirty(fs);
}
/*
* For the Hurd, check to see if the filetype option is set,
* since it doesn't support it.

View File

@ -262,7 +262,8 @@ static void check_if_skip(e2fsck_t ctx)
cflag || swapfs)
return;
if (fs->super->s_state & EXT2_ERROR_FS)
if ((fs->super->s_state & EXT2_ERROR_FS) ||
!ext2fs_test_valid(fs))
reason = _(" contains a file system with errors");
else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
reason = _(" was not cleanly unmounted");
@ -1060,6 +1061,7 @@ restart:
if (ctx->superblock)
set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
ext2fs_mark_valid(fs);
check_super_block(ctx);
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
fatal_error(ctx, 0);

View File

@ -1,3 +1,7 @@
2005-01-25 Theodore Ts'o <tytso@mit.edu>
* f_summary_counts: New test case
2005-01-21 Theodore Ts'o <tytso@mit.edu>
* r_resize_inode: Skip this test if resize2fs is not compiled (due

View File

@ -0,0 +1,25 @@
test_filesys contains a file system with errors, check forced.
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Free blocks count wrong for group #0 (200, counted=80).
Fix? yes
Free blocks count wrong (200, counted=80).
Fix? yes
Free inodes count wrong for group #0 (250, counted=5).
Fix? yes
Directories count wrong for group #0 (150, counted=2).
Fix? yes
Free inodes count wrong (250, counted=5).
Fix? yes
test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
test_filesys: 11/16 files (0.0% non-contiguous), 20/100 blocks
Exit status is 1

View File

@ -0,0 +1,7 @@
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
test_filesys: 11/16 files (0.0% non-contiguous), 20/100 blocks
Exit status is 0

Binary file not shown.

View File

@ -0,0 +1 @@
incorrect inode/block free counts

View File

@ -0,0 +1,4 @@
FSCK_OPT=-y
SECOND_FSCK_OPT=-yf
. $cmd_dir/run_e2fsck