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 <tahsin@google.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
Tahsin Erdogan 2017-04-14 23:24:36 -07:00 committed by Theodore Ts'o
parent ed1e950f84
commit d5d981a369
4 changed files with 74 additions and 56 deletions

View File

@ -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 */

View File

@ -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);
}
pb->last_block = blockcnt;
pb->previous_block = blk;
if (is_dir) {
pctx->errcode = ext2fs_add_dir_block2(ctx->fs->dblist, pctx->ino, blk, blockcnt);
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 = blk;
pctx->num = blockcnt;
pctx->blk = 0;
pctx->num = pb->last_db_block;
goto failed_add_dir_block;
}
}
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 = 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 (is_dir && extent.e_len > 0)
pb->last_db_block = blockcnt - 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;
}
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 &&

View File

@ -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);

View File

@ -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