]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
E2fsck will now check the individual block group inode and block free counts,
authorTheodore Ts'o <tytso@mit.edu>
Tue, 25 Jan 2005 08:09:24 +0000 (03:09 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 25 Jan 2005 08:09:24 +0000 (03:09 -0500)
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
e2fsck/super.c
e2fsck/unix.c
tests/ChangeLog
tests/f_summary_counts/expect.1 [new file with mode: 0644]
tests/f_summary_counts/expect.2 [new file with mode: 0644]
tests/f_summary_counts/image.gz [new file with mode: 0644]
tests/f_summary_counts/name [new file with mode: 0644]
tests/f_summary_counts/script [new file with mode: 0644]

index 332f0c134df6629e71c02885ffdca98d3e45f41b..4effd27a5b06eba179228f6fc89ef4379c1464cd 100644 (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
index 2e9e6a8cded23749412ad2f7142ebbf234de2f52..9a662f0ad8ef342b4458fb05733b24122c361c1a 100644 (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.
index 171647131fa4647f0bf6e0f091b5879a4b21343d..a8ac53d5403d9f5afe79c05a36370738072cccdc 100644 (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);
index 7499e1bf1f9692f1125389b8736f245516e16629..c705a646e6022587467fc49e4c34ad7969e455f4 100644 (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
diff --git a/tests/f_summary_counts/expect.1 b/tests/f_summary_counts/expect.1
new file mode 100644 (file)
index 0000000..5c528bb
--- /dev/null
@@ -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 (file)
index 0000000..44bff62
--- /dev/null
@@ -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 (file)
index 0000000..d527e9a
Binary files /dev/null and b/tests/f_summary_counts/image.gz differ
diff --git a/tests/f_summary_counts/name b/tests/f_summary_counts/name
new file mode 100644 (file)
index 0000000..9fd1021
--- /dev/null
@@ -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 (file)
index 0000000..fc425ef
--- /dev/null
@@ -0,0 +1,4 @@
+FSCK_OPT=-y
+SECOND_FSCK_OPT=-yf
+
+. $cmd_dir/run_e2fsck