From: Tahsin Erdogan Date: Sat, 15 Apr 2017 06:24:36 +0000 (-0700) Subject: e2fsck: eliminate per-block cluster alignment check X-Git-Tag: v1.44.0-rc1~115 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d5d981a369924311b91f437439a4ff4d1d7062b2;p=thirdparty%2Fe2fsprogs.git 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 --- diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h index 1b6c5065e..fd12024c2 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 40ffd8dd5..422a3d699 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 fb55b7e66..ab7364960 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 75a38209e..b44e65d00 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