aboutsummaryrefslogtreecommitdiffstats
path: root/e2fsck/pass1.c
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2014-08-02 22:32:11 -0400
committerTheodore Ts'o <tytso@mit.edu>2014-08-02 22:32:11 -0400
commit49fed79e7c23783832df3bb137d2db4607fa98a7 (patch)
tree13b2206d9919449faf0037baa355bae98c6af10c /e2fsck/pass1.c
parent5b9cbd76df1e96f927acee0910456319b1a99d53 (diff)
downloadandroid_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.c45
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;
}