From: Andreas Dilger <andreas.dilger@xxxxxxxxx> The present e2fsck code checks the inode, per field basis. It doesn't take into consideration to total sanity of the inode. This may cause e2fsck turning a garbage inode into an apparently sane inode ("It is a vessel of fertilizer, and none may abide its strength."). The following patch adds a heuristics to detect the degree of badness of an inode. icount mechanism is used to keep track of the badness of every inode. The badness is increased as various fields in inode are found to be corrupt. Badness above a certain threshold value results in deletion of the inode. The default badness threshold value is 7, it can be specified to e2fsck using "-E inode_badness_threshold=<value>" This can avoid lengthy pass1b shared block processing, where a corrupt chunk of the inode table has resulted in a bunch of garbage inodes suddenly having shared blocks with a lot of good inodes (or each other). Signed-off-by: Girish Shilamkar <girish@xxxxxxxxxxxxx> Signed-off-by: Andreas Dilger <andreas.dilger@xxxxxxxxx> Signed-off-by: Artem Blagodarenko <artem.blagodarenko@xxxxxxxxx> --- e2fsck/e2fsck.8.in | 9 +++ e2fsck/e2fsck.c | 4 - e2fsck/e2fsck.h | 27 ++++++- e2fsck/pass1.c | 140 ++++++++++++++++++++++++----------- e2fsck/pass1b.c | 4 +- e2fsck/pass2.c | 74 +++++++++++++----- e2fsck/pass4.c | 1 + e2fsck/problem.c | 5 ++ e2fsck/problem.h | 2 + e2fsck/super.c | 6 +- e2fsck/unix.c | 15 ++++ lib/ext2fs/ext2fs.h | 1 + lib/ext2fs/icount.c | 17 +++++ tests/f_ind_inode_collision/expect.1 | 43 ++--------- tests/f_ind_inode_collision/expect.2 | 18 ++++- tests/f_messy_inode/expect.1 | 20 ++++- tests/f_messy_inode/expect.2 | 2 +- tests/f_no/expect | 1 + tests/f_yes/expect | 8 +- tests/f_yesall/expect | 8 +- tests/f_yesthenall/expect | 8 +- tests/f_yesthenno/expect | 1 + 22 files changed, 288 insertions(+), 126 deletions(-) diff --git a/e2fsck/e2fsck.8.in b/e2fsck/e2fsck.8.in index ec6427ee..fbdd1d06 100644 --- a/e2fsck/e2fsck.8.in +++ b/e2fsck/e2fsck.8.in @@ -221,6 +221,15 @@ be 1 or 2. The default extended attribute version format is 2. Only replay the journal if required, but do not perform any further checks 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 +.I threshold_value +will be prompted for deletion. The default +.I threshold_value +is 7. +.TP .BI fragcheck During pass 1, print a detailed report of any discontiguous blocks for files in the filesystem. diff --git a/e2fsck/e2fsck.c b/e2fsck/e2fsck.c index 88088a25..284411f1 100644 --- a/e2fsck/e2fsck.c +++ b/e2fsck/e2fsck.c @@ -126,10 +126,6 @@ errcode_t e2fsck_reset_context(e2fsck_t ctx) ext2fs_free_inode_bitmap(ctx->inode_bb_map); ctx->inode_bb_map = 0; } - if (ctx->inode_bad_map) { - ext2fs_free_inode_bitmap(ctx->inode_bad_map); - ctx->inode_bad_map = 0; - } if (ctx->inode_imagic_map) { ext2fs_free_inode_bitmap(ctx->inode_imagic_map); ctx->inode_imagic_map = 0; diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h index 0014fc2c..e434dad1 100644 --- a/e2fsck/e2fsck.h +++ b/e2fsck/e2fsck.h @@ -11,6 +11,7 @@ #include <stdio.h> #include <string.h> +#include <stddef.h> #ifdef HAVE_UNISTD_H #include <unistd.h> #endif @@ -220,6 +221,24 @@ enum clone_opt { E2F_CLONE_ZERO }; +#define EXT4_FITS_IN_INODE(ext4_inode, einode, field) \ + ((offsetof(typeof(*ext4_inode), field) + \ + sizeof(ext4_inode->field)) <= \ + (EXT2_GOOD_OLD_INODE_SIZE + \ + (einode)->i_extra_isize)) \ + +#define EXT4_XTIME_FUTURE(ctx, sb, xtime, margin) \ + (!((ctx)->flags & E2F_FLAG_TIME_INSANE) && \ + (xtime) > (ctx)->now + (margin)) +#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 the extended attribute refcount structure */ @@ -261,7 +280,6 @@ struct e2fsck_struct { unsigned long max); ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */ - ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */ ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */ ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */ ext2fs_inode_bitmap inode_imagic_map; /* AFS inodes */ @@ -276,6 +294,8 @@ struct e2fsck_struct { */ ext2_icount_t inode_count; ext2_icount_t inode_link_info; + ext2_icount_t inode_badness; + int inode_badness_threshold; ext2_refcount_t refcount; ext2_refcount_t refcount_extra; @@ -550,6 +570,11 @@ extern int e2fsck_pass1_check_symlink(ext2_filsys fs, 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); extern void e2fsck_intercept_block_allocations(e2fsck_t ctx); /* pass2.c */ diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 1d60cc88..0fedb9a4 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -20,7 +20,8 @@ * - A bitmap of which inodes are in use. (inode_used_map) * - A bitmap of which inodes are directories. (inode_dir_map) * - A bitmap of which inodes are regular files. (inode_reg_map) - * - A bitmap of which inodes have bad fields. (inode_bad_map) + * - An icount mechanism is used to keep track of + * inodes with bad fields and its badness (ctx->inode_badness) * - A bitmap of which inodes are in bad blocks. (inode_bb_map) * - A bitmap of which inodes are imagic inodes. (inode_imagic_map) * - A bitmap of which blocks are in use. (block_found_map) @@ -76,7 +77,6 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, static void mark_table_blocks(e2fsck_t ctx); static void alloc_bb_map(e2fsck_t ctx); static void alloc_imagic_map(e2fsck_t ctx); -static void mark_inode_bad(e2fsck_t ctx, ino_t ino); static void add_encrypted_dir(e2fsck_t ctx, ino_t ino); static void handle_fs_bad_blocks(e2fsck_t ctx); static void process_inodes(e2fsck_t ctx, char *block_buf); @@ -292,6 +292,7 @@ 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; @@ -310,6 +311,7 @@ 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; @@ -574,7 +576,7 @@ static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx, struct ext2_super_block *sb = ctx->fs->super; struct ext2_inode_large *inode; __u32 *eamagic; - int min, max; + int min, max, dirty = 0; ea_ibody_quota->blocks = 0; ea_ibody_quota->inodes = 0; @@ -599,14 +601,14 @@ 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) inode->i_extra_isize = sb->s_want_extra_isize; else inode->i_extra_isize = (inode->i_extra_isize + 3) & ~3; - e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode, - EXT2_INODE_SIZE(sb), "pass1"); + dirty = 1; } /* check if there is no place for an EA header */ @@ -643,10 +645,12 @@ static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx, inode->i_crtime_extra &= ~EXT4_EPOCH_MASK; if (CHECK_INODE_EXTRA_NEGATIVE_EPOCH(inode, mtime)) inode->i_mtime_extra &= ~EXT4_EPOCH_MASK; - e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode, - EXT2_INODE_SIZE(sb), "pass1"); + dirty = 1; } + if (dirty) + e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode, + EXT2_INODE_SIZE(sb), "pass1"); } /* @@ -801,6 +805,7 @@ 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, @@ -1626,15 +1631,19 @@ void e2fsck_pass1(e2fsck_t ctx) ehp = inode->i_block; #endif if ((ext2fs_extent_header_verify(ehp, - sizeof(inode->i_block)) == 0) && - (fix_problem(ctx, PR_1_UNSET_EXTENT_FL, &pctx))) { - inode->i_flags |= EXT4_EXTENTS_FL; + 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; #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; + } } } @@ -1706,6 +1715,7 @@ void e2fsck_pass1(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, @@ -1809,6 +1819,7 @@ void e2fsck_pass1(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"); @@ -1829,15 +1840,15 @@ void e2fsck_pass1(e2fsck_t ctx) if (inode->i_faddr || frag || fsize || (!ext2fs_has_feature_largedir(fs->super) && (LINUX_S_ISDIR(inode->i_mode) && inode->i_size_high))) - mark_inode_bad(ctx, ino); + e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); if ((fs->super->s_creator_os != EXT2_OS_HURD) && !ext2fs_has_feature_64bit(fs->super) && inode->osd2.linux2.l_i_file_acl_high != 0) - mark_inode_bad(ctx, ino); + e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); if ((fs->super->s_creator_os != EXT2_OS_HURD) && !ext2fs_has_feature_huge_file(fs->super) && (inode->osd2.linux2.l_i_blocks_hi != 0)) - mark_inode_bad(ctx, ino); + e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); if (inode->i_flags & EXT2_IMAGIC_FL) { if (imagic_fs) { if (!ctx->inode_imagic_map) @@ -1845,6 +1856,7 @@ void e2fsck_pass1(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, @@ -1919,8 +1931,24 @@ void e2fsck_pass1(e2fsck_t ctx) check_immutable(ctx, &pctx); check_size(ctx, &pctx); ctx->fs_sockets_count++; - } else - mark_inode_bad(ctx, ino); + } else { + e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); + } + + 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); + + if (EXT4_XTIME_FUTURE(ctx, sb, inode->i_ctime, ctx->time_fudge)) + e2fsck_mark_inode_bad(ctx, ino, BADNESS_HIGH); + else if (EXT4_XTIME_ANCIENT(ctx, sb, inode->i_ctime, + ctx->time_fudge)) + e2fsck_mark_inode_bad(ctx, ino, BADNESS_HIGH); + + /* i_crtime is checked in check_inode_extra_space() */ + if (!(inode->i_flags & EXT4_EXTENTS_FL) && !(inode->i_flags & EXT4_INLINE_DATA_FL)) { if (inode->i_block[EXT2_IND_BLOCK]) @@ -2165,27 +2193,31 @@ static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b) } /* - * Mark an inode as being bad in some what + * Mark an inode as being bad and increment its badness counter. */ -static void mark_inode_bad(e2fsck_t ctx, ino_t ino) +void e2fsck_mark_inode_bad_loc(e2fsck_t ctx, ino_t ino, int count, + const char *func, const int line) { struct problem_context pctx; + __u16 result; - if (!ctx->inode_bad_map) { + if (!ctx->inode_badness) { clear_problem_context(&pctx); - pctx.errcode = e2fsck_allocate_inode_bitmap(ctx->fs, - _("bad inode map"), EXT2FS_BMAP64_RBTREE, - "inode_bad_map", &ctx->inode_bad_map); + pctx.errcode = ext2fs_create_icount2(ctx->fs, 0, 0, NULL, + &ctx->inode_badness); if (pctx.errcode) { - pctx.num = 3; - fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); - /* Should never get here */ + fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx); ctx->flags |= E2F_FLAG_ABORT; return; } } - ext2fs_mark_inode_bitmap2(ctx->inode_bad_map, ino); + ext2fs_icount_fetch(ctx->inode_badness, ino, &result); + ext2fs_icount_store(ctx->inode_badness, ino, count + result); + + 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); } static void add_encrypted_dir(e2fsck_t ctx, ino_t ino) @@ -2379,7 +2411,8 @@ static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx, if (!ext2fs_has_feature_xattr(fs->super) || (blk < fs->super->s_first_data_block) || (blk >= ext2fs_blocks_count(fs->super))) { - mark_inode_bad(ctx, ino); + /* Fixed in pass2, e2fsck_process_bad_inode(). */ + e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); return 0; } @@ -2627,9 +2660,11 @@ 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) && - fix_problem(ctx, PR_1_HTREE_SET, pctx))) - return 1; + (!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; + } pctx->errcode = ext2fs_bmap2(fs, ino, inode, 0, 0, 0, 0, &blk); @@ -2637,6 +2672,7 @@ 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 @@ -2644,8 +2680,11 @@ static int handle_htree(e2fsck_t ctx, struct problem_context *pctx, } retval = io_channel_read_blk64(fs->io, blk, 1, block_buf); - if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) - return 1; + if (retval) { + e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); + if (fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) + return 1; + } /* XXX should check that beginning matches a directory */ root = (struct ext2_dx_root_info *) (block_buf + 24); @@ -2696,8 +2735,8 @@ void e2fsck_clear_inode(e2fsck_t ctx, ext2_ino_t ino, ext2fs_unmark_inode_bitmap2(ctx->inode_used_map, ino); if (ctx->inode_reg_map) ext2fs_unmark_inode_bitmap2(ctx->inode_reg_map, ino); - if (ctx->inode_bad_map) - ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino); + if (ctx->inode_badness) + ext2fs_icount_store(ctx->inode_badness, ino, 0); /* * If the inode was partially accounted for before processing @@ -2850,6 +2889,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)) { if (ctx->invalid_bitmaps) { @@ -3382,6 +3425,11 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, if (!pb.num_blocks && pb.is_dir && !(inode->i_flags & EXT4_INLINE_DATA_FL)) { + /* + * 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--; @@ -3470,6 +3518,7 @@ 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, BADNESS_NORMAL); if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) { if (LINUX_S_ISDIR(inode->i_mode)) pctx->num &= 0xFFFFFFFFULL; @@ -3493,6 +3542,7 @@ 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; @@ -3510,11 +3560,13 @@ static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, (LINUX_S_ISREG(inode->i_mode) || LINUX_S_ISDIR(inode->i_mode)) && ext2fs_inode_data_blocks2(fs, inode) > 0 && (ino == EXT2_ROOT_INO || ino >= EXT2_FIRST_INO(fs->super)) && - !(inode->i_flags & (EXT4_EXTENTS_FL | EXT4_INLINE_DATA_FL)) && - fix_problem(ctx, PR_1_NO_BIGALLOC_BLOCKMAP_FILES, pctx)) { - pctx->errcode = e2fsck_rebuild_extents_later(ctx, ino); - if (pctx->errcode) - goto out; + !(inode->i_flags & (EXT4_EXTENTS_FL | EXT4_INLINE_DATA_FL))) { + e2fsck_mark_inode_bad(ctx, ino, BADNESS_NORMAL); + if (fix_problem(ctx, PR_1_NO_BIGALLOC_BLOCKMAP_FILES, pctx)) { + pctx->errcode = e2fsck_rebuild_extents_later(ctx, ino); + if (pctx->errcode) + goto out; + } } if (ctx->dirs_to_hash && pb.is_dir && @@ -3658,8 +3710,10 @@ 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 diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c index e63fb083..d5802cfe 100644 --- a/e2fsck/pass1b.c +++ b/e2fsck/pass1b.c @@ -695,8 +695,8 @@ 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_bad_map) - ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino); + if (ctx->inode_badness) + e2fsck_mark_inode_bad(ctx, ino, 0); ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(dp->inode.i_mode)); quota_data_sub(ctx->qctx, &dp->inode, ino, pb.dup_blocks * fs->blocksize); diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c index e922876d..4dc20224 100644 --- a/e2fsck/pass2.c +++ b/e2fsck/pass2.c @@ -33,11 +33,10 @@ * Pass 2 relies on the following information from previous passes: * - The directory information collected in pass 1. * - The inode_used_map bitmap - * - The inode_bad_map bitmap + * - The inode_badness bitmap * - The inode_dir_map bitmap * * Pass 2 frees the following data structures - * - The inode_bad_map bitmap * - The inode_reg_map bitmap */ @@ -276,10 +275,6 @@ void e2fsck_pass2(e2fsck_t ctx) ext2fs_free_mem(&buf); ext2fs_free_dblist(fs->dblist); - if (ctx->inode_bad_map) { - ext2fs_free_inode_bitmap(ctx->inode_bad_map); - ctx->inode_bad_map = 0; - } if (ctx->inode_reg_map) { ext2fs_free_inode_bitmap(ctx->inode_reg_map); ctx->inode_reg_map = 0; @@ -528,6 +523,7 @@ static _INLINE_ int check_filetype(e2fsck_t ctx, int filetype = ext2fs_dirent_file_type(dirent); int should_be = EXT2_FT_UNKNOWN; struct ext2_inode inode; + __u16 result; if (!ext2fs_has_feature_filetype(ctx->fs->super)) { if (filetype == 0 || @@ -537,16 +533,18 @@ static _INLINE_ int check_filetype(e2fsck_t ctx, return 1; } + if (ctx->inode_badness) + ext2fs_icount_fetch(ctx->inode_badness, dirent->inode, + &result); + 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_bad_map && - ext2fs_test_inode_bitmap2(ctx->inode_bad_map, - dirent->inode)) + } else if (ctx->inode_badness && result >= BADNESS_BAD_MODE) { should_be = 0; - else { + } else { e2fsck_read_inode(ctx, dirent->inode, &inode, "check_filetype"); should_be = ext2_file_type(inode.i_mode); @@ -1334,11 +1332,9 @@ skip_checksum: * (We wait until now so that we can display the * pathname to the user.) */ - if (ctx->inode_bad_map && - ext2fs_test_inode_bitmap2(ctx->inode_bad_map, - dirent->inode)) { - if (e2fsck_process_bad_inode(ctx, ino, - dirent->inode, + if (ctx->inode_badness && + ext2fs_icount_is_set(ctx->inode_badness, dirent->inode)) { + if (e2fsck_process_bad_inode(ctx, ino, dirent->inode, buf + fs->blocksize)) { dirent->inode = 0; dir_modified++; @@ -1646,8 +1642,17 @@ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) struct problem_context pctx; __u32 count; struct del_block del_block; + int extent_fs = 0; e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); + /* ext2fs_block_iterate2() depends on the extents flags */ + if (inode.i_flags & EXT4_EXTENTS_FL) + extent_fs = 1; + e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode"); + if (extent_fs) { + inode.i_flags |= EXT4_EXTENTS_FL; + e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode"); + } clear_problem_context(&pctx); pctx.ino = ino; @@ -1676,6 +1681,8 @@ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) ext2fs_block_alloc_stats2(fs, ext2fs_file_acl_block(fs, &inode), -1); } + if (ctx->inode_badness) + ext2fs_icount_store(ctx->inode_badness, ino, 0); ext2fs_file_acl_block_set(fs, &inode, 0); } @@ -1731,7 +1738,10 @@ 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; + if (ctx->inode_badness) + ext2fs_icount_fetch(ctx->inode_badness, ino, &badness); e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode"); clear_problem_context(&pctx); @@ -1746,6 +1756,7 @@ 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) && @@ -1779,6 +1790,11 @@ int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, } else not_fixed++; problem = 0; + /* + * A high value is associated with bad mode in order to detect + * that mode was corrupt in check_filetype() + */ + badness += BADNESS_BAD_MODE; } if (inode.i_faddr) { @@ -1787,6 +1803,7 @@ 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) { @@ -1804,6 +1821,7 @@ 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) { @@ -1813,6 +1831,7 @@ int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, inode_modified++; } else not_fixed++; + badness += BADNESS_NORMAL; pctx.num = 0; } @@ -1824,6 +1843,8 @@ 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) && @@ -1835,6 +1856,7 @@ 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) && @@ -1845,6 +1867,7 @@ 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) && LINUX_S_ISDIR(inode.i_mode)) { @@ -1853,12 +1876,29 @@ 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; + } + not_fixed++; } if (inode_modified) e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode"); - if (!not_fixed && ctx->inode_bad_map) - ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino); + if (ctx->inode_badness) + ext2fs_icount_store(ctx->inode_badness, ino, 0); return 0; } diff --git a/e2fsck/pass4.c b/e2fsck/pass4.c index 9a491b13..9b8c83ec 100644 --- a/e2fsck/pass4.c +++ b/e2fsck/pass4.c @@ -253,6 +253,7 @@ 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); diff --git a/e2fsck/problem.c b/e2fsck/problem.c index 4c1d8628..37a0a3c4 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -1679,6 +1679,11 @@ static struct e2fsck_problem problem_table[] = { N_("Encrypted @E is too short.\n"), PROMPT_CLEAR, 0 }, + /* Inode too bad */ + { PR_2_INODE_TOOBAD, + N_("@i %i is badly corrupt (badness value = %N). "), + PROMPT_CLEAR, PR_PREEN_OK }, + /* Pass 3 errors */ /* Pass 3: Checking directory connectivity */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index 516cbc35..7c6f4ff8 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -1010,6 +1010,8 @@ struct problem_context { /* Encrypted directory entry is too short */ #define PR_2_BAD_ENCRYPTED_NAME 0x020050 +/* Inode completely corrupt */ +#define PR_2_INODE_TOOBAD 0x020051 /* * Pass 3 errors */ diff --git a/e2fsck/super.c b/e2fsck/super.c index eb5387ba..5f84d086 100644 --- a/e2fsck/super.c +++ b/e2fsck/super.c @@ -913,8 +913,7 @@ void check_super_block(e2fsck_t ctx) * write time is in the future. */ if (!broken_system_clock && - !(ctx->flags & E2F_FLAG_TIME_INSANE) && - fs->super->s_mtime > (__u32) ctx->now) { + EXT4_XTIME_FUTURE(ctx, fs->super, fs->super->s_mtime, 0)) { pctx.num = fs->super->s_mtime; problem = PR_0_FUTURE_SB_LAST_MOUNT; if (fs->super->s_mtime <= (__u32) ctx->now + ctx->time_fudge) @@ -925,8 +924,7 @@ void check_super_block(e2fsck_t ctx) } } if (!broken_system_clock && - !(ctx->flags & E2F_FLAG_TIME_INSANE) && - fs->super->s_wtime > (__u32) ctx->now) { + EXT4_XTIME_FUTURE(ctx, fs->super, fs->super->s_wtime, 0)) { pctx.num = fs->super->s_wtime; problem = PR_0_FUTURE_SB_LAST_WRITE; if (fs->super->s_wtime <= (__u32) ctx->now + ctx->time_fudge) diff --git a/e2fsck/unix.c b/e2fsck/unix.c index e1de9060..a865abc4 100644 --- a/e2fsck/unix.c +++ b/e2fsck/unix.c @@ -772,6 +772,18 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts) extended_usage++; continue; } + /* -E inode_badness_threshold=<value> */ + } else if (strcmp(token, "inode_badness_threshold") == 0) { + 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")); + extended_usage++; + continue; + } } else if (strcmp(token, "journal_only") == 0) { if (arg) { extended_usage++; @@ -834,6 +846,7 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts) fputs("\tbmap2extent\n", stderr); fputs("\tfixes_only\n", stderr); fputs(("\tclone=<dup|zero>\n"), stderr); + fputs(("\tinode_badness_threhold=(value)\n"), stderr); fputc('\n', stderr); exit(1); } @@ -920,6 +933,8 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx) initialize_profile_options(ctx); + ctx->inode_badness_threshold = BADNESS_THRESHOLD; + phys_mem_kb = get_memory_size() / 1024; ctx->readahead_kb = ~0ULL; while ((c = getopt(argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDkz:")) != EOF) diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 6774e32c..f558619b 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -1441,6 +1441,7 @@ extern errcode_t ext2fs_initialize(const char *name, int flags, /* icount.c */ extern void ext2fs_free_icount(ext2_icount_t icount); +extern int ext2fs_icount_is_set(ext2_icount_t icount, ext2_ino_t ino); extern errcode_t ext2fs_create_icount_tdb(ext2_filsys fs, char *tdb_dir, int flags, ext2_icount_t *ret); extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, diff --git a/lib/ext2fs/icount.c b/lib/ext2fs/icount.c index d7de19fe..bc62b369 100644 --- a/lib/ext2fs/icount.c +++ b/lib/ext2fs/icount.c @@ -503,6 +503,23 @@ static errcode_t get_inode_count(ext2_icount_t icount, ext2_ino_t ino, return 0; } +int ext2fs_icount_is_set(ext2_icount_t icount, ext2_ino_t ino) +{ + __u16 result; + + if (ext2fs_test_inode_bitmap2(icount->single, ino)) + return 1; + else if (icount->multiple) { + if (ext2fs_test_inode_bitmap2(icount->multiple, ino)) + return 1; + return 0; + } + ext2fs_icount_fetch(icount, ino, &result); + if (result) + return 1; + return 0; +} + errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out) { errcode_t ret = 0; diff --git a/tests/f_ind_inode_collision/expect.1 b/tests/f_ind_inode_collision/expect.1 index 63c128b4..7ed0ec4a 100644 --- a/tests/f_ind_inode_collision/expect.1 +++ b/tests/f_ind_inode_collision/expect.1 @@ -102,45 +102,12 @@ Illegal block number passed to ext2fs_test_block_bitmap #65536 for multiply clai Illegal block number passed to ext2fs_test_block_bitmap #1421529397 for multiply claimed block map Illegal block number passed to ext2fs_test_block_bitmap #16777215 for multiply claimed block map Pass 2: Checking directory structure -Restarting e2fsck from the beginning... -Pass 1: Checking inodes, blocks, and sizes -Inode 12 has illegal block(s). Clear? yes - -Illegal block #1038 (1421529376) in inode 12. CLEARED. -Illegal block #1039 (1421529376) in inode 12. CLEARED. -Illegal block #1040 (1421529376) in inode 12. CLEARED. -Illegal block #1100 (16877) in inode 12. CLEARED. -Illegal block #1101 (4096) in inode 12. CLEARED. -Illegal block #1102 (1421529376) in inode 12. CLEARED. -Illegal block #1103 (1421529376) in inode 12. CLEARED. -Illegal block #1104 (1421529376) in inode 12. CLEARED. -Illegal block #1106 (196608) in inode 12. CLEARED. -Illegal block #1136 (1421529376) in inode 12. CLEARED. -Illegal block #1420 (33152) in inode 12. CLEARED. -Too many illegal blocks in inode 12. -Clear inode? yes - -Restarting e2fsck from the beginning... -Pass 1: Checking inodes, blocks, and sizes -Pass 2: Checking directory structure -Entry 'a' in / (2) has deleted/unused inode 12. Clear? yes +Inode 12 is badly corrupt (badness value = 37). Clear? yes -Pass 3: Checking directory connectivity -Pass 4: Checking reference counts -Pass 5: Checking group summary information -Block bitmap differences: -(3--7) -(15--17) -(19--24) -Fix? yes - -Inode bitmap differences: -12 -Fix? yes - -Free inodes count wrong for group #0 (116, counted=117). -Fix? yes - -Free inodes count wrong (116, counted=117). -Fix? yes +Error deallocating inode 12: Illegal indirect block found +test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** +e2fsck: aborted test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** -test_filesys: 11/128 files (9.1% non-contiguous), 18/512 blocks -Exit status is 1 +Exit status is 9 diff --git a/tests/f_ind_inode_collision/expect.2 b/tests/f_ind_inode_collision/expect.2 index d0a6dac4..856d900e 100644 --- a/tests/f_ind_inode_collision/expect.2 +++ b/tests/f_ind_inode_collision/expect.2 @@ -1,7 +1,23 @@ Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure +Entry 'a' in / (2) has deleted/unused inode 12. Clear? yes + Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information +Block bitmap differences: -(3--7) +(9--10) +(12--14) +Fix? yes + +Inode bitmap differences: -12 +Fix? yes + +Free inodes count wrong for group #0 (116, counted=117). +Fix? yes + +Free inodes count wrong (116, counted=117). +Fix? yes + + +test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** test_filesys: 11/128 files (9.1% non-contiguous), 18/512 blocks -Exit status is 0 +Exit status is 1 diff --git a/tests/f_messy_inode/expect.1 b/tests/f_messy_inode/expect.1 index 708f1da7..cc4819e7 100644 --- a/tests/f_messy_inode/expect.1 +++ b/tests/f_messy_inode/expect.1 @@ -1,38 +1,52 @@ 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 i_file_acl for inode 14 (/MAKEDEV) is 4294901760, should be zero. Clear? yes +Inode 14 is badly corrupt (badness value = 13). Clear? yes + Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information Block bitmap differences: -(43--49) Fix? yes -Free blocks count wrong for group #0 (68, counted=75). +Free blocks count wrong for group #0 (70, counted=77). Fix? yes -Free blocks count wrong (68, counted=75). +Free blocks count wrong (70, counted=77). Fix? yes test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** -test_filesys: 29/32 files (3.4% non-contiguous), 25/100 blocks +test_filesys: 28/32 files (3.6% non-contiguous), 23/100 blocks Exit status is 1 diff --git a/tests/f_messy_inode/expect.2 b/tests/f_messy_inode/expect.2 index 1fffb022..fb4e83ac 100644 --- a/tests/f_messy_inode/expect.2 +++ b/tests/f_messy_inode/expect.2 @@ -3,5 +3,5 @@ Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information -test_filesys: 29/32 files (0.0% non-contiguous), 25/100 blocks +test_filesys: 28/32 files (0.0% non-contiguous), 23/100 blocks Exit status is 0 diff --git a/tests/f_no/expect b/tests/f_no/expect index e7b619d5..68a69b36 100644 --- a/tests/f_no/expect +++ b/tests/f_no/expect @@ -27,6 +27,7 @@ Extended attribute block for inode 13 (/b) is invalid (298954296). Clear<y>? no Extended attribute block for inode 14 (/c) is invalid (388697201). Clear<y>? no +Inode 14 is badly corrupt (badness value = 8). Clear<y>? no Pass 3: Checking directory connectivity Pass 4: Checking reference counts Inode 12 ref count is 34463, should be 1. Fix<y>? no diff --git a/tests/f_yes/expect b/tests/f_yes/expect index c73e6204..d24fdec0 100644 --- a/tests/f_yes/expect +++ b/tests/f_yes/expect @@ -27,19 +27,19 @@ Extended attribute block for inode 13 (/b) is invalid (298954296). Clear ('a' enables 'yes' to all) <y>? yes Extended attribute block for inode 14 (/c) is invalid (388697201). Clear ('a' enables 'yes' to all) <y>? yes +Inode 14 is badly corrupt (badness value = 8). Clear ('a' enables 'yes' to all) <y>? yes Pass 3: Checking directory connectivity Pass 4: Checking reference counts -Inode 12 ref count is 34463, should be 1. Fix ('a' enables 'yes' to all) <y>? yes +Inode 12 ref count is 34463, should be 1. Fix<y>? yes Inode 13 ref count is 9999, should be 1. Fix<y>? yes -Inode 14 ref count is 12241, should be 1. Fix<y>? yes Pass 5: Checking group summary information Block bitmap differences: -202 -381 -457 Fix<y>? yes Free blocks count wrong for group #0 (0, counted=494). Fix<y>? yes -Free inodes count wrong for group #0 (4294967293, counted=114). +Free inodes count wrong for group #0 (4294967294, counted=115). Fix<y>? yes test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** -test_filesys: 14/128 files (0.0% non-contiguous), 18/512 blocks +test_filesys: 13/128 files (0.0% non-contiguous), 18/512 blocks Exit status is 1 diff --git a/tests/f_yesall/expect b/tests/f_yesall/expect index f6d3c2b8..196e8306 100644 --- a/tests/f_yesall/expect +++ b/tests/f_yesall/expect @@ -38,14 +38,14 @@ Clear? yes Extended attribute block for inode 14 (/c) is invalid (388697201). Clear? yes +Inode 14 is badly corrupt (badness value = 8). Clear? yes + Pass 3: Checking directory connectivity Pass 4: Checking reference counts Inode 12 ref count is 34463, should be 1. Fix? yes Inode 13 ref count is 9999, should be 1. Fix? yes -Inode 14 ref count is 12241, should be 1. Fix? yes - Pass 5: Checking group summary information Block bitmap differences: -202 -381 -457 Fix? yes @@ -53,10 +53,10 @@ Fix? yes Free blocks count wrong for group #0 (0, counted=494). Fix? yes -Free inodes count wrong for group #0 (4294967293, counted=114). +Free inodes count wrong for group #0 (4294967294, counted=115). Fix? yes test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** -test_filesys: 14/128 files (0.0% non-contiguous), 18/512 blocks +test_filesys: 13/128 files (0.0% non-contiguous), 18/512 blocks Exit status is 1 diff --git a/tests/f_yesthenall/expect b/tests/f_yesthenall/expect index 1fc3bde6..7e8f8dc1 100644 --- a/tests/f_yesthenall/expect +++ b/tests/f_yesthenall/expect @@ -28,14 +28,14 @@ Clear ('a' enables 'yes' to all) <y>? yes to all Extended attribute block for inode 14 (/c) is invalid (388697201). Clear? yes +Inode 14 is badly corrupt (badness value = 8). Clear? yes + Pass 3: Checking directory connectivity Pass 4: Checking reference counts Inode 12 ref count is 34463, should be 1. Fix? yes Inode 13 ref count is 9999, should be 1. Fix? yes -Inode 14 ref count is 12241, should be 1. Fix? yes - Pass 5: Checking group summary information Block bitmap differences: -202 -381 -457 Fix? yes @@ -43,10 +43,10 @@ Fix? yes Free blocks count wrong for group #0 (0, counted=494). Fix? yes -Free inodes count wrong for group #0 (4294967293, counted=114). +Free inodes count wrong for group #0 (4294967294, counted=115). Fix? yes test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** -test_filesys: 14/128 files (0.0% non-contiguous), 18/512 blocks +test_filesys: 13/128 files (0.0% non-contiguous), 18/512 blocks Exit status is 1 diff --git a/tests/f_yesthenno/expect b/tests/f_yesthenno/expect index de55f47d..3b7d92e9 100644 --- a/tests/f_yesthenno/expect +++ b/tests/f_yesthenno/expect @@ -27,6 +27,7 @@ Extended attribute block for inode 13 (/b) is invalid (298954296). Clear ('a' enables 'yes' to all) <y>? no Extended attribute block for inode 14 (/c) is invalid (388697201). Clear<y>? no +Inode 14 is badly corrupt (badness value = 8). Clear<y>? no Pass 3: Checking directory connectivity Pass 4: Checking reference counts Inode 12 ref count is 34463, should be 1. Fix<y>? no -- 2.14.3