Detect mismatches of the inode and checksum, and prompt the user to fix the situation. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- e2fsck/pass1.c | 43 +++++++++++++++++++++++++++++++++++++++++++ e2fsck/problem.c | 15 +++++++++++++++ e2fsck/problem.h | 9 +++++++++ 3 files changed, 67 insertions(+), 0 deletions(-) diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index d051703..96f87e8 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -540,6 +540,41 @@ extern void e2fsck_setup_tdb_icount(e2fsck_t ctx, int flags, *ret = 0; } +static int validate_inode_checksum(ext2_filsys fs, + e2fsck_t ctx, + struct problem_context *pctx, + ext2_ino_t ino, + struct ext2_inode *inode) +{ + struct ext2_inode_large *linode = (struct ext2_inode_large *)inode; + + /* Ignore non-Linux filesystems */ + if (fs->super->s_creator_os != EXT2_OS_LINUX) + return 0; + + /* Check for invalid inode checksum */ + if (ext2fs_inode_csum_verify(fs, ino, linode)) + return 0; + + /* + * TODO: Change the following check to use the inode badness patch. + * For the moment we'll just assume that the user wants to clear the + * bad inode. + */ + if (fix_problem(ctx, PR_1_INODE_CORRUPT, pctx)) { + e2fsck_clear_inode(ctx, ino, inode, 0, "pass1"); + if (ino == EXT2_BAD_INO) + ext2fs_mark_inode_bitmap2(ctx->inode_used_map, + ino); + return PR_1_INODE_CORRUPT; + } else if (fix_problem(ctx, PR_1_INODE_CSUM_INVALID, pctx)) { + e2fsck_write_inode(ctx, ino, inode, "pass1"); + return PR_1_INODE_CSUM_INVALID; + } + + return 0; +} + void e2fsck_pass1(e2fsck_t ctx) { int i; @@ -717,8 +752,10 @@ void e2fsck_pass1(e2fsck_t ctx) fatal_error(ctx, 0); } old_op = ehandler_operation(_("getting next inode from scan")); + ctx->fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS; pctx.errcode = ext2fs_get_next_inode_full(scan, &ino, inode, inode_size); + ctx->fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS; ehandler_operation(old_op); if (ctx->flags & E2F_FLAG_SIGNAL_MASK) return; @@ -750,6 +787,12 @@ void e2fsck_pass1(e2fsck_t ctx) } } + check_inode_extra_space(ctx, &pctx); + /* Validate inode checksum. i_extra_isize must be sane. */ + if (validate_inode_checksum(fs, ctx, &pctx, ino, inode) == + PR_1_INODE_CORRUPT) + continue; + /* * Test for incorrect extent flag settings. * diff --git a/e2fsck/problem.c b/e2fsck/problem.c index 6ee3fa4..86cd954 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -934,6 +934,21 @@ static struct e2fsck_problem problem_table[] = { /* Quota inode is user visible */ { PR_1_QUOTA_INODE_NOT_HIDDEN, N_("@q @i is visible to the user. "), + PROMPT_FIX, PR_PREEN_OK }, + + /* inode checksum probably not set */ + { PR_1_INODE_CSUM_INVALID, + N_("@i %i checksum incorrect. "), + PROMPT_FIX, PR_PREEN_OK }, + + /* inode checksum probably set, but does not match */ + { PR_1_INODE_CORRUPT, + N_("@i %i checksum shows corruption. "), + PROMPT_CLEAR, PR_PREEN_OK }, + + /* inode checksumming disabled, yet checksum is probably set? */ + { PR_1_INODE_CSUM_NONZERO, + N_("@i %i checksum should not be set. "), PROMPT_CLEAR, PR_PREEN_OK }, /* Invalid bad inode */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index 9db29d8..e1c7f26 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -550,6 +550,15 @@ struct problem_context { /* Invalid bad inode */ #define PR_1_INVALID_BAD_INODE 0x010065 +/* inode checksum probably not set */ +#define PR_1_INODE_CSUM_INVALID 0x010066 + +/* inode checksum probably set, but does not match */ +#define PR_1_INODE_CORRUPT 0x010067 + +/* inode checksum should not be set */ +#define PR_1_INODE_CSUM_NONZERO 0x010068 + /* * Pass 1b errors */ -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html