From 550a4afa24be35976edffe578555de30e06c456a Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 25 Jan 2005 03:09:24 -0500 Subject: [PATCH] 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) --- e2fsck/ChangeLog | 12 ++++++ e2fsck/super.c | 92 +++++++++++++++++++++++----------------- e2fsck/unix.c | 4 +- tests/ChangeLog | 4 ++ tests/f_summary_counts/expect.1 | 25 +++++++++++ tests/f_summary_counts/expect.2 | 7 +++ tests/f_summary_counts/image.gz | Bin 0 -> 440 bytes tests/f_summary_counts/name | 1 + tests/f_summary_counts/script | 4 ++ 9 files changed, 110 insertions(+), 39 deletions(-) create mode 100644 tests/f_summary_counts/expect.1 create mode 100644 tests/f_summary_counts/expect.2 create mode 100644 tests/f_summary_counts/image.gz create mode 100644 tests/f_summary_counts/name create mode 100644 tests/f_summary_counts/script diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog index 332f0c1..4effd27 100644 --- a/e2fsck/ChangeLog +++ b/e2fsck/ChangeLog @@ -1,3 +1,15 @@ +2005-01-25 Theodore Ts'o + + * 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 * super.c (check_resize_inode): If resize feature is set, but diff --git a/e2fsck/super.c b/e2fsck/super.c index 2e9e6a8..9a662f0 100644 --- a/e2fsck/super.c +++ b/e2fsck/super.c @@ -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); } @@ -611,21 +642,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. */ diff --git a/e2fsck/unix.c b/e2fsck/unix.c index 1716471..a8ac53d 100644 --- a/e2fsck/unix.c +++ b/e2fsck/unix.c @@ -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); diff --git a/tests/ChangeLog b/tests/ChangeLog index 7499e1b..c705a64 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,7 @@ +2005-01-25 Theodore Ts'o + + * f_summary_counts: New test case + 2005-01-21 Theodore Ts'o * r_resize_inode: Skip this test if resize2fs is not compiled (due diff --git a/tests/f_summary_counts/expect.1 b/tests/f_summary_counts/expect.1 new file mode 100644 index 0000000..5c528bb --- /dev/null +++ b/tests/f_summary_counts/expect.1 @@ -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 diff --git a/tests/f_summary_counts/expect.2 b/tests/f_summary_counts/expect.2 new file mode 100644 index 0000000..44bff62 --- /dev/null +++ b/tests/f_summary_counts/expect.2 @@ -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 diff --git a/tests/f_summary_counts/image.gz b/tests/f_summary_counts/image.gz new file mode 100644 index 0000000000000000000000000000000000000000..d527e9a7682cdf20f5f0e902d95a9ff0caa6e625 GIT binary patch literal 440 zcmb2|=HS@=_p2ilb7pR0dMd-)8}{DPi45!y%*DO4{;c-qd``<<3JOJ= zM5b`9eJ6V~v>@aU!#S%??*%)$9*7IX9$DHXs8Tz5PEkj5bHtZ<>~&A{zPAVUFgpFH83R z7tTApOtbM$##S%>+vd6o;a%=?Q}(&bc1re28n4|W==nTKPi1QRTa}d| zyRQFm-8e@__kWaRd_>&eK=beq_rBP^`hP!Z`+o<&FEf}f)I0oV{LB7D9+kmBT~M*E NUUKTHUWN&b3;_FTvv&Xh literal 0 HcmV?d00001 diff --git a/tests/f_summary_counts/name b/tests/f_summary_counts/name new file mode 100644 index 0000000..9fd1021 --- /dev/null +++ b/tests/f_summary_counts/name @@ -0,0 +1 @@ +incorrect inode/block free counts diff --git a/tests/f_summary_counts/script b/tests/f_summary_counts/script new file mode 100644 index 0000000..fc425ef --- /dev/null +++ b/tests/f_summary_counts/script @@ -0,0 +1,4 @@ +FSCK_OPT=-y +SECOND_FSCK_OPT=-yf + +. $cmd_dir/run_e2fsck -- 1.8.3.1