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