diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2014-08-02 22:32:11 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2014-08-02 22:32:11 -0400 |
commit | 49fed79e7c23783832df3bb137d2db4607fa98a7 (patch) | |
tree | 13b2206d9919449faf0037baa355bae98c6af10c /e2fsck/pass1.c | |
parent | 5b9cbd76df1e96f927acee0910456319b1a99d53 (diff) | |
download | android_external_e2fsprogs-49fed79e7c23783832df3bb137d2db4607fa98a7.tar.gz android_external_e2fsprogs-49fed79e7c23783832df3bb137d2db4607fa98a7.tar.bz2 android_external_e2fsprogs-49fed79e7c23783832df3bb137d2db4607fa98a7.zip |
e2fsck: try to salvage extent blocks with bad checksums
Remove the code that would zap an extent block immediately if the
checksum failed (i.e. strict_csums). Instead, we'll only do that if
the extent block header shows obvious structural problems; if the
header checks out, then we'll iterate the block and see if we can
recover some extents.
Requires a minor modification to ext2fs_extent_get such that the
extent block will be returned in the buffer even if the return code
indicates a checksum error. This brings its behavior in line with
the rest of libext2fs.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'e2fsck/pass1.c')
-rw-r--r-- | e2fsck/pass1.c | 45 |
1 files changed, 19 insertions, 26 deletions
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 02683d32..283b0b1e 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -2001,7 +2001,10 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, int is_dir, is_leaf; problem_t problem; struct ext2_extent_info info; - int failed_csum; + int failed_csum = 0; + + if (pctx->errcode == EXT2_ET_EXTENT_CSUM_INVALID) + failed_csum = 1; pctx->errcode = ext2fs_extent_get_info(ehandle, &info); if (pctx->errcode) @@ -2012,7 +2015,6 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, while ((pctx->errcode == 0 || pctx->errcode == EXT2_ET_EXTENT_CSUM_INVALID) && info.num_entries-- > 0) { - failed_csum = 0; is_leaf = extent.e_flags & EXT2_EXTENT_FLAGS_LEAF; is_dir = LINUX_S_ISDIR(pctx->inode->i_mode); last_lblk = extent.e_lblk + extent.e_len - 1; @@ -2023,15 +2025,6 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, pctx->num = extent.e_len; pctx->blkcount = extent.e_lblk + extent.e_len; - /* Ask to clear a corrupt extent block */ - if (try_repairs && - pctx->errcode == EXT2_ET_EXTENT_CSUM_INVALID) { - problem = PR_1_EXTENT_CSUM_INVALID; - if (fix_problem(ctx, problem, pctx)) - goto fix_problem_now; - failed_csum = 1; - } - if (extent.e_pblk == 0 || extent.e_pblk < ctx->fs->super->s_first_data_block || extent.e_pblk >= ext2fs_blocks_count(ctx->fs->super)) @@ -2069,16 +2062,6 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, failed_csum = 0; } - /* Failed csum but passes checks? Ask to fix checksum. */ - if (try_repairs && failed_csum && problem == 0 && - fix_problem(ctx, PR_1_EXTENT_ONLY_CSUM_INVALID, pctx)) { - pb->inode_modified = 1; - pctx->errcode = ext2fs_extent_replace(ehandle, - 0, &extent); - if (pctx->errcode) - return; - } - if (try_repairs && problem) { report_problem: if (fix_problem(ctx, problem, pctx)) { @@ -2124,6 +2107,7 @@ fix_problem_now: pctx->errcode = 0; break; } + failed_csum = 0; continue; } goto next; @@ -2152,15 +2136,13 @@ fix_problem_now: } pctx->errcode = ext2fs_extent_get(ehandle, EXT2_EXTENT_DOWN, &extent); - if (pctx->errcode) { + if (pctx->errcode && + pctx->errcode != EXT2_ET_EXTENT_CSUM_INVALID) { pctx->str = "EXT2_EXTENT_DOWN"; problem = PR_1_EXTENT_HEADER_INVALID; if (!next_try_repairs) return; - if (pctx->errcode == - EXT2_ET_EXTENT_HEADER_BAD || - pctx->errcode == - EXT2_ET_EXTENT_CSUM_INVALID) + if (pctx->errcode == EXT2_ET_EXTENT_HEADER_BAD) goto report_problem; return; } @@ -2256,6 +2238,7 @@ fix_problem_now: if (pctx->errcode) goto failed_add_dir_block; last_lblk = extent.e_lblk + extent.e_len - 1; + failed_csum = 0; } } alloc_later: @@ -2323,6 +2306,16 @@ alloc_later: EXT2_EXTENT_NEXT_SIB, &extent); } + + /* Failed csum but passes checks? Ask to fix checksum. */ + if (failed_csum && + fix_problem(ctx, PR_1_EXTENT_ONLY_CSUM_INVALID, pctx)) { + pb->inode_modified = 1; + pctx->errcode = ext2fs_extent_replace(ehandle, 0, &extent); + if (pctx->errcode) + return; + } + if (pctx->errcode == EXT2_ET_EXTENT_NO_NEXT) pctx->errcode = 0; } |