]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
e2fsck: Handle a pass 2 "should never happen" error gracefully
authorTheodore Ts'o <tytso@mit.edu>
Wed, 12 Mar 2008 20:10:48 +0000 (16:10 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Wed, 12 Mar 2008 20:10:48 +0000 (16:10 -0400)
Turns out a "should never happen" error can indeed happen very easily
if a directory with an htree index has an incorrect, and too-large,
i_size field.  This patch fixes this so that we handle this situation
gracefully, allowing filesystems with this error to be fixed.

In another patch I will clean up the specific problem which caused the
internal "should never happen" error from happening at all, but patch
will prevent e2fsck from crashing, and prompt the user to remove the
htree index, so it can be rebuilt again after pass 3.

Thanks to Bas van Schaik at Tetra for giving me access to his system
so this problem could be debugged.

Addresses-Launchpad-Bug: #129395

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
e2fsck/pass2.c
e2fsck/problem.c
e2fsck/problem.h

index 6fb2ed79e985aee645d225a8b7bf9912b406c642..b79461ddfa7775c62bd2106b26e06c69c7ea35ef 100644 (file)
@@ -783,8 +783,14 @@ static int check_dir_block(ext2_filsys fs,
        dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
        if (dx_dir && dx_dir->numblocks) {
                if (db->blockcnt >= dx_dir->numblocks) {
-                       printf("XXX should never happen!!!\n");
-                       abort();
+                       if (fix_problem(ctx, PR_2_UNEXPECTED_HTREE_BLOCK, 
+                                       &pctx)) {
+                               clear_htree(ctx, ino);
+                               dx_dir->numblocks = 0;
+                               dx_db = 0;
+                               goto out_htree;
+                       }
+                       fatal_error(ctx, _("Can not continue."));
                }
                dx_db = &dx_dir->dx_block[db->blockcnt];
                dx_db->type = DX_DIRBLOCK_LEAF;
@@ -819,6 +825,7 @@ static int check_dir_block(ext2_filsys fs,
                             sizeof(struct ext2_dx_entry))))
                        dx_db->type = DX_DIRBLOCK_NODE;
        }
+out_htree:
 #endif /* ENABLE_HTREE */
 
        dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
index 7c3ebea9bd3c94d9d1db1e2f3c24e6f4b1ce31e4..418d83b4d37aa7cff28ca513938603c322e858fc 100644 (file)
@@ -1188,6 +1188,10 @@ static struct e2fsck_problem problem_table[] = {
          N_("i_blocks_hi @F %N, @s zero.\n"),
          PROMPT_CLEAR, 0 },
 
+       /* Unexpected HTREE block */
+       { PR_2_UNEXPECTED_HTREE_BLOCK,
+         N_("Unexpected @b in @h %d (%q).\n"), PROMPT_CLEAR_HTREE, 0 },
+                 
        /* Pass 3 errors */
 
        /* Pass 3: Checking directory connectivity */
index f5f7212fd61bcba4ae32f631276da9fbf366dd67..91a6148e6efbe64290b10d4dc27fb259d88885d6 100644 (file)
@@ -708,6 +708,9 @@ struct problem_context {
 /* i_blocks_hi should be zero */
 #define PR_2_BLOCKS_HI_ZERO    0x020044
 
+/* Unexpected HTREE block */
+#define PR_2_UNEXPECTED_HTREE_BLOCK    0x020045
+
 /*
  * Pass 3 errors
  */