OSDN Git Service

pass1.c (e2fsck_pass1), problem.h (PR_1_BB_FS_BLOCK),
authorTheodore Ts'o <tytso@mit.edu>
Fri, 21 Nov 2003 15:41:58 +0000 (10:41 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Fri, 21 Nov 2003 15:41:58 +0000 (10:41 -0500)
  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
e2fsck/pass1.c
e2fsck/problem.c
e2fsck/problem.h

index d39d458..094555a 100644 (file)
@@ -1,3 +1,14 @@
+2003-09-13  Theodore Ts'o  <tytso@mit.edu>
+
+       * 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  <tytso@mit.edu>
 
        * unix.c (PRS): Check the returned name from blkid_get_devname and
index 992d91d..58edd0a 100644 (file)
@@ -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;
index cc50bf1..a164bb5 100644 (file)
@@ -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 */
index b8e6c13..8e2e140 100644 (file)
@@ -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
  */