From: Wang Shilong Date: Wed, 23 Sep 2020 03:17:29 +0000 (+0800) Subject: e2fsck: merge bitmaps after thread completes X-Git-Tag: v1.46.6-wc1~79 X-Git-Url: https://git.whamcloud.com/tools/e2fsprogs.git/?a=commitdiff_plain;h=44d62329518e011ada2b00bc7b73de4f5100a98c;p=tools%2Fe2fsprogs.git e2fsck: merge bitmaps after thread completes A new method merge_bmap has been added to bitmap operations. But only red-black bitmap has that operation now. E2fsprogs-commit: ecf85fb474fb7537f14bddd8f85d8372b808d5e9 Change-Id: Id5c387dd813d633adff3afb9208213086c33b6d2 Signed-off-by: Li Xi Signed-off-by: Wang Shilong Reviewed-by: Andreas Dilger Signed-off-by: Theodore Ts'o --- diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c index 22b7509..b8e3a7d 100644 --- a/e2fsck/pass1.c +++ b/e2fsck/pass1.c @@ -2161,12 +2161,38 @@ static errcode_t e2fsck_pass1_copy_bitmap(ext2_filsys fs, ext2fs_generic_bitmap return ret; (*dest)->fs = fs; - ext2fs_free_generic_bmap(*src); - *src = NULL; return 0; } +static void e2fsck_pass1_free_bitmap(ext2fs_generic_bitmap *bitmap) +{ + if (*bitmap) { + ext2fs_free_generic_bmap(*bitmap); + *bitmap = NULL; + } + +} + +static errcode_t e2fsck_pass1_merge_bitmap(ext2_filsys fs, ext2fs_generic_bitmap *src, + ext2fs_generic_bitmap *dest) +{ + errcode_t ret = 0; + + if (*src) { + if (*dest == NULL) { + *dest = *src; + *src = NULL; + } else { + ret = ext2fs_merge_bitmap(*src, *dest, NULL, NULL); + if (ret) + return ret; + } + (*dest)->fs = fs; + } + + return 0; +} static errcode_t e2fsck_pass1_copy_fs(ext2_filsys dest, e2fsck_t src_context, ext2_filsys src) @@ -2174,6 +2200,8 @@ static errcode_t e2fsck_pass1_copy_fs(ext2_filsys dest, e2fsck_t src_context, errcode_t retval; memcpy(dest, src, sizeof(struct struct_ext2_filsys)); + dest->inode_map = NULL; + dest->block_map = NULL; if (dest->dblist) dest->dblist->fs = dest; if (src->block_map) { @@ -2233,42 +2261,50 @@ static int e2fsck_pass1_merge_fs(ext2_filsys dest, ext2_filsys src) errcode_t retval = 0; io_channel dest_io; io_channel dest_image_io; + ext2fs_inode_bitmap inode_map; + ext2fs_block_bitmap block_map; dest_io = dest->io; dest_image_io = dest->image_io; + inode_map = dest->inode_map; + block_map = dest->block_map; memcpy(dest, src, sizeof(struct struct_ext2_filsys)); dest->io = dest_io; dest->image_io = dest_image_io; dest->icache = icache; + dest->inode_map = inode_map; + dest->block_map = block_map; if (dest->dblist) dest->dblist->fs = dest; - if (src->inode_map) { - retval = e2fsck_pass1_copy_bitmap(dest, &src->inode_map, - &dest->inode_map); - if (retval) - return retval; - } - if (src->block_map) { - retval = e2fsck_pass1_copy_bitmap(dest, &src->block_map, - &dest->block_map); - if (retval) - return retval; - } if (src->icache) { ext2fs_free_inode_cache(src->icache); src->icache = NULL; } + retval = e2fsck_pass1_merge_bitmap(dest, &src->inode_map, + &dest->inode_map); + if (retval) + goto out; + + retval = e2fsck_pass1_merge_bitmap(dest, &src->block_map, + &dest->block_map); + if (retval) + goto out; + if (src->badblocks) { retval = ext2fs_badblocks_copy(src->badblocks, &dest->badblocks); ext2fs_badblocks_list_free(src->badblocks); src->badblocks = NULL; } - +out: io_channel_close(src->io); + if (src->inode_map) + ext2fs_free_generic_bmap(src->inode_map); + if (src->block_map) + ext2fs_free_generic_bmap(src->block_map); return retval; } @@ -2358,6 +2394,18 @@ static int e2fsck_pass1_thread_join_one(e2fsck_t global_ctx, e2fsck_t thread_ctx ext2_filsys global_fs = global_ctx->fs; FILE *global_logf = global_ctx->logf; FILE *global_problem_logf = global_ctx->problem_logf; + ext2fs_inode_bitmap inode_bad_map = global_ctx->inode_bad_map; + ext2fs_inode_bitmap inode_used_map = global_ctx->inode_used_map; + ext2fs_inode_bitmap inode_dir_map = global_ctx->inode_dir_map; + ext2fs_inode_bitmap inode_bb_map = global_ctx->inode_bb_map; + ext2fs_inode_bitmap inode_imagic_map = global_ctx->inode_imagic_map; + ext2fs_inode_bitmap inode_reg_map = global_ctx->inode_reg_map; + ext2fs_block_bitmap block_found_map = global_ctx->block_found_map; + ext2fs_block_bitmap block_dup_map = global_ctx->block_dup_map; + ext2fs_block_bitmap block_ea_map = global_ctx->block_ea_map; + ext2fs_block_bitmap block_metadata_map = global_ctx->block_metadata_map; + ext2fs_block_bitmap inodes_to_rebuild = global_ctx->inodes_to_rebuild; + #ifdef HAVE_SETJMP_H jmp_buf old_jmp; @@ -2367,6 +2415,19 @@ static int e2fsck_pass1_thread_join_one(e2fsck_t global_ctx, e2fsck_t thread_ctx #ifdef HAVE_SETJMP_H memcpy(global_ctx->abort_loc, old_jmp, sizeof(jmp_buf)); #endif + + global_ctx->inode_used_map = inode_used_map; + global_ctx->inode_bad_map = inode_bad_map; + global_ctx->inode_dir_map = inode_dir_map; + global_ctx->inode_bb_map = inode_bb_map; + global_ctx->inode_imagic_map = inode_imagic_map; + global_ctx->inodes_to_rebuild = inodes_to_rebuild; + global_ctx->inode_reg_map = inode_reg_map; + global_ctx->block_found_map = block_found_map; + global_ctx->block_dup_map = block_dup_map; + global_ctx->block_ea_map = block_ea_map; + global_ctx->block_metadata_map = block_metadata_map; + /* Keep the global singal flags*/ global_ctx->flags |= (flags & E2F_FLAG_SIGNAL_MASK) | (global_ctx->flags & E2F_FLAG_SIGNAL_MASK); @@ -2382,83 +2443,62 @@ static int e2fsck_pass1_thread_join_one(e2fsck_t global_ctx, e2fsck_t thread_ctx global_ctx->problem_logf = global_problem_logf; global_ctx->global_ctx = NULL; - if (thread_ctx->inode_used_map) { - retval = e2fsck_pass1_copy_bitmap(global_fs, - &thread_ctx->inode_used_map, - &global_ctx->inode_used_map); - if (retval) - return retval; - } - if (thread_ctx->inode_bad_map) { - retval = e2fsck_pass1_copy_bitmap(global_fs, - &thread_ctx->inode_bad_map, - &global_ctx->inode_bad_map); - if (retval) - return retval; - } - if (thread_ctx->inode_dir_map) { - retval = e2fsck_pass1_copy_bitmap(global_fs, + retval = e2fsck_pass1_merge_bitmap(global_fs, + &thread_ctx->inode_used_map, + &global_ctx->inode_used_map); + if (retval) + return retval; + + retval = e2fsck_pass1_merge_bitmap(global_fs, + &thread_ctx->inode_bad_map, + &global_ctx->inode_bad_map); + if (retval) + return retval; + retval = e2fsck_pass1_merge_bitmap(global_fs, &thread_ctx->inode_dir_map, &global_ctx->inode_dir_map); - if (retval) - return retval; - } - if (thread_ctx->inode_bb_map) { - retval = e2fsck_pass1_copy_bitmap(global_fs, - &thread_ctx->inode_bb_map, - &global_ctx->inode_bb_map); - if (retval) - return retval; - } - if (thread_ctx->inode_imagic_map) { - retval = e2fsck_pass1_copy_bitmap(global_fs, - &thread_ctx->inode_imagic_map, - &global_ctx->inode_imagic_map); - if (retval) - return retval; - } - if (thread_ctx->inode_reg_map) { - retval = e2fsck_pass1_copy_bitmap(global_fs, - &thread_ctx->inode_reg_map, - &global_ctx->inode_reg_map); - if (retval) - return retval; - } - if (thread_ctx->inodes_to_rebuild) { - retval = e2fsck_pass1_copy_bitmap(global_fs, - &thread_ctx->inodes_to_rebuild, - &global_ctx->inodes_to_rebuild); - if (retval) - return retval; - } - if (thread_ctx->block_found_map) { - retval = e2fsck_pass1_copy_bitmap(global_fs, - &thread_ctx->block_found_map, - &global_ctx->block_found_map); - if (retval) - return retval; - } - if (thread_ctx->block_dup_map) { - retval = e2fsck_pass1_copy_bitmap(global_fs, - &thread_ctx->block_dup_map, - &global_ctx->block_dup_map); - if (retval) - return retval; - } - if (thread_ctx->block_ea_map) { - retval = e2fsck_pass1_copy_bitmap(global_fs, - &thread_ctx->block_ea_map, - &global_ctx->block_ea_map); - if (retval) - return retval; - } - if (thread_ctx->block_metadata_map) { - retval = e2fsck_pass1_copy_bitmap(global_fs, - &thread_ctx->block_metadata_map, - &global_ctx->block_metadata_map); - if (retval) - return retval; - } + if (retval) + return retval; + retval = e2fsck_pass1_merge_bitmap(global_fs, + &thread_ctx->inode_bb_map, + &global_ctx->inode_bb_map); + if (retval) + return retval; + retval = e2fsck_pass1_merge_bitmap(global_fs, + &thread_ctx->inode_imagic_map, + &global_ctx->inode_imagic_map); + if (retval) + return retval; + retval = e2fsck_pass1_merge_bitmap(global_fs, + &thread_ctx->inode_reg_map, + &global_ctx->inode_reg_map); + if (retval) + return retval; + retval = e2fsck_pass1_merge_bitmap(global_fs, + &thread_ctx->inodes_to_rebuild, + &global_ctx->inodes_to_rebuild); + if (retval) + return retval; + retval = e2fsck_pass1_merge_bitmap(global_fs, + &thread_ctx->block_found_map, + &global_ctx->block_found_map); + if (retval) + return retval; + retval = e2fsck_pass1_merge_bitmap(global_fs, + &thread_ctx->block_dup_map, + &global_ctx->block_dup_map); + if (retval) + return retval; + retval = e2fsck_pass1_merge_bitmap(global_fs, + &thread_ctx->block_ea_map, + &global_ctx->block_ea_map); + if (retval) + return retval; + retval = e2fsck_pass1_merge_bitmap(global_fs, + &thread_ctx->block_metadata_map, + &global_ctx->block_metadata_map); + if (retval) + return retval; return 0; } @@ -2475,6 +2515,17 @@ static int e2fsck_pass1_thread_join(e2fsck_t global_ctx, e2fsck_t thread_ctx) fputs("\n", thread_ctx->problem_logf); fclose(thread_ctx->problem_logf); } + e2fsck_pass1_free_bitmap(&thread_ctx->inode_used_map); + e2fsck_pass1_free_bitmap(&thread_ctx->inode_bad_map); + e2fsck_pass1_free_bitmap(&thread_ctx->inode_dir_map); + e2fsck_pass1_free_bitmap(&thread_ctx->inode_bb_map); + e2fsck_pass1_free_bitmap(&thread_ctx->inode_imagic_map); + e2fsck_pass1_free_bitmap(&thread_ctx->inode_reg_map); + e2fsck_pass1_free_bitmap(&thread_ctx->inodes_to_rebuild); + e2fsck_pass1_free_bitmap(&thread_ctx->block_found_map); + e2fsck_pass1_free_bitmap(&thread_ctx->block_dup_map); + e2fsck_pass1_free_bitmap(&thread_ctx->block_ea_map); + e2fsck_pass1_free_bitmap(&thread_ctx->block_metadata_map); ext2fs_free_mem(&thread_ctx); return retval; @@ -2501,7 +2552,13 @@ static int e2fsck_pass1_threads_join(struct e2fsck_thread_info *infos, if (ret == 0) ret = rc; } - e2fsck_pass1_thread_join(global_ctx, infos[i].eti_thread_ctx); + rc = e2fsck_pass1_thread_join(global_ctx, infos[i].eti_thread_ctx); + if (rc) { + com_err(global_ctx->program_name, rc, + _("while joining pass1 thread\n")); + if (ret == 0) + ret = rc; + } } free(infos); diff --git a/lib/ext2fs/bitmaps.c b/lib/ext2fs/bitmaps.c index 8bfa24b..9437331 100644 --- a/lib/ext2fs/bitmaps.c +++ b/lib/ext2fs/bitmaps.c @@ -45,6 +45,16 @@ errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src, { return (ext2fs_copy_generic_bmap(src, dest)); } + +errcode_t ext2fs_merge_bitmap(ext2fs_generic_bitmap src, + ext2fs_generic_bitmap dest, + ext2fs_generic_bitmap dup, + ext2fs_generic_bitmap dup_allowed) +{ + return ext2fs_merge_generic_bmap(src, dest, dup, + dup_allowed); +} + void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map) { ext2fs_set_generic_bmap_padding(map); diff --git a/lib/ext2fs/blkmap64_rb.c b/lib/ext2fs/blkmap64_rb.c index 0df58dc..d7c88ae 100644 --- a/lib/ext2fs/blkmap64_rb.c +++ b/lib/ext2fs/blkmap64_rb.c @@ -977,11 +977,76 @@ static void rb_print_stats(ext2fs_generic_bitmap_64 bitmap EXT2FS_ATTR((unused)) } #endif +static errcode_t rb_merge_bmap(ext2fs_generic_bitmap_64 src, + ext2fs_generic_bitmap_64 dest, + ext2fs_generic_bitmap_64 dup, + ext2fs_generic_bitmap_64 dup_allowed) +{ + struct ext2fs_rb_private *src_bp, *dest_bp, *dup_bp = NULL; + struct bmap_rb_extent *src_ext; + struct rb_node *src_node; + errcode_t retval = 0; + int dup_found = 0; + __u64 i; + + src_bp = (struct ext2fs_rb_private *) src->private; + dest_bp = (struct ext2fs_rb_private *) dest->private; + if (dup) + dup_bp = (struct ext2fs_rb_private *)dup->private; + src_bp->rcursor = NULL; + dest_bp->rcursor = NULL; + + src_node = ext2fs_rb_first(&src_bp->root); + while (src_node) { + src_ext = node_to_extent(src_node); + retval = rb_test_clear_bmap_extent(dest, + src_ext->start + src->start, + src_ext->count); + if (retval) { + rb_insert_extent(src_ext->start, src_ext->count, + dest_bp); + goto next; + } + + /* unlikely case, do it one by one block */ + for (i = src_ext->start; + i < src_ext->start + src_ext->count; i++) { + retval = rb_test_clear_bmap_extent(dest, i + src->start, 1); + if (retval) { + rb_insert_extent(i, 1, dest_bp); + continue; + } + if (dup_allowed) { + retval = rb_test_clear_bmap_extent(dup_allowed, + i + src->start, 1); + /* not existed in dup_allowed */ + if (retval) { + dup_found = 1; + if (dup_bp) + rb_insert_extent(i, 1, dup_bp); + } /* else we conside it not duplicated */ + } else { + if (dup_bp) + rb_insert_extent(i, 1, dup_bp); + dup_found = 1; + } + } +next: + src_node = ext2fs_rb_next(src_node); + } + + if (dup_found && dup) + return EEXIST; + + return 0; +} + struct ext2_bitmap_ops ext2fs_blkmap64_rbtree = { .type = EXT2FS_BMAP64_RBTREE, .new_bmap = rb_new_bmap, .free_bmap = rb_free_bmap, .copy_bmap = rb_copy_bmap, + .merge_bmap = rb_merge_bmap, .resize_bmap = rb_resize_bmap, .mark_bmap = rb_mark_bmap, .unmark_bmap = rb_unmark_bmap, diff --git a/lib/ext2fs/bmap64.h b/lib/ext2fs/bmap64.h index de33454..555193e 100644 --- a/lib/ext2fs/bmap64.h +++ b/lib/ext2fs/bmap64.h @@ -72,6 +72,10 @@ struct ext2_bitmap_ops { void (*free_bmap)(ext2fs_generic_bitmap_64 bitmap); errcode_t (*copy_bmap)(ext2fs_generic_bitmap_64 src, ext2fs_generic_bitmap_64 dest); + errcode_t (*merge_bmap)(ext2fs_generic_bitmap_64 src, + ext2fs_generic_bitmap_64 dest, + ext2fs_generic_bitmap_64 dup, + ext2fs_generic_bitmap_64 dup_allowed); errcode_t (*resize_bmap)(ext2fs_generic_bitmap_64 bitmap, __u64 new_end, __u64 new_real_end); diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index b4ed108..5eb9526 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -865,6 +865,10 @@ extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap); extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap); extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src, ext2fs_generic_bitmap *dest); +errcode_t ext2fs_merge_bitmap(ext2fs_generic_bitmap src, + ext2fs_generic_bitmap dest, + ext2fs_generic_bitmap dup, + ext2fs_generic_bitmap dup_allowed); extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs, const char *descr, ext2fs_block_bitmap *ret); @@ -1459,6 +1463,10 @@ void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap); errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap, __u64 new_end, __u64 new_real_end); +errcode_t ext2fs_merge_generic_bmap(ext2fs_generic_bitmap gen_src, + ext2fs_generic_bitmap gen_dest, + ext2fs_generic_bitmap gen_dup, + ext2fs_generic_bitmap dup_allowed); errcode_t ext2fs_compare_generic_bmap(errcode_t neq, ext2fs_generic_bitmap bm1, ext2fs_generic_bitmap bm2); diff --git a/lib/ext2fs/gen_bitmap64.c b/lib/ext2fs/gen_bitmap64.c index c860c10..4ea930a 100644 --- a/lib/ext2fs/gen_bitmap64.c +++ b/lib/ext2fs/gen_bitmap64.c @@ -346,6 +346,35 @@ errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap gen_src, return 0; } +errcode_t ext2fs_merge_generic_bmap(ext2fs_generic_bitmap gen_src, + ext2fs_generic_bitmap gen_dest, + ext2fs_generic_bitmap gen_dup, + ext2fs_generic_bitmap gen_dup_allowed) +{ + ext2fs_generic_bitmap_64 src = (ext2fs_generic_bitmap_64)gen_src; + ext2fs_generic_bitmap_64 dest = (ext2fs_generic_bitmap_64)gen_dest; + ext2fs_generic_bitmap_64 dup = (ext2fs_generic_bitmap_64)gen_dup; + ext2fs_generic_bitmap_64 dup_allowed = (ext2fs_generic_bitmap_64)gen_dup_allowed; + + if (!src || !dest) + return EINVAL; + + if (!EXT2FS_IS_64_BITMAP(src) || !EXT2FS_IS_64_BITMAP(dest) || + (dup && !EXT2FS_IS_64_BITMAP(dup)) || + (dup_allowed && !EXT2FS_IS_64_BITMAP(dup_allowed))) + return EINVAL; + + if (src->bitmap_ops != dest->bitmap_ops || + (dup && src->bitmap_ops != dup->bitmap_ops) || + (dup_allowed && src->bitmap_ops != dup_allowed->bitmap_ops)) + return EINVAL; + + if (src->bitmap_ops->merge_bmap == NULL) + return EOPNOTSUPP; + + return src->bitmap_ops->merge_bmap(src, dest, dup, dup_allowed); +} + errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap gen_bmap, __u64 new_end, __u64 new_real_end)