aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWang Shilong <wshilong@ddn.com>2020-09-23 11:17:29 +0800
committerTheodore Ts'o <tytso@mit.edu>2021-01-25 15:17:02 -0500
commitecf85fb474fb7537f14bddd8f85d8372b808d5e9 (patch)
tree156b7bcbee0195aaeb9da78ad38a8b86f26ab1b4
parent5b071ed80deca2cdc87585a673076529dd47ca6e (diff)
downloade2fsprogs-ecf85fb474fb7537f14bddd8f85d8372b808d5e9.tar.gz
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. Signed-off-by: Li Xi <lixi@ddn.com> Signed-off-by: Wang Shilong <wshilong@ddn.com> Reviewed-by: Andreas Dilger <adilger@whamcloud.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--e2fsck/pass1.c239
-rw-r--r--lib/ext2fs/bitmaps.c10
-rw-r--r--lib/ext2fs/blkmap64_rb.c65
-rw-r--r--lib/ext2fs/bmap64.h4
-rw-r--r--lib/ext2fs/ext2fs.h8
-rw-r--r--lib/ext2fs/gen_bitmap64.c29
6 files changed, 264 insertions, 91 deletions
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index c59cf1019..fa8d1ebff 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -2124,12 +2124,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)
@@ -2137,6 +2163,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) {
@@ -2196,42 +2224,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;
}
@@ -2321,6 +2357,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;
@@ -2330,6 +2378,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);
@@ -2345,83 +2406,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;
}
@@ -2438,6 +2478,17 @@ static int e2fsck_pass1_thread_join(e2fsck_t global_ctx, e2fsck_t thread_ctx)
fputs("</problem_log>\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;
@@ -2464,7 +2515,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 834a3962a..000df234c 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 1fd552745..7150d791e 100644
--- a/lib/ext2fs/blkmap64_rb.c
+++ b/lib/ext2fs/blkmap64_rb.c
@@ -968,11 +968,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 de3345481..555193ee1 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 1f60652f1..fc1af3e34 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -852,6 +852,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_write_inode_bitmap(ext2_filsys fs);
extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs);
extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs);
@@ -1448,6 +1452,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 b2370667c..50617a346 100644
--- a/lib/ext2fs/gen_bitmap64.c
+++ b/lib/ext2fs/gen_bitmap64.c
@@ -344,6 +344,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)