diff options
author | Li Dongyang <dongyangli@ddn.com> | 2022-12-20 00:05:44 +1100 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2023-01-25 21:38:33 -0500 |
commit | 6cae615a47dfe37fe5fd096accb82579813a6366 (patch) | |
tree | a11db3ecae927a117eb47827c009449c5ebaa809 /e2fsck | |
parent | f7c9598655420102353ff87946f5bf77ebf465bc (diff) | |
download | e2fsprogs-6cae615a47dfe37fe5fd096accb82579813a6366.tar.gz |
e2fsck: optimize clone_file on large devices
When cloning multiply-claimed blocks for an inode,
clone_file() uses ext2fs_block_iterate3() to iterate
every block calling clone_file_block().
clone_file_block() calls check_if_fs_cluster(), even
the block is not on the block_dup_map, which could take
a long time on a large device.
Only check if it's metadata block when we need to clone
it.
Test block_metadata_map in check_if_fs_block()
and check_if_fs_cluster(), so we don't need to go over
each bg every time. The metadata blocks are already
marked in the bitmap.
Before this patch on a 500TB device with 3 files having
3 multiply-claimed blocks between them, pass1b is stuck
for more than 48 hours without progressing,
before e2fsck was terminated.
After this patch pass1b could finish in 180 seconds.
Signed-off-by: Li Dongyang <dongyangli@ddn.com>
Reviewed-by: Andreas Dilger <adilger@dilger.ca>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'e2fsck')
-rw-r--r-- | e2fsck/pass1b.c | 73 |
1 files changed, 11 insertions, 62 deletions
diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c index 92c746c1d..950af5be0 100644 --- a/e2fsck/pass1b.c +++ b/e2fsck/pass1b.c @@ -90,7 +90,7 @@ static void delete_file(e2fsck_t ctx, ext2_ino_t ino, struct dup_inode *dp, char *block_buf); static errcode_t clone_file(e2fsck_t ctx, ext2_ino_t ino, struct dup_inode *dp, char* block_buf); -static int check_if_fs_block(e2fsck_t ctx, blk64_t test_block); +static int check_if_fs_block(e2fsck_t ctx, blk64_t block); static int check_if_fs_cluster(e2fsck_t ctx, blk64_t cluster); static void pass1b(e2fsck_t ctx, char *block_buf); @@ -815,8 +815,6 @@ static int clone_file_block(ext2_filsys fs, should_write = 0; c = EXT2FS_B2C(fs, blockcnt); - if (check_if_fs_cluster(ctx, EXT2FS_B2C(fs, *block_nr))) - is_meta = 1; if (c == cs->dup_cluster && cs->alloc_block) { new_block = cs->alloc_block; @@ -894,6 +892,8 @@ cluster_alloc_ok: return BLOCK_ABORT; } } + if (check_if_fs_cluster(ctx, EXT2FS_B2C(fs, *block_nr))) + is_meta = 1; cs->save_dup_cluster = (is_meta ? NULL : p); cs->save_blocknr = *block_nr; *block_nr = new_block; @@ -1021,37 +1021,9 @@ errout: * This routine returns 1 if a block overlaps with one of the superblocks, * group descriptors, inode bitmaps, or block bitmaps. */ -static int check_if_fs_block(e2fsck_t ctx, blk64_t test_block) +static int check_if_fs_block(e2fsck_t ctx, blk64_t block) { - ext2_filsys fs = ctx->fs; - blk64_t first_block; - dgrp_t i; - - first_block = fs->super->s_first_data_block; - for (i = 0; i < fs->group_desc_count; i++) { - - /* Check superblocks/block group descriptors */ - if (ext2fs_bg_has_super(fs, i)) { - if (test_block >= first_block && - (test_block <= first_block + fs->desc_blocks)) - return 1; - } - - /* Check the inode table */ - if ((ext2fs_inode_table_loc(fs, i)) && - (test_block >= ext2fs_inode_table_loc(fs, i)) && - (test_block < (ext2fs_inode_table_loc(fs, i) + - fs->inode_blocks_per_group))) - return 1; - - /* Check the bitmap blocks */ - if ((test_block == ext2fs_block_bitmap_loc(fs, i)) || - (test_block == ext2fs_inode_bitmap_loc(fs, i))) - return 1; - - first_block += fs->super->s_blocks_per_group; - } - return 0; + return ext2fs_test_block_bitmap2(ctx->block_metadata_map, block); } /* @@ -1061,37 +1033,14 @@ static int check_if_fs_block(e2fsck_t ctx, blk64_t test_block) static int check_if_fs_cluster(e2fsck_t ctx, blk64_t cluster) { ext2_filsys fs = ctx->fs; - blk64_t first_block; - dgrp_t i; - - first_block = fs->super->s_first_data_block; - for (i = 0; i < fs->group_desc_count; i++) { - - /* Check superblocks/block group descriptors */ - if (ext2fs_bg_has_super(fs, i)) { - if (cluster >= EXT2FS_B2C(fs, first_block) && - (cluster <= EXT2FS_B2C(fs, first_block + - fs->desc_blocks))) - return 1; - } + blk64_t block = EXT2FS_C2B(fs, cluster); + int i; - /* Check the inode table */ - if ((ext2fs_inode_table_loc(fs, i)) && - (cluster >= EXT2FS_B2C(fs, - ext2fs_inode_table_loc(fs, i))) && - (cluster <= EXT2FS_B2C(fs, - ext2fs_inode_table_loc(fs, i) + - fs->inode_blocks_per_group - 1))) + for (i = 0; i < EXT2FS_CLUSTER_RATIO(fs); i++) { + if (ext2fs_test_block_bitmap2(ctx->block_metadata_map, + block + i)) return 1; - - /* Check the bitmap blocks */ - if ((cluster == EXT2FS_B2C(fs, - ext2fs_block_bitmap_loc(fs, i))) || - (cluster == EXT2FS_B2C(fs, - ext2fs_inode_bitmap_loc(fs, i)))) - return 1; - - first_block += fs->super->s_blocks_per_group; } + return 0; } |