From 000ba4046fbcc11ff70ef840988854d82235e5b5 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 21 Nov 2003 10:41:58 -0500 Subject: [PATCH] pass1.c (e2fsck_pass1), problem.h (PR_1_BB_FS_BLOCK), problem.c (PR_1_BB_FS_BLOCK, PR_1_BBINODE_BAD_METABLOCK_PROMPT): Fix up the handling of corrupted indirect blocks in the bad block. We now correctly handle the case where there is an overlap between a block group descriptor or a superblock and a bad block indirect block. In the case where the indirect block is corrupted, we now suggest "e2fsck -c". --- e2fsck/ChangeLog | 11 +++++++++++ e2fsck/pass1.c | 56 ++++++++++++++++++++++++++++++++++++++------------------ e2fsck/problem.c | 17 +++++++++++------ e2fsck/problem.h | 3 +++ 4 files changed, 63 insertions(+), 24 deletions(-) diff --git a/e2fsck/ChangeLog b/e2fsck/ChangeLog index d39d458e..094555a7 100644 --- a/e2fsck/ChangeLog +++ b/e2fsck/ChangeLog @@ -1,3 +1,14 @@ +2003-09-13 Theodore Ts'o + + * pass1.c (e2fsck_pass1), problem.h (PR_1_BB_FS_BLOCK), + problem.c (PR_1_BB_FS_BLOCK, PR_1_BBINODE_BAD_METABLOCK_PROMPT): + Fix up the handling of corrupted indirect blocks in the + bad block. We now correctly handle the case where there + is an overlap between a block group descriptor or + a superblock and a bad block indirect block. In the case + where the indirect block is corrupted, we now suggest + "e2fsck -c". + 2003-09-12 Theodore Ts'o * unix.c (PRS): Check the returned name from blkid_get_devname and diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 992d91d5..58edd0a5 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -78,7 +78,7 @@ static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount, struct process_block_struct { ext2_ino_t ino; int is_dir:1, is_reg:1, clear:1, suppress:1, - fragmented:1, compressed:1; + fragmented:1, compressed:1, bbcheck:1; blk_t num_blocks; blk_t max_blocks; e2_blkcnt_t last_block; @@ -86,6 +86,7 @@ struct process_block_struct { blk_t previous_block; struct ext2_inode *inode; struct problem_context *pctx; + ext2fs_block_bitmap fs_meta_blocks; e2fsck_t ctx; }; @@ -417,21 +418,35 @@ void e2fsck_pass1(e2fsck_t ctx) if (ino == EXT2_BAD_INO) { struct process_block_struct pb; + pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map, + &pb.fs_meta_blocks); + if (pctx.errcode) { + pctx.num = 4; + fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } pb.ino = EXT2_BAD_INO; pb.num_blocks = pb.last_block = 0; pb.num_illegal_blocks = 0; pb.suppress = 0; pb.clear = 0; pb.is_dir = 0; - pb.is_reg = 0; pb.fragmented = 0; + pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0; pb.inode = &inode; pb.pctx = &pctx; pb.ctx = ctx; pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf, process_bad_block, &pb); + ext2fs_free_block_bitmap(pb.fs_meta_blocks); if (pctx.errcode) { fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx); ctx->flags |= E2F_FLAG_ABORT; return; } + if (pb.bbcheck) + if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) { + ctx->flags |= E2F_FLAG_ABORT; + return; + } ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); clear_problem_context(&pctx); continue; @@ -1527,18 +1542,6 @@ mark_dir: return ret_code; } -static void bad_block_indirect(e2fsck_t ctx, blk_t blk) -{ - struct problem_context pctx; - - clear_problem_context(&pctx); - /* - * Prompt to see if we should continue or not. - */ - if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, &pctx)) - ctx->flags |= E2F_FLAG_ABORT; -} - static int process_bad_block(ext2_filsys fs, blk_t *block_nr, e2_blkcnt_t blockcnt, @@ -1579,8 +1582,20 @@ static int process_bad_block(ext2_filsys fs, } if (blockcnt < 0) { - if (ext2fs_test_block_bitmap(ctx->block_found_map, blk)) { - bad_block_indirect(ctx, blk); + if (ext2fs_test_block_bitmap(p->fs_meta_blocks, blk)) { + p->bbcheck = 1; + if (fix_problem(ctx, PR_1_BB_FS_BLOCK, pctx)) { + *block_nr = 0; + return BLOCK_CHANGED; + } + } else if (ext2fs_test_block_bitmap(ctx->block_found_map, + blk)) { + p->bbcheck = 1; + if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, + pctx)) { + *block_nr = 0; + return BLOCK_CHANGED; + } if (ctx->flags & E2F_FLAG_SIGNAL_MASK) return BLOCK_ABORT; } else @@ -1671,8 +1686,13 @@ static int process_bad_block(ext2_filsys fs, * is using a bad block. */ if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) || - p->inode->i_block[EXT2_DIND_BLOCK]) { - bad_block_indirect(ctx, blk); + (blk == p->inode->i_block[EXT2_DIND_BLOCK]) || + (blk == p->inode->i_block[EXT2_TIND_BLOCK])) { + p->bbcheck = 1; + if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, pctx)) { + *block_nr = 0; + return BLOCK_CHANGED; + } if (ctx->flags & E2F_FLAG_SIGNAL_MASK) return BLOCK_ABORT; return 0; diff --git a/e2fsck/problem.c b/e2fsck/problem.c index cc50bf12..a164bb52 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -422,15 +422,14 @@ static const struct e2fsck_problem problem_table[] = { /* Bad block used as bad block indirect block */ { PR_1_BBINODE_BAD_METABLOCK, - N_("Bad @b %b used as bad @b indirect @b?!?\n"), - PROMPT_NONE, PR_AFTER_CODE, PR_1_BBINODE_BAD_METABLOCK_PROMPT }, + N_("Bad @b %b used as bad @b @i indirect @b. "), + PROMPT_CLEAR, PR_LATCH_BBLOCK }, /* Inconsistency can't be fixed prompt */ { PR_1_BBINODE_BAD_METABLOCK_PROMPT, - N_("\nThis inconsistency can not be fixed with e2fsck; to fix it, use\n" - """dumpe2fs -b"" to dump out the bad @b " - "list and ""e2fsck -L filename""\n" - "to read it back in again.\n"), + N_("\nThe bad @b @i has probably been corrupted. You probably\n" + "should stop now and run ""e2fsck -c"" to scan for bad blocks\n" + "in the @f.\n"), PROMPT_CONTINUE, PR_PREEN_NOMSG }, /* Bad primary block */ @@ -703,6 +702,12 @@ static const struct e2fsck_problem problem_table[] = { N_("@h %i has a tree depth (%N) which is too big\n"), PROMPT_CLEAR_HTREE, PR_PREEN_OK }, + /* Bad block has indirect block that conflicts with filesystem block */ + { PR_1_BB_FS_BLOCK, + N_("Bad @b @i has an indirect @b (%b) that conflicts with\n" + "@f metadata. "), + PROMPT_CLEAR, PR_LATCH_BBLOCK }, + /* Pass 1b errors */ /* Pass 1B: Rescan for duplicate/bad blocks */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index b8e6c132..8e2e1405 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -407,6 +407,9 @@ struct problem_context { /* HTREE too deep */ #define PR_1_HTREE_DEPTH 0x01004C +/* Bad block has indirect block that conflicts with filesystem block */ +#define PR_1_BB_FS_BLOCK 0x01004D + /* * Pass 1b errors */ -- 2.11.0