diff mbox series

[RFC,v2,17/51] e2fsck: merge bitmaps after thread completes

Message ID 1592494074-28991-18-git-send-email-wangshilong1991@gmail.com
State New
Headers show
Series introduce parallel fsck to e2fsck pass1 | expand

Commit Message

Wang Shilong June 18, 2020, 3:27 p.m. UTC
From: Li Xi <lixi@ddn.com>

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>
---
 e2fsck/pass1.c            | 149 +++++++++++++++++++++++++++++---------
 lib/ext2fs/bitmaps.c      |   7 ++
 lib/ext2fs/blkmap64_rb.c  |  25 +++++++
 lib/ext2fs/bmap64.h       |   2 +
 lib/ext2fs/ext2fs.h       |   4 +
 lib/ext2fs/gen_bitmap64.c |  21 ++++++
 6 files changed, 173 insertions(+), 35 deletions(-)
diff mbox series

Patch

diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 64666663..8f24df0e 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -2105,31 +2105,57 @@  endit:
 		ctx->invalid_bitmaps++;
 }
 
-#define PASS1_COPY_FS_BITMAP(_dest, _src, _map_filed)			\
+#define PASS1_COPY_FS_BITMAP(_dest, _src, _map_filed)		\
+do {								\
+	errcode_t _ret;						\
+	if (_src->_map_filed) {					\
+		_ret = ext2fs_copy_bitmap(_src->_map_filed,	\
+					  &_dest->_map_filed);	\
+		if (_ret)                                       \
+			return _ret;				\
+		_dest->_map_filed->fs = _dest;			\
+	}							\
+} while (0)
+
+#define PASS1_MERGE_FS_BITMAP(_dest, _src, _map_field)			\
 do {									\
-    errcode_t _ret;							\
-    if (_src->_map_filed) {						\
-        _ret = ext2fs_copy_bitmap(_src->_map_filed, &_dest->_map_filed);\
-        if (_ret)							\
-            return _ret;						\
-        _dest->_map_filed->fs = _dest;					\
-									\
-        ext2fs_free_generic_bmap(_src->_map_filed);			\
-        _src->_map_filed = NULL;					\
-    }									\
+	errcode_t _ret = 0;						\
+	if (_src->_map_field) {						\
+		if (_dest->_map_field == NULL)	{			\
+			_dest->_map_field = _src->_map_field;		\
+			_src->_map_field = NULL;			\
+		} else {						\
+			_ret = ext2fs_merge_bitmap(_src->_map_field,	\
+						   _dest->_map_field);	\
+			if (_ret)					\
+				return _ret;				\
+		}							\
+		_dest->_map_field->fs = _dest;				\
+	}								\
 } while (0)
 
-#define PASS1_COPY_CTX_BITMAP(_dest, _src, _map_filed)			\
+#define PASS1_MERGE_CTX_BITMAP(_dest, _src, _map_field)			\
 do {									\
-    errcode_t _ret;							\
-    if (_src->_map_filed) {						\
-        _ret = ext2fs_copy_bitmap(_src->_map_filed, &_dest->_map_filed);\
-        if (_ret)							\
-            return _ret;						\
-        _dest->_map_filed->fs = _dest->fs;				\
-									\
-        ext2fs_free_generic_bmap(_src->_map_filed);			\
-        _src->_map_filed = NULL;					\
+	errcode_t _ret = 0;						\
+	if (_src->_map_field) {						\
+		if (_dest->_map_field == NULL)	{			\
+			_dest->_map_field = _src->_map_field;		\
+			_src->_map_field = NULL;			\
+		} else {						\
+			_ret = ext2fs_merge_bitmap(_src->_map_field,	\
+						   _dest->_map_field);	\
+			if (_ret)					\
+				return _ret;				\
+		}							\
+		_dest->_map_field->fs = _dest->fs;			\
+	}								\
+} while (0)
+
+#define PASS1_FREE_CTX_BITMAP(_src, _map_field)				\
+do {									\
+    if (_src->_map_field) {						\
+        ext2fs_free_generic_bmap(_src->_map_field);			\
+        _src->_map_field = NULL;					\
     }									\
 } while (0)
 
@@ -2168,6 +2194,9 @@  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;
+
 	/*
 	 * PASS1_COPY_FS_BITMAP might return directly from this function,
 	 * so please do NOT leave any garbage behind after returning.
@@ -2241,18 +2270,24 @@  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->inode_map = inode_map;
+	dest->block_map = block_map;
 	/*
-	 * PASS1_COPY_FS_BITMAP might return directly from this function,
+	 * PASS1_MERGE_FS_BITMAP might return directly from this function,
 	 * so please do NOT leave any garbage behind after returning.
 	 */
-	PASS1_COPY_FS_BITMAP(dest, src, inode_map);
-	PASS1_COPY_FS_BITMAP(dest, src, block_map);
+	PASS1_MERGE_FS_BITMAP(dest, src, inode_map);
+	PASS1_MERGE_FS_BITMAP(dest, src, block_map);
 
 	if (src->dblist) {
 		retval = ext2fs_copy_dblist(src->dblist, &dest->dblist);
@@ -2281,6 +2316,11 @@  static int e2fsck_pass1_merge_fs(ext2_filsys dest, ext2_filsys src)
 
 	retval = _e2fsck_pass1_merge_fs(dest, src);
 
+	if (src->inode_map)
+		ext2fs_free_generic_bmap(src->inode_map);
+	if (src->block_map)
+		ext2fs_free_generic_bmap(src->block_map);
+
 	/* icache will be rebuilt if needed, so do not copy from @src */
 	if (src->icache) {
 		ext2fs_free_inode_cache(src->icache);
@@ -2388,6 +2428,17 @@  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_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;
 
@@ -2397,6 +2448,18 @@  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_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);
@@ -2416,16 +2479,16 @@  static int e2fsck_pass1_thread_join_one(e2fsck_t global_ctx, e2fsck_t thread_ctx
 	 * PASS1_COPY_CTX_BITMAP might return directly from this function,
 	 * so please do NOT leave any garbage behind after returning.
 	 */
-	PASS1_COPY_CTX_BITMAP(global_ctx, thread_ctx, inode_used_map);
-	PASS1_COPY_CTX_BITMAP(global_ctx, thread_ctx, inode_dir_map);
-	PASS1_COPY_CTX_BITMAP(global_ctx, thread_ctx, inode_bb_map);
-	PASS1_COPY_CTX_BITMAP(global_ctx, thread_ctx, inode_imagic_map);
-	PASS1_COPY_CTX_BITMAP(global_ctx, thread_ctx, inode_reg_map);
-	PASS1_COPY_CTX_BITMAP(global_ctx, thread_ctx, inodes_to_rebuild);
-	PASS1_COPY_CTX_BITMAP(global_ctx, thread_ctx, block_found_map);
-	PASS1_COPY_CTX_BITMAP(global_ctx, thread_ctx, block_dup_map);
-	PASS1_COPY_CTX_BITMAP(global_ctx, thread_ctx, block_ea_map);
-	PASS1_COPY_CTX_BITMAP(global_ctx, thread_ctx, block_metadata_map);
+	PASS1_MERGE_CTX_BITMAP(global_ctx, thread_ctx, inode_used_map);
+	PASS1_MERGE_CTX_BITMAP(global_ctx, thread_ctx, inode_dir_map);
+	PASS1_MERGE_CTX_BITMAP(global_ctx, thread_ctx, inode_bb_map);
+	PASS1_MERGE_CTX_BITMAP(global_ctx, thread_ctx, inode_imagic_map);
+	PASS1_MERGE_CTX_BITMAP(global_ctx, thread_ctx, inode_reg_map);
+	PASS1_MERGE_CTX_BITMAP(global_ctx, thread_ctx, inodes_to_rebuild);
+	PASS1_MERGE_CTX_BITMAP(global_ctx, thread_ctx, block_found_map);
+	PASS1_MERGE_CTX_BITMAP(global_ctx, thread_ctx, block_dup_map);
+	PASS1_MERGE_CTX_BITMAP(global_ctx, thread_ctx, block_ea_map);
+	PASS1_MERGE_CTX_BITMAP(global_ctx, thread_ctx, block_metadata_map);
 
 	return 0;
 }
@@ -2442,6 +2505,16 @@  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);
 	}
+	PASS1_FREE_CTX_BITMAP(thread_ctx, inode_used_map);
+	PASS1_FREE_CTX_BITMAP(thread_ctx, inode_dir_map);
+	PASS1_FREE_CTX_BITMAP(thread_ctx, inode_bb_map);
+	PASS1_FREE_CTX_BITMAP(thread_ctx, inode_imagic_map);
+	PASS1_FREE_CTX_BITMAP(thread_ctx, inode_reg_map);
+	PASS1_FREE_CTX_BITMAP(thread_ctx, inodes_to_rebuild);
+	PASS1_FREE_CTX_BITMAP(thread_ctx, block_found_map);
+	PASS1_FREE_CTX_BITMAP(thread_ctx, block_dup_map);
+	PASS1_FREE_CTX_BITMAP(thread_ctx, block_ea_map);
+	PASS1_FREE_CTX_BITMAP(thread_ctx, block_metadata_map);
 	ext2fs_free_mem(&thread_ctx);
 
 	return retval;
@@ -2468,7 +2541,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 834a3962..74a8c347 100644
--- a/lib/ext2fs/bitmaps.c
+++ b/lib/ext2fs/bitmaps.c
@@ -45,6 +45,13 @@  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)
+{
+	return ext2fs_merge_generic_bmap(src, dest);
+}
+
 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 1fd55274..42a10536 100644
--- a/lib/ext2fs/blkmap64_rb.c
+++ b/lib/ext2fs/blkmap64_rb.c
@@ -968,11 +968,36 @@  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)
+{
+	struct ext2fs_rb_private *src_bp, *dest_bp;
+	struct bmap_rb_extent *src_ext;
+	struct rb_node *src_node;
+	errcode_t retval = 0;
+
+	src_bp = (struct ext2fs_rb_private *) src->private;
+	dest_bp = (struct ext2fs_rb_private *) dest->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);
+		rb_insert_extent(src_ext->start, src_ext->count, dest_bp);
+
+		src_node = ext2fs_rb_next(src_node);
+	}
+
+	return retval;
+}
+
 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 de334548..09a5886b 100644
--- a/lib/ext2fs/bmap64.h
+++ b/lib/ext2fs/bmap64.h
@@ -72,6 +72,8 @@  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);
 	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 69c8a3ff..d5b1af2f 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -837,6 +837,8 @@  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);
 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);
@@ -1433,6 +1435,8 @@  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);
 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 b2370667..2617ac22 100644
--- a/lib/ext2fs/gen_bitmap64.c
+++ b/lib/ext2fs/gen_bitmap64.c
@@ -344,6 +344,27 @@  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_64 src = (ext2fs_generic_bitmap_64) gen_src;
+	ext2fs_generic_bitmap_64 dest = (ext2fs_generic_bitmap_64) gen_dest;
+
+	if (!src || !dest)
+		return EINVAL;
+
+	if (!EXT2FS_IS_64_BITMAP(src) || !EXT2FS_IS_64_BITMAP(dest))
+		return EINVAL;
+
+	if (src->bitmap_ops != dest->bitmap_ops)
+		return EINVAL;
+
+	if (src->bitmap_ops->merge_bmap == NULL)
+		return EOPNOTSUPP;
+
+	return src->bitmap_ops->merge_bmap(src, dest);
+}
+
 errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap gen_bmap,
 				     __u64 new_end,
 				     __u64 new_real_end)