From: Li Dongyang Date: Fri, 19 Jul 2024 06:09:16 +0000 (+1000) Subject: LU-15985 e2fsck: skip block scanning if the inode is too bad X-Git-Tag: v1.47.1-wc2~1 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=cd423df181fba2de46dc632fcebda754a1a4f683;p=tools%2Fe2fsprogs.git LU-15985 e2fsck: skip block scanning if the inode is too bad If the inode is badly corrupted, scanning the extent tree/blocks could get stuck repeating the error with: Inode %i block %b conflicts with critical metadata, skipping block checks. This error PR_1_CRITICAL_METADATA_COLLISION bumps up inode badness by 2 already, we could skip the block/extent scanning if the inode badness is above the threshold. Add test case f_ibadness_meta_collision to verify this. Change-Id: Ifd7246ee8cceb4ea11d2c255310c5af0176bfb1c Signed-off-by: Li Dongyang Reviewed-on: https://review.whamcloud.com/c/tools/e2fsprogs/+/55802 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Li Xi Reviewed-by: Andreas Dilger --- diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 7399fe7..412a756 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -4745,6 +4745,17 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, while ((pctx->errcode == 0 || pctx->errcode == EXT2_ET_EXTENT_CSUM_INVALID) && info.num_entries-- > 0) { + __u16 badness; + + if (ctx->inode_badness && + !ext2fs_icount_fetch(ctx->inode_badness, + pb->ino, &badness) && + badness > ctx->inode_badness_threshold) { + log_out(ctx, "Inode %lu is badly corrupt, skipping block check\n", + pb->ino); + return; + } + is_leaf = extent.e_flags & EXT2_EXTENT_FLAGS_LEAF; is_dir = LINUX_S_ISDIR(pctx->inode->i_mode); last_lblk = extent.e_lblk + extent.e_len - 1; @@ -5588,6 +5599,7 @@ static int process_block(ext2_filsys fs, int ret_code = 0; problem_t problem = 0; e2fsck_t ctx; + __u16 badness; p = (struct process_block_struct *) priv_data; pctx = p->pctx; @@ -5611,6 +5623,14 @@ static int process_block(ext2_filsys fs, if (blk == 0) return 0; + if (ctx->inode_badness && + !ext2fs_icount_fetch(ctx->inode_badness, p->ino, &badness) && + badness > ctx->inode_badness_threshold) { + log_out(ctx, "Inode %lu is badly corrupt, skipping block check\n", + p->ino); + return BLOCK_ABORT; + } + #if 0 printf("Process_block, inode %lu, block %u, #%d\n", p->ino, blk, blockcnt); diff --git a/tests/f_ibadness_meta_collision/expect.1 b/tests/f_ibadness_meta_collision/expect.1 new file mode 100644 index 0000000..6012071 --- /dev/null +++ b/tests/f_ibadness_meta_collision/expect.1 @@ -0,0 +1,51 @@ +Pass 1: Checking inodes, blocks, and sizes +process_block: increase inode 12 badness 0 to 2 for 10071 +Inode 12 block 104 conflicts with critical metadata, skipping block checks. +process_block: increase inode 12 badness 2 to 4 for 10071 +Inode 12 block 104 conflicts with critical metadata, skipping block checks. +process_block: increase inode 12 badness 4 to 6 for 10071 +Inode 12 block 104 conflicts with critical metadata, skipping block checks. +process_block: increase inode 12 badness 6 to 8 for 10071 +Inode 12 block 104 conflicts with critical metadata, skipping block checks. +process_block: increase inode 12 badness 8 to 10 for 10071 +Inode 12 block 104 conflicts with critical metadata, skipping block checks. +process_block: increase inode 12 badness 10 to 12 for 10071 +Inode 12 block 104 conflicts with critical metadata, skipping block checks. +process_block: increase inode 12 badness 12 to 14 for 10071 +Inode 12 block 104 conflicts with critical metadata, skipping block checks. +Inode 12 is badly corrupt, skipping block check +check_blocks: increase inode 12 badness 14 to 15 for 1000d +Inode 12, i_blocks is 2, should be 16. Fix? yes + +Inode 12 is badly corrupt (badness value = 15). Clear? yes + +Restarting e2fsck from the beginning... +Pass 1: Checking inodes, blocks, and sizes +Pass 2: Checking directory structure +Entry 'testfile' 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: -2651 +Fix? yes + +Free blocks count wrong for group #0 (5541, counted=5542). +Fix? yes + +Free blocks count wrong (13153, counted=13154). +Fix? yes + +Inode bitmap differences: -12 +Fix? yes + +Free inodes count wrong for group #0 (2036, counted=2037). +Fix? yes + +Free inodes count wrong (4084, counted=4085). +Fix? yes + + +test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** +test_filesys: 11/4096 files (0.0% non-contiguous), 3230/16384 blocks +Exit status is 1 diff --git a/tests/f_ibadness_meta_collision/expect.2 b/tests/f_ibadness_meta_collision/expect.2 new file mode 100644 index 0000000..1f4c8aa --- /dev/null +++ b/tests/f_ibadness_meta_collision/expect.2 @@ -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/4096 files (0.0% non-contiguous), 3230/16384 blocks +Exit status is 0 diff --git a/tests/f_ibadness_meta_collision/image.gz b/tests/f_ibadness_meta_collision/image.gz new file mode 100644 index 0000000..685923a Binary files /dev/null and b/tests/f_ibadness_meta_collision/image.gz differ diff --git a/tests/f_ibadness_meta_collision/name b/tests/f_ibadness_meta_collision/name new file mode 100644 index 0000000..a3b38c5 --- /dev/null +++ b/tests/f_ibadness_meta_collision/name @@ -0,0 +1 @@ +Bad inode has many blocks colliding with metadata diff --git a/tests/f_ibadness_meta_collision/script b/tests/f_ibadness_meta_collision/script new file mode 100644 index 0000000..324a3e4 --- /dev/null +++ b/tests/f_ibadness_meta_collision/script @@ -0,0 +1,4 @@ +FSCK_OPT="-fyd" +SECOND_FSCK_OPT=-yf + +. $cmd_dir/run_e2fsck