Check block bitmap checksum and write a new checksum if the verification fails. This is ok because e2fsck has already computed the correct block bitmap. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- e2fsck/pass5.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ e2fsck/problem.c | 5 +++++ e2fsck/problem.h | 3 +++ 3 files changed, 68 insertions(+), 0 deletions(-) diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c index a0cc564..63b7e99 100644 --- a/e2fsck/pass5.c +++ b/e2fsck/pass5.c @@ -27,6 +27,7 @@ static void check_inode_bitmaps(e2fsck_t ctx); static void check_inode_end(e2fsck_t ctx); static void check_block_end(e2fsck_t ctx); static void check_inode_bitmap_checksum(e2fsck_t ctx); +static void check_block_bitmap_checksum(e2fsck_t ctx); void e2fsck_pass5(e2fsck_t ctx) { @@ -67,6 +68,7 @@ void e2fsck_pass5(e2fsck_t ctx) return; check_inode_bitmap_checksum(ctx); + check_block_bitmap_checksum(ctx); ext2fs_free_inode_bitmap(ctx->inode_used_map); ctx->inode_used_map = 0; @@ -134,6 +136,64 @@ static void check_inode_bitmap_checksum(e2fsck_t ctx) ext2fs_free_mem(&buf); } +static void check_block_bitmap_checksum(e2fsck_t ctx) +{ + struct problem_context pctx; + struct ext4_group_desc *gdp; + char *buf; + dgrp_t i; + int nbytes; + blk64_t blk_itr; + errcode_t retval; + int csum_flag = 0; + + /* If bitmap is dirty from being fixed, checksum will be corrected */ + if (ext2fs_test_bb_dirty(ctx->fs)) + return; + + nbytes = (size_t)((EXT2_BLOCKS_PER_GROUP(ctx->fs->super) + 7) / 8); + retval = ext2fs_get_memalign(ctx->fs->blocksize, ctx->fs->blocksize, + &buf); + if (retval) + return; + + if (EXT2_HAS_RO_COMPAT_FEATURE(ctx->fs->super, + EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) + csum_flag = 1; + + clear_problem_context(&pctx); + for (i = 0; i < ctx->fs->group_desc_count; i++) { + if (csum_flag && ext2fs_bg_flags_test(ctx->fs, i, + EXT2_BG_BLOCK_UNINIT)) + continue; + + blk_itr = EXT2FS_B2C(ctx->fs, + ctx->fs->super->s_first_data_block) + + (i * (nbytes << 3)); + gdp = (struct ext4_group_desc *)ext2fs_group_desc(ctx->fs, + ctx->fs->group_desc, i); + retval = ext2fs_get_block_bitmap_range2(ctx->fs->block_map, + blk_itr, nbytes << 3, + buf); + if (retval) + break; + + if (ext2fs_bitmap_csum_verify(ctx->fs, i, + gdp->bg_block_bitmap_csum, buf, + nbytes)) + continue; + pctx.group = i; + if (!fix_problem(ctx, PR_5_BLOCK_BITMAP_CSUM_INVALID, &pctx)) + continue; + + /* Fixing one checksum will rewrite all of them */ + ext2fs_mark_bb_dirty(ctx->fs); + break; + } + + ext2fs_free_mem(&buf); +} + static void e2fsck_discard_blocks(e2fsck_t ctx, io_manager manager, blk64_t start, blk64_t count) { diff --git a/e2fsck/problem.c b/e2fsck/problem.c index 35a8055..9629b9e 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -1664,6 +1664,11 @@ static struct e2fsck_problem problem_table[] = { N_("@g %g @i bitmap does not match checksum\n"), PROMPT_FIX, PR_LATCH_IBITMAP | PR_PREEN_OK }, + /* Group N block bitmap does not match checksum */ + { PR_5_BLOCK_BITMAP_CSUM_INVALID, + N_("@g %g @b bitmap does not match checksum\n"), + PROMPT_FIX, PR_LATCH_BBITMAP | PR_PREEN_OK }, + /* Post-Pass 5 errors */ /* Recreate journal if E2F_FLAG_JOURNAL_INODE flag is set */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index 9766113..8cc461b 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -1004,6 +1004,9 @@ struct problem_context { /* Inode bitmap checksum does not match */ #define PR_5_INODE_BITMAP_CSUM_INVALID 0x05001A +/* Block bitmap checksum does not match */ +#define PR_5_BLOCK_BITMAP_CSUM_INVALID 0x05001B + /* * Post-Pass 5 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