From d5d981a369924311b91f437439a4ff4d1d7062b2 Mon Sep 17 00:00:00 2001 From: Tahsin Erdogan Date: Fri, 14 Apr 2017 23:24:36 -0700 Subject: [PATCH] e2fsck: eliminate per-block cluster alignment check scan_extent_node() did cluster alignment check for every block in an extent. This is unnecessary and significantly slows down the runtime when hugefile is used with bigalloc. Do cluster alignment check once for each extent. Google-Bug-Id: 36886699 Signed-off-by: Tahsin Erdogan Signed-off-by: Theodore Ts'o --- e2fsck/e2fsck.h | 3 ++ e2fsck/pass1.c | 117 +++++++++++++++++++++++++++------------------- e2fsck/pass5.c | 2 - tests/f_badcluster/expect | 4 -- 4 files changed, 72 insertions(+), 54 deletions(-) diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h index 1b6c506..fd12024 100644 --- a/e2fsck/e2fsck.h +++ b/e2fsck/e2fsck.h @@ -648,4 +648,7 @@ unsigned long long get_memory_size(void); extern void e2fsck_clear_progbar(e2fsck_t ctx); extern int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent, unsigned int dpynum); + +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) + #endif /* _E2FSCK_H */ diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 40ffd8d..422a3d6 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -2155,14 +2155,20 @@ static _INLINE_ void mark_block_used(e2fsck_t ctx, blk64_t block) } } +/* + * When cluster size is greater than one block, it is caller's responsibility + * to make sure block parameter starts at a cluster boundary. + */ static _INLINE_ void mark_blocks_used(e2fsck_t ctx, blk64_t block, unsigned int num) { if (ext2fs_test_block_bitmap_range2(ctx->block_found_map, block, num)) ext2fs_mark_block_bitmap_range2(ctx->block_found_map, block, num); - else - while (num--) - mark_block_used(ctx, block++); + else { + int i; + for (i = 0; i < num; i += EXT2FS_CLUSTER_RATIO(ctx->fs)) + mark_block_used(ctx, block + i); + } } /* @@ -2562,8 +2568,7 @@ static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, { struct ext2fs_extent extent; blk64_t blk, last_lblk; - e2_blkcnt_t blockcnt; - unsigned int i; + unsigned int i, n; int is_dir, is_leaf; problem_t problem; struct ext2_extent_info info; @@ -2828,50 +2833,29 @@ report_problem: } } alloc_later: - while (is_dir && (++pb->last_db_block < - (e2_blkcnt_t) extent.e_lblk)) { - pctx->errcode = ext2fs_add_dir_block2(ctx->fs->dblist, - pb->ino, 0, - pb->last_db_block); - if (pctx->errcode) { - pctx->blk = 0; - pctx->num = pb->last_db_block; - goto failed_add_dir_block; - } - } - if (!ctx->fs->cluster_ratio_bits) { - mark_blocks_used(ctx, extent.e_pblk, extent.e_len); - pb->num_blocks += extent.e_len; - } - for (blk = extent.e_pblk, blockcnt = extent.e_lblk, i = 0; - i < extent.e_len; - blk++, blockcnt++, i++) { - if (ctx->fs->cluster_ratio_bits && - !(pb->previous_block && - (EXT2FS_B2C(ctx->fs, blk) == - EXT2FS_B2C(ctx->fs, pb->previous_block)) && - (blk & EXT2FS_CLUSTER_MASK(ctx->fs)) == - ((unsigned) blockcnt & EXT2FS_CLUSTER_MASK(ctx->fs)))) { - mark_block_used(ctx, blk); - pb->num_blocks++; - } - if (has_unaligned_cluster_map(ctx, pb->previous_block, - pb->last_block, blk, - blockcnt)) { - pctx->blk = blockcnt; - pctx->blk2 = blk; - fix_problem(ctx, PR_1_MISALIGNED_CLUSTER, pctx); - mark_block_used(ctx, blk); - mark_block_used(ctx, blk); + if (is_dir) { + while (++pb->last_db_block < + (e2_blkcnt_t) extent.e_lblk) { + pctx->errcode = ext2fs_add_dir_block2( + ctx->fs->dblist, + pb->ino, 0, + pb->last_db_block); + if (pctx->errcode) { + pctx->blk = 0; + pctx->num = pb->last_db_block; + goto failed_add_dir_block; + } } - pb->last_block = blockcnt; - pb->previous_block = blk; - if (is_dir) { - pctx->errcode = ext2fs_add_dir_block2(ctx->fs->dblist, pctx->ino, blk, blockcnt); + for (i = 0; i < extent.e_len; i++) { + pctx->errcode = ext2fs_add_dir_block2( + ctx->fs->dblist, + pctx->ino, + extent.e_pblk + i, + extent.e_lblk + i); if (pctx->errcode) { - pctx->blk = blk; - pctx->num = blockcnt; + pctx->blk = extent.e_pblk + i; + pctx->num = extent.e_lblk + i; failed_add_dir_block: fix_problem(ctx, PR_1_ADD_DBLOCK, pctx); /* Should never get here */ @@ -2879,9 +2863,46 @@ alloc_later: return; } } + if (extent.e_len > 0) + pb->last_db_block = extent.e_lblk + extent.e_len - 1; + } + if (has_unaligned_cluster_map(ctx, pb->previous_block, + pb->last_block, + extent.e_pblk, + extent.e_lblk)) { + for (i = 0; i < extent.e_len; i++) { + pctx->blk = extent.e_lblk + i; + pctx->blk2 = extent.e_pblk + i; + fix_problem(ctx, PR_1_MISALIGNED_CLUSTER, pctx); + mark_block_used(ctx, extent.e_pblk + i); + mark_block_used(ctx, extent.e_pblk + i); + } + } + + /* + * Check whether first cluster got marked in previous iteration. + */ + if (ctx->fs->cluster_ratio_bits && + pb->previous_block && + (EXT2FS_B2C(ctx->fs, extent.e_pblk) == + EXT2FS_B2C(ctx->fs, pb->previous_block))) + /* Set blk to the beginning of next cluster. */ + blk = EXT2FS_C2B( + ctx->fs, + EXT2FS_B2C(ctx->fs, extent.e_pblk) + 1); + else + /* Set blk to the beginning of current cluster. */ + blk = EXT2FS_C2B(ctx->fs, + EXT2FS_B2C(ctx->fs, extent.e_pblk)); + + if (blk < extent.e_pblk + extent.e_len) { + mark_blocks_used(ctx, blk, + extent.e_pblk + extent.e_len - blk); + n = DIV_ROUND_UP(extent.e_pblk + extent.e_len - blk, + EXT2FS_CLUSTER_RATIO(ctx->fs)); + pb->num_blocks += n; } - if (is_dir && extent.e_len > 0) - pb->last_db_block = blockcnt - 1; + pb->last_block = extent.e_lblk + extent.e_len - 1; pb->previous_block = extent.e_pblk + extent.e_len - 1; start_block = pb->last_block = last_lblk; if (is_leaf && !is_dir && diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c index fb55b7e..ab73649 100644 --- a/e2fsck/pass5.c +++ b/e2fsck/pass5.c @@ -21,8 +21,6 @@ #include "e2fsck.h" #include "problem.h" -#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) - static void check_block_bitmaps(e2fsck_t ctx); static void check_inode_bitmaps(e2fsck_t ctx); static void check_inode_end(e2fsck_t ctx); diff --git a/tests/f_badcluster/expect b/tests/f_badcluster/expect index 75a3820..b44e65d 100644 --- a/tests/f_badcluster/expect +++ b/tests/f_badcluster/expect @@ -13,8 +13,6 @@ Inode 17 logical block 0 (physical block 1186) violates cluster allocation rules Will fix in pass 1B. Inode 17 logical block 2 (physical block 1184) violates cluster allocation rules. Will fix in pass 1B. -Inode 17, i_blocks is 32, should be 64. Fix? yes - Inode 18 logical block 3 (physical block 1201) violates cluster allocation rules. Will fix in pass 1B. Inode 18, i_blocks is 32, should be 64. Fix? yes @@ -86,8 +84,6 @@ Inode 12, i_blocks is 64, should be 32. Fix? yes Inode 16, i_blocks is 64, should be 32. Fix? yes -Inode 17, i_blocks is 64, should be 32. Fix? yes - Inode 18, i_blocks is 64, should be 32. Fix? yes Pass 2: Checking directory structure -- 1.8.3.1