summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2008-03-12 16:10:48 -0400
committerTheodore Ts'o <tytso@mit.edu>2008-03-12 16:10:48 -0400
commitd45edec0fb2e5d100d122fdda0914560c64def44 (patch)
tree934ff33948526d3ad67c6880daa9be05a7ea2924
parent46d9a7462b7e796fb34c09c02e635ab77012c2bb (diff)
downloade2fsprogs-d45edec0fb2e5d100d122fdda0914560c64def44.tar.gz
e2fsck: Handle a pass 2 "should never happen" error gracefully
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>
-rw-r--r--e2fsck/pass2.c11
-rw-r--r--e2fsck/problem.c4
-rw-r--r--e2fsck/problem.h3
3 files changed, 16 insertions, 2 deletions
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index 6fb2ed79..b79461dd 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -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);
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index 7c3ebea9..418d83b4 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -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 */
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index f5f7212f..91a6148e 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -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
*/