From a3efe4842054175d01b465fbe0b29b9be8b800a1 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 16 Jun 2011 01:13:42 -0400 Subject: [PATCH] e2fsck: fix mysterious "FILE SYSTEM WAS MODIFIED" with no changes Commit 2a77a784a3 (firest released in e2fsprogs 1.33) compared superblock summary free blocks and inode counts with the allocation bitmap counts before starting the file system check proper, and if they differed, set the superblock and marked it as dirty. If no other file systme changes were required, this would cause a "*** FILE SYSTEM WAS MODIFIED ***" message without any explanation of what e2fsck had changed. We fix this by only setting the superblock summary free block/inodes counts if we are skipping a full check, and in non-preen mode, e2fsck will now print an explicit message stating how the superblock had been updated. In a full check, any updates to the superblock free blocks/inodes fields will be noted in pass5. This change requires changing a few test results (essentially reversing the changes made in commit 2a77a784a3). Signed-off-by: "Theodore Ts'o" --- e2fsck/e2fsck.h | 4 +++- e2fsck/problem.c | 10 ++++++++++ e2fsck/problem.h | 6 ++++++ e2fsck/super.c | 19 ++----------------- e2fsck/unix.c | 31 +++++++++++++++++++++++++++++++ tests/f_baddir/expect.1 | 3 +++ tests/f_dup/expect.1 | 2 +- tests/f_dup2/expect.1 | 2 +- tests/f_end-bitmap/expect.1 | 3 --- tests/f_lpf/expect.1 | 2 +- tests/f_summary_counts/expect.1 | 6 ------ tests/f_unused_itable/expect.1 | 3 --- 12 files changed, 58 insertions(+), 33 deletions(-) diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h index 486a71b0..b4a1a88d 100644 --- a/e2fsck/e2fsck.h +++ b/e2fsck/e2fsck.h @@ -212,10 +212,12 @@ struct e2fsck_struct { char *io_options; int flags; /* E2fsck internal flags */ int options; + int blocksize; /* blocksize */ blk64_t use_superblock; /* sb requested by user */ blk64_t superblock; /* sb used to open fs */ - int blocksize; /* blocksize */ blk64_t num_blocks; /* Total number of blocks */ + blk64_t free_blocks; + ino_t free_inodes; int mount_flags; blkid_cache blkid; /* blkid cache */ diff --git a/e2fsck/problem.c b/e2fsck/problem.c index fb900071..c5bebf85 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -402,6 +402,16 @@ static struct e2fsck_problem problem_table[] = { N_("One or more @b @g descriptor checksums are invalid. "), PROMPT_FIX, PR_PREEN_OK }, + /* Free inodes count wrong */ + { PR_0_FREE_INODE_COUNT, + N_("Setting free @is count to %j (was %i)\n"), + PROMPT_NONE, PR_PREEN_NOMSG }, + + /* Free blocks count wrong */ + { PR_0_FREE_BLOCK_COUNT, + N_("Setting free @bs count to %c (was %b)\n"), + PROMPT_NONE, PR_PREEN_NOMSG }, + /* Pass 1 errors */ /* Pass 1: Checking inodes, blocks, and sizes */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index 38b3c784..8379e0cf 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -227,6 +227,12 @@ struct problem_context { /* Block group checksum (latch question) */ #define PR_0_GDT_CSUM_LATCH 0x00003E +/* Free inodes count wrong */ +#define PR_0_FREE_INODE_COUNT 0x00003F + +/* Free blocks count wrong */ +#define PR_0_FREE_BLOCK_COUNT 0x000040 + /* * Pass 1 errors diff --git a/e2fsck/super.c b/e2fsck/super.c index 5d6aa7a3..3f9e3331 100644 --- a/e2fsck/super.c +++ b/e2fsck/super.c @@ -690,23 +690,8 @@ void check_super_block(e2fsck_t ctx) return; } - /* - * 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 != ext2fs_free_blocks_count(sb)) || - (free_inodes != sb->s_free_inodes_count)) { - if (ctx->options & E2F_OPT_READONLY) - ext2fs_unmark_valid(fs); - else { - ext2fs_free_blocks_count_set(sb, free_blocks); - sb->s_free_inodes_count = free_inodes; - ext2fs_mark_super_dirty(fs); - } - } + ctx->free_blocks = free_blocks; + ctx->free_inodes = free_inodes; if ((ext2fs_free_blocks_count(sb) > ext2fs_blocks_count(sb)) || (sb->s_free_inodes_count > sb->s_inodes_count)) diff --git a/e2fsck/unix.c b/e2fsck/unix.c index a43f0c9b..7e95ca88 100644 --- a/e2fsck/unix.c +++ b/e2fsck/unix.c @@ -287,6 +287,7 @@ static int is_on_batt(void) static void check_if_skip(e2fsck_t ctx) { ext2_filsys fs = ctx->fs; + struct problem_context pctx; const char *reason = NULL; unsigned int reason_arg = 0; long next_check; @@ -349,6 +350,36 @@ static void check_if_skip(e2fsck_t ctx) fputs(_(", check forced.\n"), stdout); return; } + + /* + * Update the global counts from the block group counts. This + * is needed since modern kernels don't update the global + * counts so as to avoid locking the entire file system. So + * if the filesystem is not unmounted cleanly, the global + * counts may not be accurate. Update them here if we can, + * for the benefit of users who might examine the file system + * using dumpe2fs. (This is for cosmetic reasons only.) + */ + clear_problem_context(&pctx); + pctx.ino = fs->super->s_free_inodes_count; + pctx.ino2 = ctx->free_inodes; + if ((pctx.ino != pctx.ino2) && + !(ctx->options & E2F_OPT_READONLY) && + fix_problem(ctx, PR_0_FREE_INODE_COUNT, &pctx)) { + fs->super->s_free_inodes_count = ctx->free_inodes; + ext2fs_mark_super_dirty(fs); + } + clear_problem_context(&pctx); + pctx.blk = ext2fs_free_blocks_count(fs->super); + pctx.blk2 = ctx->free_blocks; + if ((pctx.blk != pctx.blk2) && + !(ctx->options & E2F_OPT_READONLY) && + fix_problem(ctx, PR_0_FREE_BLOCK_COUNT, &pctx)) { + ext2fs_free_blocks_count_set(fs->super, ctx->free_blocks); + ext2fs_mark_super_dirty(fs); + } + + /* Print the summary message when we're skipping a full check */ printf(_("%s: clean, %u/%u files, %llu/%llu blocks"), ctx->device_name, fs->super->s_inodes_count - fs->super->s_free_inodes_count, fs->super->s_inodes_count, diff --git a/tests/f_baddir/expect.1 b/tests/f_baddir/expect.1 index 39735061..cf46a60c 100644 --- a/tests/f_baddir/expect.1 +++ b/tests/f_baddir/expect.1 @@ -39,6 +39,9 @@ Pass 5: Checking group summary information Block bitmap differences: -22 Fix? yes +Free blocks count wrong (74, counted=75). +Fix? yes + Inode bitmap differences: -13 Fix? yes diff --git a/tests/f_dup/expect.1 b/tests/f_dup/expect.1 index ce369062..e7128f34 100644 --- a/tests/f_dup/expect.1 +++ b/tests/f_dup/expect.1 @@ -27,7 +27,7 @@ Pass 5: Checking group summary information Free blocks count wrong for group #0 (44, counted=60). Fix? yes -Free blocks count wrong (44, counted=60). +Free blocks count wrong (62, counted=60). Fix? yes Padding at end of block bitmap is not set. Fix? yes diff --git a/tests/f_dup2/expect.1 b/tests/f_dup2/expect.1 index 79a5f1a0..0476005d 100644 --- a/tests/f_dup2/expect.1 +++ b/tests/f_dup2/expect.1 @@ -34,7 +34,7 @@ Pass 5: Checking group summary information Free blocks count wrong for group #0 (8, counted=22). Fix? yes -Free blocks count wrong (8, counted=22). +Free blocks count wrong (26, counted=22). Fix? yes Padding at end of block bitmap is not set. Fix? yes diff --git a/tests/f_end-bitmap/expect.1 b/tests/f_end-bitmap/expect.1 index 3348a2b3..87e2fd64 100644 --- a/tests/f_end-bitmap/expect.1 +++ b/tests/f_end-bitmap/expect.1 @@ -8,9 +8,6 @@ Pass 5: Checking group summary information Free blocks count wrong for group #0 (44, counted=63). Fix? yes -Free blocks count wrong (44, counted=63). -Fix? yes - Padding at end of block bitmap is not set. Fix? yes diff --git a/tests/f_lpf/expect.1 b/tests/f_lpf/expect.1 index 6c0a746c..4f2853c5 100644 --- a/tests/f_lpf/expect.1 +++ b/tests/f_lpf/expect.1 @@ -30,7 +30,7 @@ Fix? yes Free blocks count wrong for group #0 (24, counted=33). Fix? yes -Free blocks count wrong (24, counted=33). +Free blocks count wrong (38, counted=33). Fix? yes Inode bitmap differences: +13 diff --git a/tests/f_summary_counts/expect.1 b/tests/f_summary_counts/expect.1 index 5c528bb4..ddb14bd6 100644 --- a/tests/f_summary_counts/expect.1 +++ b/tests/f_summary_counts/expect.1 @@ -7,18 +7,12 @@ 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 diff --git a/tests/f_unused_itable/expect.1 b/tests/f_unused_itable/expect.1 index d77e82a5..08a97001 100644 --- a/tests/f_unused_itable/expect.1 +++ b/tests/f_unused_itable/expect.1 @@ -22,9 +22,6 @@ Fix? yes Free inodes count wrong for group #1 (64, counted=58). Fix? yes -Free inodes count wrong (117, counted=109). -Fix? yes - test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** test_filesys: 19/128 files (0.0% non-contiguous), 165/1000 blocks