Whamcloud - gitweb
LU-5949 e2fsck: simplify inode badness handling 28/41328/5
authorAndreas Dilger <adilger@whamcloud.com>
Thu, 30 Jul 2020 20:36:49 +0000 (14:36 -0600)
committerAndreas Dilger <adilger@whamcloud.com>
Mon, 8 Feb 2021 11:25:32 +0000 (11:25 +0000)
Move the badness increment into fix_problem() so that code does
not need to be spread across the code and explicitly set.  Instead,
take advantage of the fact that pctx->ino is almost always pointing
at the bad inode and increment badness whenever fix_problem() is
called on the inode.  This also handles new problems in the future.

That leaves only a handful of places in the code that need special
handling to either set a higher badness (e.g. inode blocks that are
directly referencing filesystem metadata or have wildly incorrect
timestamps), or should not contribute to inode badness at all.

The main exceptions are when reprocessing duplicate blocks in the
inode (badness already set), and cleaning bad entries in a directory
leaf block in check_dir_block(), which uses pctx->ino to reference
the parent directory inode number.  In such cases, fix_problem_bad()
is called with 0 badness, since the leaf block was been repaired,
and clearing the directory inode in this case is unnecessary.

This patch should be merged into original badness patch on rebase.

Fixes: 92a85a3ced2c ("e2fsck: track errors/badness found for each inode")
Signed-off-by: Andreas Dilger <adilger@whamcloud.com>
Change-Id: I96cd21b5976991f0bb1c63fc99857c80e23ebbe5
Reviewed-on: https://review.whamcloud.com/41328
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Wang Shilong <wshilong@whamcloud.com>
Reviewed-by: Artem Blagodarenko <artem.blagodarenko@hpe.com>
18 files changed:
e2fsck/e2fsck.8.in
e2fsck/e2fsck.h
e2fsck/pass1.c
e2fsck/pass1b.c
e2fsck/pass2.c
e2fsck/pass3.c
e2fsck/pass4.c
e2fsck/problem.c
e2fsck/problem.h
e2fsck/unix.c
tests/f_ibadness/expect.1
tests/f_ibadness/script [new file with mode: 0644]
tests/f_ibadness_bad_extents/expect.1
tests/f_ibadness_bad_extents/image.gz
tests/f_ibadness_bad_extents/script [new file with mode: 0644]
tests/f_messy_inode/expect.1
tests/f_messy_inode/script
tests/filter.sed

index 63ae0bd..7dc0203 100644 (file)
@@ -223,12 +223,13 @@ or repairs.
 .TP
 .BI inode_badness_threshold= threshold_value
 A badness counter is associated with every inode, which determines the degree
-of inode corruption. Each error found in the inode will increase the badness by
-1 or 2, and inodes with a badness at or above
+of inode corruption. Each error found in the inode will increase the badness
+by 1 or 2, and inodes with a badness at or above
 .I threshold_value
 will be prompted for deletion. The default
 .I threshold_value
-is 7.
+is 12, and must either be 0 (disabled), or between 3 and 200, as some valid
+inode states may set a badness of 1 or 2 that should not clear the inode.
 .TP
 .BI fragcheck
 During pass 1, print a detailed report of any discontiguous blocks for
index a7d0884..a3f0b5b 100644 (file)
@@ -238,11 +238,9 @@ enum clone_opt {
 #define EXT4_XTIME_ANCIENT(ctx, sb, xtime, margin)     \
        ((sb)->s_mkfs_time > (margin) && (xtime) < (sb)->s_mkfs_time - (margin))
 
-#define BADNESS_NORMAL         1
-#define BADNESS_HIGH           2
-#define BADNESS_THRESHOLD      8
-#define BADNESS_BAD_MODE       100
-#define BADNESS_LARGE_FILE     2199023255552ULL
+#define BADNESS_THRESHOLD      12
+#define BADNESS_BAD_MODE       0x8000
+#define BADNESS_MAX            0x7fff
 
 /*
  * Define the extended attribute refcount structure
@@ -353,7 +351,7 @@ struct e2fsck_struct {
        /* E2fsck internal flags */
        int                     flags;
 
-       int                     inode_badness_threshold;
+       unsigned int            inode_badness_threshold;
 
        /*
         * How we display the progress update (for unix)
@@ -671,11 +669,14 @@ extern int e2fsck_pass1_check_symlink(e2fsck_t ctx, ext2_ino_t ino,
 extern void e2fsck_clear_inode(e2fsck_t ctx, ext2_ino_t ino,
                               struct ext2_inode *inode, int restart_flag,
                               const char *source);
-#define e2fsck_mark_inode_bad(ctx, ino, count) \
-               e2fsck_mark_inode_bad_loc(ctx, ino, count, __func__, __LINE__)
-extern void e2fsck_mark_inode_bad_loc(e2fsck_t ctx, ino_t ino, int count,
-                                     const char *func, const int line);
-extern int is_inode_bad(e2fsck_t ctx, ino_t ino);
+#define e2fsck_mark_inode_bad(ctx, pctx, code) \
+       e2fsck_mark_inode_bad_loc(ctx, pctx, code, 1, __func__, __LINE__)
+#define e2fsck_mark_inode_badder(ctx, pctx, code) \
+       e2fsck_mark_inode_bad_loc(ctx, pctx, code, 2, __func__, __LINE__)
+extern void e2fsck_mark_inode_bad_loc(e2fsck_t ctx,
+                               struct problem_context *pctx, __u32 code,
+                               int count, const char *func, const int line);
+extern int e2fsck_fix_bad_inode(e2fsck_t ctx, struct problem_context *pctx);
 extern void e2fsck_intercept_block_allocations(e2fsck_t ctx);
 
 /* pass2.c */
index 696c411..eafaa01 100644 (file)
@@ -313,7 +313,6 @@ static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
        if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
                return;
 
-       e2fsck_mark_inode_bad(ctx, pctx->ino, BADNESS_NORMAL);
        if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
                return;
 
@@ -332,7 +331,6 @@ static void check_size(e2fsck_t ctx, struct problem_context *pctx)
        if (EXT2_I_SIZE(inode) == 0)
                return;
 
-       e2fsck_mark_inode_bad(ctx, pctx->ino, BADNESS_NORMAL);
        if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
                return;
 
@@ -624,7 +622,6 @@ static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx,
        if (inode->i_extra_isize &&
            (inode->i_extra_isize < min || inode->i_extra_isize > max ||
             inode->i_extra_isize & 3)) {
-               e2fsck_mark_inode_bad(ctx, pctx->ino, BADNESS_NORMAL);
                if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
                        return;
                if (inode->i_extra_isize < min || inode->i_extra_isize > max)
@@ -656,6 +653,10 @@ static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx,
        if (*eamagic == EXT2_EXT_ATTR_MAGIC)
                check_ea_in_inode(ctx, pctx, ea_ibody_quota);
 
+       if (EXT4_XTIME_FUTURE(ctx, sb, inode->i_crtime, ctx->time_fudge))
+               e2fsck_mark_inode_bad(ctx, pctx, PR_1_CRTIME_BAD);
+       else if (EXT4_XTIME_ANCIENT(ctx, sb, inode->i_crtime, ctx->time_fudge))
+               e2fsck_mark_inode_bad(ctx, pctx, PR_1_CRTIME_BAD);
        /*
         * If the inode's extended atime (ctime, crtime, mtime) is stored in
         * the old, invalid format, repair it.
@@ -668,7 +669,7 @@ static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx,
             CHECK_INODE_EXTRA_NEGATIVE_EPOCH(inode, crtime) ||
             CHECK_INODE_EXTRA_NEGATIVE_EPOCH(inode, mtime))) {
 
-               if (!fix_problem(ctx, PR_1_EA_TIME_OUT_OF_RANGE, pctx))
+               if (!fix_problem_bad(ctx, PR_1_EA_TIME_OUT_OF_RANGE, pctx, 2))
                        return;
 
                if (CHECK_INODE_EXTRA_NEGATIVE_EPOCH(inode, atime))
@@ -680,7 +681,6 @@ static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx,
                if (CHECK_INODE_EXTRA_NEGATIVE_EPOCH(inode, mtime))
                        inode->i_mtime_extra &= ~EXT4_EPOCH_MASK;
                dirty = 1;
-               e2fsck_mark_inode_bad(ctx, pctx->ino, BADNESS_HIGH);
        }
 
 out:
@@ -865,7 +865,6 @@ static void check_is_really_dir(e2fsck_t ctx, struct problem_context *pctx,
                return;
 
 isdir:
-       e2fsck_mark_inode_bad(ctx, pctx->ino, BADNESS_NORMAL);
        if (fix_problem(ctx, PR_1_TREAT_AS_DIRECTORY, pctx)) {
                inode->i_mode = (inode->i_mode & 07777) | LINUX_S_IFDIR;
                e2fsck_write_inode_full(ctx, pctx->ino, inode,
@@ -1154,6 +1153,28 @@ err:
        return retval;
 }
 
+int e2fsck_fix_bad_inode(e2fsck_t ctx, struct problem_context *pctx)
+{
+       __u16 badness;
+       int rc = 0;
+
+       if (!ctx->inode_badness)
+               return 0;
+
+       if (ext2fs_icount_fetch(ctx->inode_badness, pctx->ino, &badness))
+               return 0;
+
+       if ((badness & ~BADNESS_BAD_MODE) > ctx->inode_badness_threshold) {
+               __u64 pctx_num_sav = pctx->num;
+
+               pctx->num = badness;
+               rc = fix_problem_bad(ctx, PR_1B_INODE_TOOBAD, pctx, 0);
+               pctx->num = pctx_num_sav;
+       }
+
+       return rc;
+}
+
 static void finish_processing_inode(e2fsck_t ctx, ext2_ino_t ino,
                                    struct problem_context *pctx,
                                    int failed_csum)
@@ -1173,7 +1194,7 @@ static void finish_processing_inode(e2fsck_t ctx, ext2_ino_t ino,
 #define FINISH_INODE_LOOP(ctx, ino, pctx, failed_csum) \
        do { \
                finish_processing_inode((ctx), (ino), (pctx), (failed_csum)); \
-               if ((ctx)->flags & E2F_FLAG_ABORT) { \
+               if (e2fsck_should_abort(ctx)) { \
                        e2fsck_pass1_check_unlock(ctx); \
                        return; \
                } \
@@ -1856,9 +1877,8 @@ void e2fsck_pass1_run(e2fsck_t ctx)
        if (ctx->global_ctx) {
                if (ctx->options & E2F_OPT_DEBUG &&
                    ctx->options & E2F_OPT_MULTITHREAD)
-                       fprintf(stderr, "thread %d jumping to group %u\n",
-                                       ctx->thread_info.et_thread_index,
-                                       ctx->thread_info.et_group_start);
+                       log_out(ctx, "jumping to group %u\n",
+                               ctx->thread_info.et_group_start);
                pctx.errcode = ext2fs_inode_scan_goto_blockgroup(scan,
                                        ctx->thread_info.et_group_start);
                if (pctx.errcode) {
@@ -2201,19 +2221,15 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                        ehp = inode->i_block;
 #endif
                        if ((ext2fs_extent_header_verify(ehp,
-                                        sizeof(inode->i_block)) == 0)) {
-                               e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL);
-                               if (fix_problem(ctx, PR_1_UNSET_EXTENT_FL,
-                                               &pctx)) {
-                                       inode->i_flags |= EXT4_EXTENTS_FL;
+                                        sizeof(inode->i_block)) == 0) &&
+                           (fix_problem(ctx, PR_1_UNSET_EXTENT_FL, &pctx))) {
+                               inode->i_flags |= EXT4_EXTENTS_FL;
 #ifdef WORDS_BIGENDIAN
-                                       memcpy(inode->i_block, tmp_block,
-                                              sizeof(inode->i_block));
+                               memcpy(inode->i_block, tmp_block,
+                                      sizeof(inode->i_block));
 #endif
-                                       e2fsck_write_inode(ctx, ino, inode,
-                                                          "pass1");
-                                       failed_csum = 0;
-                               }
+                               e2fsck_write_inode(ctx, ino, inode, "pass1");
+                               failed_csum = 0;
                        }
                }
 
@@ -2292,7 +2308,6 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                         * as a special case.
                         */
                        if (inode->i_dtime && inode->i_links_count) {
-                               e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL);
                                if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
                                        inode->i_dtime = 0;
                                        e2fsck_write_inode(ctx, ino, inode,
@@ -2400,7 +2415,6 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                 *
                 */
                if (inode->i_dtime) {
-                       e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL);
                        if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
                                inode->i_dtime = 0;
                                e2fsck_write_inode(ctx, ino, inode, "pass1");
@@ -2421,16 +2435,18 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                /* Fixed in pass2, e2fsck_process_bad_inode(). */
                if (inode->i_faddr || frag || fsize ||
                    (!ext2fs_has_feature_largedir(fs->super) &&
-                   (LINUX_S_ISDIR(inode->i_mode) && inode->i_size_high)))
-                       e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL);
+                    LINUX_S_ISDIR(inode->i_mode) && inode->i_size_high))
+                       e2fsck_mark_inode_bad(ctx, &pctx,
+                                             PR_2_DIR_SIZE_HIGH_ZERO);
                if ((fs->super->s_creator_os != EXT2_OS_HURD) &&
                    !ext2fs_has_feature_64bit(fs->super) &&
                    inode->osd2.linux2.l_i_file_acl_high != 0)
-                       e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL);
+                       e2fsck_mark_inode_bad(ctx, &pctx,
+                                             PR_2_I_FILE_ACL_HI_ZERO);
                if ((fs->super->s_creator_os != EXT2_OS_HURD) &&
                    !ext2fs_has_feature_huge_file(fs->super) &&
                    (inode->osd2.linux2.l_i_blocks_hi != 0))
-                       e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL);
+                       e2fsck_mark_inode_bad(ctx, &pctx, PR_2_BLOCKS_HI_ZERO);
                if (inode->i_flags & EXT2_IMAGIC_FL) {
                        if (imagic_fs) {
                                if (!ctx->inode_imagic_map)
@@ -2438,7 +2454,6 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                                ext2fs_mark_inode_bitmap2(ctx->inode_imagic_map,
                                                         ino);
                        } else {
-                               e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL);
                                if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
                                        inode->i_flags &= ~EXT2_IMAGIC_FL;
                                        e2fsck_write_inode(ctx, ino,
@@ -2515,23 +2530,35 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                        check_size(ctx, &pctx);
                        ctx->fs_sockets_count++;
                } else {
-                       e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL);
+                       e2fsck_mark_inode_bad(ctx, &pctx, PR_2_BAD_MODE);
                }
 
+               /* Future atime/mtime may be valid in rare cases, but are more
+                * likely to indicate corruption.  Don't try to fix timestamps,
+                * but take into consideration whether inode is corrupted.  If
+                * no other problems with the inode, probably it is OK. */
                if (EXT4_XTIME_FUTURE(ctx, sb, inode->i_atime, ctx->time_fudge))
-                       e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL);
-               else if (EXT4_XTIME_FUTURE(ctx, sb, inode->i_mtime,
-                                          ctx->time_fudge))
-                       e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL);
+                       e2fsck_mark_inode_bad(ctx, &pctx, PR_1_INODE_BAD_TIME);
+               if (EXT4_XTIME_FUTURE(ctx, sb, inode->i_mtime, ctx->time_fudge))
+                       e2fsck_mark_inode_bad(ctx, &pctx, PR_1_INODE_BAD_TIME);
 
+               /* Since ctime cannot be set directly from userspace, consider
+                * very old/future values worse than a bad atime/mtime. Same for
+                * crtime, but it is checked in check_inode_extra_space(). */
                if (EXT4_XTIME_FUTURE(ctx, sb, inode->i_ctime, ctx->time_fudge))
-                       e2fsck_mark_inode_bad(ctx, ino, BADNESS_HIGH);
+                       e2fsck_mark_inode_badder(ctx, &pctx,
+                                                PR_1_INODE_BAD_TIME);
                else if (!precreated_object(inode) &&
                         EXT4_XTIME_ANCIENT(ctx, sb, inode->i_ctime,
                                            ctx->time_fudge))
-                       e2fsck_mark_inode_bad(ctx, ino, BADNESS_HIGH);
+                       e2fsck_mark_inode_badder(ctx, &pctx,
+                                                PR_1_INODE_BAD_TIME);
 
-               /* i_crtime is checked in check_inode_extra_space() */
+               /* no restart if clearing bad inode before block processing */
+               if (e2fsck_fix_bad_inode(ctx, &pctx)) {
+                       e2fsck_clear_inode(ctx, ino, inode, 0, "pass1");
+                       goto next_unlock;
+               }
 
                if (!(inode->i_flags & EXT4_EXTENTS_FL) &&
                    !(inode->i_flags & EXT4_INLINE_DATA_FL)) {
@@ -2593,6 +2620,7 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                                goto endit;
                        }
                }
+       next_unlock:
                e2fsck_pass1_check_unlock(ctx);
        }
        process_inodes(ctx, block_buf, inodes_to_process,
@@ -3749,29 +3777,42 @@ static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b)
 /*
  * Mark an inode as being bad and increment its badness counter.
  */
-void e2fsck_mark_inode_bad_loc(e2fsck_t ctx, ino_t ino, int count,
-                              const char *func, const int line)
+void e2fsck_mark_inode_bad_loc(e2fsck_t ctx, struct problem_context *pctx,
+                              __u32 code, int badness, const char *func,
+                              const int line)
 {
-       struct          problem_context pctx;
-       __u16           result;
+       __u16 badness_before, badness_after;
+       __u64 pctx_num_sav = pctx->num;
+
+       if (!ctx->inode_badness_threshold)      /* badness is disabled */
+               return;
 
        if (!ctx->inode_badness) {
-               clear_problem_context(&pctx);
+               errcode_t retval;
 
-               pctx.errcode = ext2fs_create_icount2(ctx->fs, 0, 0, NULL,
-                                                    &ctx->inode_badness);
-               if (pctx.errcode) {
-                       fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
+               retval = ext2fs_create_icount2(ctx->fs, 0, 0, NULL,
+                                              &ctx->inode_badness);
+               if (retval) {
+                       pctx->errcode = retval;
+                       fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, pctx);
                        ctx->flags |= E2F_FLAG_ABORT;
                        return;
                }
        }
-       ext2fs_icount_fetch(ctx->inode_badness, ino, &result);
-       ext2fs_icount_store(ctx->inode_badness, ino, count + result);
+       ext2fs_icount_fetch(ctx->inode_badness, pctx->ino, &badness_before);
+       if (badness + badness_before > BADNESS_MAX)
+               badness_after = BADNESS_MAX;
+       else if (badness < 0 && badness_before < -badness)
+               badness_after = 0;
+       else
+               badness_after = badness_before + badness;
+       ext2fs_icount_store(ctx->inode_badness, pctx->ino, badness_after);
 
        if (ctx->options & E2F_OPT_DEBUG)
-               fprintf(stderr, "%s:%d: increase inode %lu badness %u to %u\n",
-                       func, line, (unsigned long)ino, result, count + result);
+               log_out(ctx,
+                       "%s:%d: increase inode %lu badness %u to %u for %x\n",
+                       func, line, (unsigned long)pctx->ino, badness_before,
+                       badness_after, code);
 }
 
 static void add_encrypted_dir(e2fsck_t ctx, ino_t ino)
@@ -3979,7 +4020,7 @@ static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
            (blk < fs->super->s_first_data_block) ||
            (blk >= ext2fs_blocks_count(fs->super))) {
                /* Fixed in pass2, e2fsck_process_bad_inode(). */
-               e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL);
+               e2fsck_mark_inode_bad(ctx, pctx, PR_2_FILE_ACL_ZERO);
                return 0;
        }
 
@@ -4242,11 +4283,9 @@ static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
 
        if ((!LINUX_S_ISDIR(inode->i_mode) &&
             fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
-           (!ext2fs_has_feature_dir_index(fs->super))) {
-               e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL);
-               if (fix_problem(ctx, PR_1_HTREE_SET, pctx))
-                       return 1;
-       }
+           (!ext2fs_has_feature_dir_index(fs->super) &&
+            fix_problem(ctx, PR_1_HTREE_SET, pctx)))
+               return 1;
 
        pctx->errcode = ext2fs_bmap2(fs, ino, inode, 0, 0, 0, 0, &blk);
 
@@ -4254,7 +4293,6 @@ static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
            (blk == 0) ||
            (blk < fs->super->s_first_data_block) ||
            (blk >= ext2fs_blocks_count(fs->super))) {
-               e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL);
                if (fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
                        return 1;
                else
@@ -4263,7 +4301,6 @@ static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
 
        retval = io_channel_read_blk64(fs->io, blk, 1, block_buf);
        if (retval) {
-               e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL);
                if (fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
                        return 1;
        }
@@ -4495,12 +4532,10 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
                }
 
                if (try_repairs && problem) {
-                       /* To ensure that extent is in inode */
-                       if (info.curr_level == 0)
-                               e2fsck_mark_inode_bad(ctx, pctx->ino,
-                                                     BADNESS_HIGH);
 report_problem:
-                       if (fix_problem(ctx, problem, pctx)) {
+                       /* Record badness only if extent is within inode */
+                       if (fix_problem_bad(ctx, problem, pctx,
+                                           info.curr_level == 0)) {
                                if (ctx->invalid_bitmaps) {
                                        /*
                                         * If fsck knows the bitmaps are bad,
@@ -4569,9 +4604,9 @@ report_problem:
                                                      extent.e_pblk)) {
                                next_try_repairs = 0;
                                pctx->blk = blk;
-                               fix_problem(ctx,
+                               fix_problem_bad(ctx,
                                            PR_1_CRITICAL_METADATA_COLLISION,
-                                           pctx);
+                                           pctx, 2);
                                if ((ctx->options & E2F_OPT_NO) == 0)
                                        ctx->flags |= E2F_FLAG_RESTART_LATER;
                        }
@@ -5047,7 +5082,6 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
                 * The mode might be in-correct. Increasing the badness by
                 * small amount won't hurt much.
                 */
-               e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL);
                if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
                        e2fsck_clear_inode(ctx, ino, inode, 0, "check_blocks");
                        ctx->fs_directory_count--;
@@ -5127,8 +5161,6 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
                if (bad_size != 7)
                        pctx->num = (pb.last_block + 1) * fs->blocksize;
                pctx->group = bad_size;
-               e2fsck_mark_inode_bad(ctx, ino, pb.is_dir ? BADNESS_HIGH :
-                                                           BADNESS_NORMAL);
                if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
                        ext2fs_inode_size_set(fs, inode, pctx->num);
                        if (EXT2_I_SIZE(inode) == 0 &&
@@ -5150,7 +5182,6 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
              (inode->i_flags & EXT4_HUGE_FILE_FL) &&
              (inode->osd2.linux2.l_i_blocks_hi != 0)))) {
                pctx->num = pb.num_blocks;
-               e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL);
                if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
                        inode->i_blocks = pb.num_blocks;
                        inode->osd2.linux2.l_i_blocks_hi = pb.num_blocks >> 32;
@@ -5182,7 +5213,11 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
                e2fsck_rehash_dir_later(ctx, ino);
 
 out:
-       if (dirty_inode)
+       /* need restart if clearing bad inode after block processing */
+       if (e2fsck_fix_bad_inode(ctx, pctx))
+               e2fsck_clear_inode(ctx, ino, inode, E2F_FLAG_RESTART,
+                                  "check_blocks_bad");
+       else if (dirty_inode)
                e2fsck_write_inode(ctx, ino, inode, "check_blocks");
 }
 
@@ -5320,10 +5355,8 @@ static int process_block(ext2_filsys fs,
                problem = PR_1_TOOBIG_SYMLINK;
 
        if (blk < fs->super->s_first_data_block ||
-           blk >= ext2fs_blocks_count(fs->super)) {
+           blk >= ext2fs_blocks_count(fs->super))
                problem = PR_1_ILLEGAL_BLOCK_NUM;
-               e2fsck_mark_inode_bad(ctx, pctx->ino, BADNESS_NORMAL);
-       }
 
        /*
         * If this IND/DIND/TIND block is squatting atop some critical metadata
@@ -5336,7 +5369,7 @@ static int process_block(ext2_filsys fs,
            blk < ctx->fs->super->s_blocks_count &&
            ext2fs_test_block_bitmap2(ctx->block_metadata_map, blk)) {
                pctx->blk = blk;
-               fix_problem(ctx, PR_1_CRITICAL_METADATA_COLLISION, pctx);
+               fix_problem_bad(ctx, PR_1_CRITICAL_METADATA_COLLISION, pctx, 2);
                if ((ctx->options & E2F_OPT_NO) == 0)
                        ctx->flags |= E2F_FLAG_RESTART_LATER;
        }
index a103342..26a1f04 100644 (file)
@@ -340,6 +340,11 @@ static void pass1b(e2fsck_t ctx, char *block_buf)
                pb.last_blk = 0;
                pb.pctx->blk = pb.pctx->blk2 = 0;
 
+               if (e2fsck_fix_bad_inode(ctx, &pctx)) {
+                       delete_file(ctx, ino, &pb, block_buf);
+                       continue;
+               }
+
                if (ext2fs_inode_has_valid_blocks2(fs, EXT2_INODE(&inode)) ||
                    (ino == EXT2_BAD_INO))
                        pctx.errcode = ext2fs_block_iterate3(fs, ino,
@@ -575,7 +580,7 @@ static void pass1d(e2fsck_t ctx, char *block_buf)
                pctx.dir = p->dir;
                pctx.blkcount = p->num_dupblocks;
                pctx.num = meta_data ? shared_len+1 : shared_len;
-               fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
+               fix_problem_bad(ctx, PR_1D_DUP_FILE, &pctx, pctx.blkcount / 2);
                pctx.blkcount = 0;
                pctx.num = 0;
 
@@ -593,14 +598,14 @@ static void pass1d(e2fsck_t ctx, char *block_buf)
                        pctx.inode = EXT2_INODE(&t->inode);
                        pctx.ino = shared[i];
                        pctx.dir = t->dir;
-                       fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
+                       fix_problem_bad(ctx, PR_1D_DUP_FILE_LIST, &pctx, 0);
                }
                /*
                 * Even if the file shares blocks with itself, we still need to
                 * clone the blocks.
                 */
                if (file_ok && (meta_data ? shared_len+1 : shared_len) != 0) {
-                       fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
+                       fix_problem_bad(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx, 0);
                        continue;
                }
                if (ctx->shared != E2F_SHARED_DELETE &&
@@ -720,8 +725,6 @@ static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
                                                     delete_file_block, &pb);
        if (pctx.errcode)
                fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
-       if (ctx->inode_badness)
-               e2fsck_mark_inode_bad(ctx, ino, 0);
        if (ctx->inode_reg_map)
                ext2fs_unmark_inode_bitmap2(ctx->inode_reg_map, ino);
        ext2fs_unmark_inode_bitmap2(ctx->inode_dir_map, ino);
index c589a4e..b9df72b 100644 (file)
@@ -38,6 +38,7 @@
  *
  * Pass 2 frees the following data structures
  *     - The inode_reg_map bitmap
+ *     - The inode_badness bitmap
  */
 
 #define _GNU_SOURCE 1 /* get strnlen() */
@@ -280,6 +281,10 @@ void e2fsck_pass2(e2fsck_t ctx)
                ext2fs_free_inode_bitmap(ctx->inode_reg_map);
                ctx->inode_reg_map = 0;
        }
+       if (ctx->inode_badness) {
+               ext2fs_free_icount(ctx->inode_badness);
+               ctx->inode_badness = 0;
+       }
        if (ctx->encrypted_dirs) {
                ext2fs_u32_list_free(ctx->encrypted_dirs);
                ctx->encrypted_dirs = 0;
@@ -604,7 +609,7 @@ static _INLINE_ int check_filetype(e2fsck_t ctx,
 {
        int     filetype = ext2fs_dirent_file_type(dirent);
        int     should_be = EXT2_FT_UNKNOWN;
-       __u16   result;
+       __u16   badness = 0;
        struct ext2_inode       inode;
        __u8    dirdata = 0;
 
@@ -623,14 +628,14 @@ static _INLINE_ int check_filetype(e2fsck_t ctx,
 
        if (ctx->inode_badness)
                ext2fs_icount_fetch(ctx->inode_badness, dirent->inode,
-                                       &result);
+                                   &badness);
 
        if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, dirent->inode)) {
                should_be = EXT2_FT_DIR;
        } else if (ext2fs_test_inode_bitmap2(ctx->inode_reg_map,
                                            dirent->inode)) {
                should_be = EXT2_FT_REG_FILE;
-       } else if (ctx->inode_badness && result >= BADNESS_BAD_MODE) {
+       } else if (badness & BADNESS_BAD_MODE) {
                should_be = 0;
        } else {
                e2fsck_read_inode(ctx, dirent->inode, &inode,
@@ -1495,15 +1500,19 @@ skip_checksum:
                        problem = PR_2_UNUSED_INODE;
 
                if (problem) {
-                       if (fix_problem(ctx, problem, &cd->pctx)) {
+                       int next = 0;
+
+                       if (fix_problem_bad(ctx, problem, &cd->pctx, 0)) {
                                dirent->inode = 0;
                                dir_modified++;
-                               goto next;
+                               next = 1;
                        } else {
                                ext2fs_unmark_valid(fs);
                                if (problem == PR_2_BAD_INO)
-                                       goto next;
+                                       next = 1;
                        }
+                       if (next)
+                               goto next;
                }
 
                if (!encrypted && check_name(ctx, dirent, &cd->pctx))
@@ -1850,11 +1859,14 @@ int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
        unsigned char           *frag, *fsize;
        struct problem_context  pctx;
        problem_t               problem = 0;
-       __u16                   badness;
+       __u16                   badness = 0;
+       unsigned int            flags = ctx->fs->flags;
 
-       if (ctx->inode_badness)
-               ext2fs_icount_fetch(ctx->inode_badness, ino, &badness);
+       flags = ctx->fs->flags;
+       ctx->fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
        e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
+       ctx->fs->flags = (flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) |
+                         (ctx->fs->flags & ~EXT2_FLAG_IGNORE_CSUM_ERRORS);
 
        clear_problem_context(&pctx);
        pctx.ino = ino;
@@ -1868,7 +1880,6 @@ int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
                        inode_modified++;
                } else
                        not_fixed++;
-               badness += BADNESS_NORMAL;
        }
 
        if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
@@ -1903,10 +1914,11 @@ int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
                        not_fixed++;
                problem = 0;
                /*
-                * A high value is associated with bad mode in order to detect
+                * A large value is associated with bad mode in order to detect
                 * that mode was corrupt in check_filetype()
                 */
-               badness += BADNESS_BAD_MODE;
+               e2fsck_mark_inode_bad_loc(ctx, &pctx, problem, BADNESS_BAD_MODE,
+                                         __func__, __LINE__);
        }
 
        if (inode.i_faddr) {
@@ -1915,7 +1927,6 @@ int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
                        inode_modified++;
                } else
                        not_fixed++;
-               badness += BADNESS_NORMAL;
        }
 
        switch (fs->super->s_creator_os) {
@@ -1933,7 +1944,6 @@ int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
                        inode_modified++;
                } else
                        not_fixed++;
-               badness += BADNESS_NORMAL;
                pctx.num = 0;
        }
        if (fsize && *fsize) {
@@ -1943,26 +1953,9 @@ int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
                        inode_modified++;
                } else
                        not_fixed++;
-               badness += BADNESS_NORMAL;
                pctx.num = 0;
        }
 
-       /* In pass1 these conditions were used to mark inode bad so that
-        * it calls e2fsck_process_bad_inode and make an extensive check
-        * plus prompt for action to be taken. To compensate for badness
-        * incremented in pass1 by this condition, decrease it.
-        */
-       if ((inode.i_faddr || frag || fsize ||
-            (LINUX_S_ISDIR(inode.i_mode) && inode.i_size_high)) ||
-           (inode.i_file_acl &&
-            (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
-             (inode.i_file_acl < fs->super->s_first_data_block) ||
-             (inode.i_file_acl >= fs->super->s_blocks_count)))) {
-               /* badness can be 0 if called from pass4. */
-               if (badness)
-                       badness -= BADNESS_NORMAL;
-       }
-
        if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
            !ext2fs_has_feature_huge_file(fs->super) &&
            (inode.osd2.linux2.l_i_blocks_hi != 0)) {
@@ -1971,8 +1964,6 @@ int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
                        inode.osd2.linux2.l_i_blocks_hi = 0;
                        inode_modified++;
                }
-               /* Badness was increased in pass1 for this condition */
-               /* badness += BADNESS_NORMAL; */
        }
 
        if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
@@ -1984,7 +1975,6 @@ int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
                        inode_modified++;
                } else
                        not_fixed++;
-               badness += BADNESS_NORMAL;
        }
 
        if (ext2fs_file_acl_block(fs, &inode) &&
@@ -1995,7 +1985,6 @@ int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
                        inode_modified++;
                } else
                        not_fixed++;
-               badness += BADNESS_NORMAL;
        }
        if (inode.i_size_high && !ext2fs_has_feature_largedir(fs->super) &&
            inode.i_blocks < 1ULL << (29 - EXT2_BLOCK_SIZE_BITS(fs->super)) &&
@@ -2005,29 +1994,20 @@ int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
                        inode_modified++;
                } else
                        not_fixed++;
-               badness += BADNESS_NORMAL;
        }
 
-       /*
-        * The high value due to BADNESS_BAD_MODE should not delete the inode.
-        */
-       if (ctx->inode_badness && (badness - (badness >= BADNESS_BAD_MODE ?
-                                             BADNESS_BAD_MODE : 0)) >=
-           ctx->inode_badness_threshold) {
-               pctx.num = badness;
-               if (fix_problem(ctx, PR_2_INODE_TOOBAD, &pctx)) {
-                       deallocate_inode(ctx, ino, 0);
-                       if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
-                               return 0;
-                       return 1;
-               }
+       /* The high value from BADNESS_BAD_MODE should not delete the inode */
+       if (e2fsck_fix_bad_inode(ctx, &pctx)) {
+               deallocate_inode(ctx, ino, 0);
+               if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+                       return 0;
+               inode_modified = 0;
+       } else {
                not_fixed++;
        }
 
        if (inode_modified)
                e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
-       if (ctx->inode_badness)
-               ext2fs_icount_store(ctx->inode_badness, ino, 0);
        return 0;
 }
 
@@ -2047,7 +2027,7 @@ static int allocate_dir_block(e2fsck_t ctx,
        char                    *block;
        struct ext2_inode       inode;
 
-       if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
+       if (fix_problem_bad(ctx, PR_2_DIRECTORY_HOLE, pctx, 0) == 0)
                return 1;
 
        /*
index 2cd085e..b0142dc 100644 (file)
@@ -464,7 +464,7 @@ unlink:
                pctx.errcode = retval;
                fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
        }
-       if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
+       if (!fix_problem(ctx, PR_3_NO_LF_DIR, &pctx))
                return 0;
 
        /*
@@ -725,7 +725,7 @@ static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
        }
        dirent->inode = fp->parent;
 
-       dirdata  = dirent->name_len & (~EXT2_FT_MASK << 8);
+       dirdata  = dirent->name_len & ((__u16)~EXT2_FT_MASK << 8);
 
        if (ext2fs_has_feature_filetype(fp->ctx->fs->super))
                ext2fs_dirent_set_file_type(dirent, EXT2_FT_DIR);
index e7dde1d..8c2d2f1 100644 (file)
@@ -275,7 +275,6 @@ void e2fsck_pass4(e2fsck_t ctx)
        }
        ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
        ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
-       ext2fs_free_icount(ctx->inode_badness); ctx->inode_badness = 0;
        ext2fs_free_inode_bitmap(ctx->inode_bb_map);
        ctx->inode_bb_map = 0;
        ea_refcount_free(ctx->ea_inode_refs);
index ab94a1b..6fb1d4e 100644 (file)
@@ -1359,6 +1359,11 @@ static struct e2fsck_problem problem_table[] = {
          " %b--%c",
          PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR, 0, 0, 0 },
 
+       /* Inode is badly corrupt (badness value = ) */
+       { PR_1B_INODE_TOOBAD,
+         N_("@i %i is badly corrupt (badness value = %N).  "),
+         PROMPT_CLEAR, PR_PREEN_OK },
+
        /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
        { PR_1C_PASS_HEADER,
          N_("Pass 1C: Scanning directories for @is with @m @bs\n"),
@@ -1846,7 +1851,7 @@ static struct e2fsck_problem problem_table[] = {
          N_("Encrypted @E is too short.\n"),
          PROMPT_CLEAR, 0, 0, 0, 0 },
 
-       /* Inode too bad */
+       /* Inode is badly corrupt (badness value = ) */
        { PR_2_INODE_TOOBAD,
          N_("@i %i is badly corrupt (badness value = %N).  "),
          PROMPT_CLEAR, PR_PREEN_OK },
@@ -2435,7 +2440,8 @@ static void print_problem(FILE *f, problem_t code, int answer, int fixed,
        fputs("/>\n", f);
 }
 
-int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
+int fix_problem_loc(e2fsck_t ctx, problem_t code, struct problem_context *pctx,
+                   int badness, const char *func, const int line)
 {
        ext2_filsys fs = ctx->fs;
        struct e2fsck_problem *ptr;
@@ -2446,6 +2452,10 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
        int             suppress = 0;
        int             fixed = 0;
 
+       /* ino is always set in pass1, where we will hit most badness */
+       if (pctx && pctx->ino != 0 && badness && code < PR_3_PASS_HEADER)
+               e2fsck_mark_inode_bad_loc(ctx, pctx, code, badness, func, line);
+
        ptr = find_problem(code);
        if (!ptr) {
                printf(_("Unhandled error code (0x%x)!\n"), code);
@@ -2493,7 +2503,8 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
        if (ptr->flags & PR_LATCH_MASK) {
                ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
                if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
-                       ans = fix_problem(ctx, ldesc->question, pctx);
+                       ans = fix_problem_loc(ctx, ldesc->question, pctx,
+                                             0, func, line);
                        if (ans == 1)
                                ldesc->flags |= PRL_YES;
                        if (ans == 0)
@@ -2596,7 +2607,8 @@ int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
                fatal_error(ctx, 0);
 
        if (ptr->flags & PR_AFTER_CODE)
-               answer = fix_problem(ctx, ptr->second_code, pctx);
+               answer = fix_problem_loc(ctx, ptr->second_code, pctx,
+                                        0, func, line);
 
        if (answer && (ptr->prompt != PROMPT_NONE) &&
            !(ptr->flags & PR_NOT_A_FIX)) {
@@ -2647,6 +2659,13 @@ void preenhalt(e2fsck_t ctx)
        return;
 }
 
+void e2fsck_mark_inode_bad_loc(e2fsck_t ctx,
+                              struct problem_context *pctx, __u32 code,
+                              int count, const char *func, const int line)
+{
+       return;
+}
+
 errcode_t
 profile_get_string(profile_t profile, const char *name, const char *subname,
                   const char *subsubname, const char *def_val,
index d060d2c..e0a90a7 100644 (file)
@@ -694,6 +694,9 @@ struct problem_context {
 /* Inode has illegal EA value inode */
 #define PR_1_ATTR_VALUE_EA_INODE               0x010083
 
+/* Inode has bad timestamp */
+#define PR_1_INODE_BAD_TIME                    0x010084
+
 /* Parent inode has invalid EA entry. EA inode does not have
  * EXT4_EA_INODE_FL flag. Delete EA entry? */
 #define PR_1_ATTR_NO_EA_INODE_FL               0x010085
@@ -769,6 +772,9 @@ struct problem_context {
 /* Duplicate/bad block range in inode */
 #define PR_1B_DUP_RANGE                0x011008
 
+/* Inode is badly corrupt (badness value = ) */
+#define PR_1B_INODE_TOOBAD     0x011009
+
 /* Pass 1C: Scan directories for inodes with dup blocks. */
 #define PR_1C_PASS_HEADER      0x012000
 
@@ -1060,7 +1066,7 @@ struct problem_context {
 /* Encrypted directory entry is too short */
 #define PR_2_BAD_ENCRYPTED_NAME                0x020050
 
-/* Inode completely corrupt */
+/* Inode is badly corrupt (badness value = ) */
 #define PR_2_INODE_TOOBAD              0x020051
 
 /* Entry dirdata length set incorrectly */
@@ -1322,7 +1328,12 @@ struct problem_context {
 /*
  * Function declarations
  */
-int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
+#define fix_problem(ctx, code, pctx)   \
+       fix_problem_bad(ctx, code, pctx, 1)
+#define fix_problem_bad(ctx, code, pctx, badness)      \
+       fix_problem_loc(ctx, code, pctx, badness, __func__, __LINE__)
+int fix_problem_loc(e2fsck_t ctx, problem_t code, struct problem_context *pctx,
+                   int badness, const char *func, const int line);
 int end_problem_latch(e2fsck_t ctx, int mask);
 int set_latch_flags(int mask, int setflags, int clearflags);
 int get_latch_flags(int mask, int *value);
index ebb1b84..a6e6305 100644 (file)
@@ -791,16 +791,20 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts)
                        }
                /* -E inode_badness_threshold=<value> */
                } else if (strcmp(token, "inode_badness_threshold") == 0) {
+                       unsigned int val;
+
                        if (!arg) {
                                extended_usage++;
                                continue;
                        }
-                       ctx->inode_badness_threshold = strtoul(arg, &p, 0);
-                       if (*p != '\0' || ctx->inode_badness_threshold > 200) {
-                               fprintf(stderr, _("Invalid badness value.\n"));
+                       val = strtoul(arg, &p, 0);
+                       if (*p != '\0' || (val < 3 && val != 0) || val > 200) {
+                               fprintf(stderr, _("Invalid badness '%s'\n"),
+                                       arg);
                                extended_usage++;
                                continue;
                        }
+                       ctx->inode_badness_threshold = val;
                } else if (strcmp(token, "journal_only") == 0) {
                        if (arg) {
                                extended_usage++;
index 24b3444..a21e499 100644 (file)
@@ -1,23 +1,37 @@
 Pass 1: Checking inodes, blocks, and sizes
+e2fsck_pass1_run: increase inode 13 badness 0 to 1 for 10005
 Inode 13 is in use, but has dtime set.  Fix? yes
 
+e2fsck_pass1_run: increase inode 13 badness 1 to 2 for 2000f
+e2fsck_pass1_run: increase inode 13 badness 2 to 3 for 20044
+e2fsck_pass1_run: increase inode 13 badness 3 to 5 for 10084
+check_ext_attr: increase inode 13 badness 5 to 6 for 2000e
+process_block: increase inode 13 badness 6 to 7 for 1000e
 Inode 13 has illegal block(s).  Clear? yes
 
 Illegal block #0 (4294967295) in inode 13.  CLEARED.
+process_block: increase inode 13 badness 7 to 8 for 1000e
 Illegal block #1 (4294967295) in inode 13.  CLEARED.
+process_block: increase inode 13 badness 8 to 9 for 1000e
 Illegal block #7 (12345678) in inode 13.  CLEARED.
+process_block: increase inode 13 badness 9 to 10 for 1000e
 Illegal triple indirect block (1234567) in inode 13.  CLEARED.
+check_blocks: increase inode 13 badness 10 to 11 for 1000d
 Inode 13, i_blocks is 3453453, should be 138.  Fix? yes
 
 Pass 2: Checking directory structure
+e2fsck_process_bad_inode: increase inode 13 badness 11 to 12 for 2000e
 i_file_acl for inode 13 (/testfile) is 345, should be zero.
 Clear? yes
 
+e2fsck_process_bad_inode: increase inode 13 badness 12 to 13 for 2000d
 i_faddr for inode 13 (/testfile) is 34534, should be zero.
 Clear? yes
 
 Inode 13 is badly corrupt (badness value = 13).  Clear? yes
 
+Entry 'testfile' in / (2) has deleted/unused inode 13.  Clear? yes
+
 Pass 3: Checking directory connectivity
 Pass 4: Checking reference counts
 Pass 5: Checking group summary information
diff --git a/tests/f_ibadness/script b/tests/f_ibadness/script
new file mode 100644 (file)
index 0000000..324a3e4
--- /dev/null
@@ -0,0 +1,4 @@
+FSCK_OPT="-fyd"
+SECOND_FSCK_OPT=-yf
+
+. $cmd_dir/run_e2fsck
index 664b3ed..d627834 100644 (file)
@@ -1,24 +1,45 @@
 Pass 1: Checking inodes, blocks, and sizes
+e2fsck_pass1_run: increase inode 12 badness 0 to 1 for 1005c
+Inode 12 missing EXTENT_FL, but is in extents format
+Fix? yes
+
+e2fsck_pass1_run: increase inode 12 badness 1 to 2 for 10005
+Inode 12 is in use, but has dtime set.  Fix? yes
+
+e2fsck_pass1_run: increase inode 12 badness 2 to 3 for 20044
+e2fsck_pass1_run: increase inode 12 badness 3 to 4 for 10084
+e2fsck_pass1_run: increase inode 12 badness 4 to 5 for 10084
+e2fsck_pass1_run: increase inode 12 badness 5 to 7 for 10084
+check_ext_attr: increase inode 12 badness 7 to 8 for 2000e
+scan_extent_node: increase inode 12 badness 8 to 9 for 10058
 Inode 12 has an invalid extent
        (logical block 0, invalid physical block 1231231222, len 492)
 Clear? yes
 
+scan_extent_node: increase inode 12 badness 9 to 10 for 10058
 Inode 12 has an invalid extent
        (logical block 556, invalid physical block 4294967295, len 45)
 Clear? yes
 
+scan_extent_node: increase inode 12 badness 10 to 11 for 10058
 Inode 12 has an invalid extent
        (logical block 666, invalid physical block 4294967295, len 5)
 Clear? yes
 
+scan_extent_node: increase inode 12 badness 11 to 12 for 10058
 Inode 12 has an invalid extent
        (logical block 700, invalid physical block 4294967295, len 45)
 Clear? yes
 
+check_blocks: increase inode 12 badness 12 to 13 for 1000d
 Inode 12, i_blocks is 984, should be 0.  Fix? yes
 
+Inode 12 is badly corrupt (badness value = 13).  Clear? yes
+
+Restarting e2fsck from the beginning...
+Pass 1: Checking inodes, blocks, and sizes
 Pass 2: Checking directory structure
-Inode 12 is badly corrupt (badness value = 9).  Clear? yes
+Entry 'testfile' in / (2) has deleted/unused inode 12.  Clear? yes
 
 Pass 3: Checking directory connectivity
 Pass 4: Checking reference counts
@@ -32,6 +53,15 @@ Fix? yes
 Free blocks count wrong (14584, counted=15076).
 Fix? yes
 
+Inode bitmap differences:  -12
+Fix? yes
+
+Free inodes count wrong for group #0 (1012, counted=1013).
+Fix? yes
+
+Free inodes count wrong (2036, counted=2037).
+Fix? yes
+
 
 test_filesys: ***** FILE SYSTEM WAS MODIFIED *****
 test_filesys: 11/2048 files (0.0% non-contiguous), 1308/16384 blocks
index 1c267f0..65d1b46 100644 (file)
Binary files a/tests/f_ibadness_bad_extents/image.gz and b/tests/f_ibadness_bad_extents/image.gz differ
diff --git a/tests/f_ibadness_bad_extents/script b/tests/f_ibadness_bad_extents/script
new file mode 100644 (file)
index 0000000..324a3e4
--- /dev/null
@@ -0,0 +1,4 @@
+FSCK_OPT="-fyd"
+SECOND_FSCK_OPT=-yf
+
+. $cmd_dir/run_e2fsck
index cc4819e..67cca25 100644 (file)
@@ -1,31 +1,19 @@
 Filesystem did not have a UUID; generating one.
 
 Pass 1: Checking inodes, blocks, and sizes
-check_ext_attr:: increase inode 14 badness 0 to 1
-process_block:: increase inode 14 badness 1 to 2
 Inode 14 has illegal block(s).  Clear? yes
 
 Illegal block #2 (4294901760) in inode 14.  CLEARED.
-process_block:: increase inode 14 badness 2 to 3
 Illegal block #3 (4294901760) in inode 14.  CLEARED.
-process_block:: increase inode 14 badness 3 to 4
 Illegal block #4 (4294901760) in inode 14.  CLEARED.
-process_block:: increase inode 14 badness 4 to 5
 Illegal block #5 (4294901760) in inode 14.  CLEARED.
-process_block:: increase inode 14 badness 5 to 6
 Illegal block #6 (4294901760) in inode 14.  CLEARED.
-process_block:: increase inode 14 badness 6 to 7
 Illegal block #7 (4294901760) in inode 14.  CLEARED.
-process_block:: increase inode 14 badness 7 to 8
 Illegal block #8 (4294901760) in inode 14.  CLEARED.
-process_block:: increase inode 14 badness 8 to 9
 Illegal block #9 (4294901760) in inode 14.  CLEARED.
-process_block:: increase inode 14 badness 9 to 10
 Illegal block #10 (4294901760) in inode 14.  CLEARED.
-check_blocks:: increase inode 14 badness 10 to 11
 Inode 14, i_size is 18446462598732849291, should be 2048.  Fix? yes
 
-check_blocks:: increase inode 14 badness 11 to 12
 Inode 14, i_blocks is 18, should be 4.  Fix? yes
 
 Pass 2: Checking directory structure
@@ -34,6 +22,8 @@ Clear? yes
 
 Inode 14 is badly corrupt (badness value = 13).  Clear? yes
 
+Entry 'MAKEDEV' in / (2) has deleted/unused inode 14.  Clear? yes
+
 Pass 3: Checking directory connectivity
 Pass 4: Checking reference counts
 Pass 5: Checking group summary information
index fe3a2c5..3277356 100644 (file)
@@ -1,4 +1,4 @@
-FSCK_OPT="-fy -d"
+FSCK_OPT="-fy"
 OUT1=$test_name.1.log
 AFTER_CMD="sed -i -e 's/:[0-9]\{4\}:/::/' $OUT1"
 
index 796186e..a1cf16d 100644 (file)
@@ -38,3 +38,4 @@ s/mmp_update_date: .*/mmp_update_date: test date/
 s/mmp_update_time: .*/mmp_update_time: test_time/
 s/MMP last updated by '.*' on .*/MMP last updated by 'test_node' on test date/
 s/MMP update by '.*' at .*/MMP last updated by 'test_node' on test date/
+s/:[0-9]*: \(increase inode [0-9]* badness\)/: \1/