Whamcloud - gitweb
e2fsck: move some fixes out of parallel pthreads
authorWang Shilong <wshilong@ddn.com>
Sat, 7 Mar 2020 14:00:45 +0000 (22:00 +0800)
committerLi Dongyang <dongyangli@ddn.com>
Fri, 28 Apr 2023 00:43:50 +0000 (10:43 +1000)
We could only use @found_map_block to find free blocks
after we have collectd all used blocks, so something like
handle_fs_bad_blocks(), ext2fs_create_resize_inode(),
e2fsck_pass1_dupblocks() really should be handled after
all threads has been finished.

E2fsprogs-commit: 6b1d459bf6018eea7ff0a0ae6b555276718dcda3

Change-Id: Ibdbaed3d218623daa0baec31837037d773799262
Signed-off-by: Wang Shilong <wshilong@ddn.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Signed-off-by: Saranya Muruganandam <saranyamohan@google.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
e2fsck/e2fsck.h
e2fsck/pass1.c
e2fsck/util.c
tests/f_multithread/expect.1
tests/f_multithread_logfile/expect.1
tests/f_multithread_no/expect.1

index 5855cea..ecc5fe1 100644 (file)
@@ -490,6 +490,8 @@ struct e2fsck_struct {
 #ifdef HAVE_PTHREAD
        /* serialize fix operation for multiple threads */
        pthread_mutex_t          fs_fix_mutex;
+       /* protect block_found_map, block_dup_map */
+       pthread_mutex_t          fs_block_map_mutex;
 #endif
 };
 
@@ -794,6 +796,8 @@ extern errcode_t e2fsck_allocate_subcluster_bitmap(ext2_filsys fs,
 unsigned long long get_memory_size(void);
 extern void e2fsck_pass1_fix_lock(e2fsck_t ctx);
 extern void e2fsck_pass1_fix_unlock(e2fsck_t ctx);
+extern void e2fsck_pass1_block_map_lock(e2fsck_t ctx);
+extern void e2fsck_pass1_block_map_unlock(e2fsck_t ctx);
 
 /* unix.c */
 extern void e2fsck_clear_progbar(e2fsck_t ctx);
index a520ec9..12172dc 100644 (file)
@@ -759,11 +759,15 @@ static void check_is_really_dir(e2fsck_t ctx, struct problem_context *pctx,
                        if (i >= 4)
                                not_device++;
 
+                       e2fsck_pass1_block_map_lock(ctx);
                        if (blk < ctx->fs->super->s_first_data_block ||
                            blk >= ext2fs_blocks_count(ctx->fs->super) ||
                            ext2fs_fast_test_block_bitmap2(ctx->block_found_map,
-                                                          blk))
+                                                          blk)) {
+                               e2fsck_pass1_block_map_unlock(ctx);
                                return; /* Invalid block, can't be dir */
+                       }
+                       e2fsck_pass1_block_map_unlock(ctx);
                }
                blk = inode->i_block[0];
        }
@@ -897,19 +901,15 @@ static void reserve_block_for_root_repair(e2fsck_t ctx)
        errcode_t       err;
        ext2_filsys     fs = ctx->fs;
 
-       e2fsck_pass1_fix_lock(ctx);
        ctx->root_repair_block = 0;
        if (ext2fs_test_inode_bitmap2(ctx->inode_used_map, EXT2_ROOT_INO))
-               goto out;
+               return;
 
        err = ext2fs_new_block2(fs, 0, ctx->block_found_map, &blk);
        if (err)
-               goto out;
+               return;
        ext2fs_mark_block_bitmap2(ctx->block_found_map, blk);
        ctx->root_repair_block = blk;
-out:
-       e2fsck_pass1_fix_unlock(ctx);
-       return;
 }
 
 static void reserve_block_for_lnf_repair(e2fsck_t ctx)
@@ -920,18 +920,15 @@ static void reserve_block_for_lnf_repair(e2fsck_t ctx)
        static const char name[] = "lost+found";
        ext2_ino_t      ino;
 
-       e2fsck_pass1_fix_lock(ctx);
        ctx->lnf_repair_block = 0;
        if (!ext2fs_lookup(fs, EXT2_ROOT_INO, name, sizeof(name)-1, 0, &ino))
-               goto out;
+               return;
 
        err = ext2fs_new_block2(fs, 0, ctx->block_found_map, &blk);
        if (err)
-               goto out;
+               return;
        ext2fs_mark_block_bitmap2(ctx->block_found_map, blk);
        ctx->lnf_repair_block = blk;
-out:
-       e2fsck_pass1_fix_unlock(ctx);
        return;
 }
 
@@ -1188,6 +1185,118 @@ static int e2fsck_should_abort(e2fsck_t ctx)
        return 0;
 }
 
+/*
+ * We need call mark_table_blocks() before multiple
+ * thread start, since all known system blocks should be
+ * marked and checked later.
+ */
+static errcode_t e2fsck_pass1_prepare(e2fsck_t ctx)
+{
+       struct problem_context pctx;
+       ext2_filsys fs = ctx->fs;
+
+       clear_problem_context(&pctx);
+       if (!(ctx->options & E2F_OPT_PREEN))
+               fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
+
+       pctx.errcode = e2fsck_allocate_subcluster_bitmap(ctx->fs,
+                       _("in-use block map"), EXT2FS_BMAP64_RBTREE,
+                       "block_found_map", &ctx->block_found_map);
+       if (pctx.errcode) {
+               pctx.num = 1;
+               fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
+               ctx->flags |= E2F_FLAG_ABORT;
+               return pctx.errcode;
+       }
+       pctx.errcode = e2fsck_allocate_block_bitmap(ctx->fs,
+                       _("metadata block map"), EXT2FS_BMAP64_RBTREE,
+                       "block_metadata_map", &ctx->block_metadata_map);
+       if (pctx.errcode) {
+               pctx.num = 1;
+               fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
+               ctx->flags |= E2F_FLAG_ABORT;
+               return pctx.errcode;
+       }
+
+       mark_table_blocks(ctx);
+       pctx.errcode = ext2fs_convert_subcluster_bitmap(ctx->fs,
+                                               &ctx->block_found_map);
+       if (pctx.errcode) {
+               fix_problem(ctx, PR_1_CONVERT_SUBCLUSTER, &pctx);
+               ctx->flags |= E2F_FLAG_ABORT;
+               return pctx.errcode;
+       }
+
+       if (ext2fs_has_feature_mmp(fs->super) &&
+           fs->super->s_mmp_block > fs->super->s_first_data_block &&
+           fs->super->s_mmp_block < ext2fs_blocks_count(fs->super))
+               ext2fs_mark_block_bitmap2(ctx->block_found_map,
+                                         fs->super->s_mmp_block);
+
+       return 0;
+}
+
+static void e2fsck_pass1_post(e2fsck_t ctx)
+{
+       struct problem_context pctx;
+       ext2_filsys fs = ctx->fs;
+       char *block_buf;
+
+       reserve_block_for_root_repair(ctx);
+       reserve_block_for_lnf_repair(ctx);
+
+       if (ctx->invalid_bitmaps)
+               handle_fs_bad_blocks(ctx);
+
+       if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
+               struct ext2_inode *inode;
+               int inode_size = EXT2_INODE_SIZE(fs->super);
+               inode = e2fsck_allocate_memory(ctx, inode_size,
+                                              "scratch inode");
+
+               clear_problem_context(&pctx);
+               pctx.errcode = ext2fs_create_resize_inode(fs);
+               if (pctx.errcode) {
+                       if (!fix_problem(ctx, PR_1_RESIZE_INODE_CREATE,
+                                        &pctx)) {
+                               ctx->flags |= E2F_FLAG_ABORT;
+                               ext2fs_free_mem(&inode);
+                               ext2fs_free_mem(&block_buf);
+                               return;
+                       }
+                       pctx.errcode = 0;
+               }
+               if (!pctx.errcode) {
+                       e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
+                                         "recreate inode");
+                       inode->i_mtime = ctx->now;
+                       e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
+                                          "recreate inode");
+               }
+               ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
+               ext2fs_free_mem(&inode);
+       }
+
+       if (ctx->flags & E2F_FLAG_RESTART) {
+               ext2fs_free_mem(&block_buf);
+               return;
+       }
+
+       if (ctx->block_dup_map) {
+               if (ctx->options & E2F_OPT_PREEN) {
+                       clear_problem_context(&pctx);
+                       fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
+               }
+               block_buf =
+                       (char *)e2fsck_allocate_memory(ctx,
+                                       ctx->fs->blocksize * 3,
+                                       "block interate buffer");
+               e2fsck_pass1_dupblocks(ctx, block_buf);
+               ext2fs_free_mem(&block_buf);
+       }
+}
+
+
 void e2fsck_pass1_run(e2fsck_t ctx)
 {
        int     i;
@@ -1226,9 +1335,6 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                ctx->readahead_kb = e2fsck_guess_readahead(ctx->fs);
        pass1_readahead(ctx, &ra_group, &ino_threshold);
 
-       if (!(ctx->options & E2F_OPT_PREEN))
-               fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
-
        if (ext2fs_has_feature_dir_index(fs->super) &&
            !(ctx->options & E2F_OPT_NO)) {
                if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
@@ -1277,24 +1383,6 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                ctx->flags |= E2F_FLAG_ABORT;
                return;
        }
-       pctx.errcode = e2fsck_allocate_subcluster_bitmap(fs,
-                       _("in-use block map"), EXT2FS_BMAP64_RBTREE,
-                       "block_found_map", &ctx->block_found_map);
-       if (pctx.errcode) {
-               pctx.num = 1;
-               fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
-               ctx->flags |= E2F_FLAG_ABORT;
-               return;
-       }
-       pctx.errcode = e2fsck_allocate_block_bitmap(fs,
-                       _("metadata block map"), EXT2FS_BMAP64_RBTREE,
-                       "block_metadata_map", &ctx->block_metadata_map);
-       if (pctx.errcode) {
-               pctx.num = 1;
-               fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
-               ctx->flags |= E2F_FLAG_ABORT;
-               return;
-       }
        if (casefold_fs) {
                pctx.errcode =
                        e2fsck_allocate_inode_bitmap(fs,
@@ -1350,14 +1438,6 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                }
        }
 
-       mark_table_blocks(ctx);
-       pctx.errcode = ext2fs_convert_subcluster_bitmap(fs,
-                                               &ctx->block_found_map);
-       if (pctx.errcode) {
-               fix_problem(ctx, PR_1_CONVERT_SUBCLUSTER, &pctx);
-               ctx->flags |= E2F_FLAG_ABORT;
-               goto endit;
-       }
        block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
                                                    "block iterate buffer");
        if (EXT2_INODE_SIZE(fs->super) == EXT2_GOOD_OLD_INODE_SIZE)
@@ -1391,12 +1471,6 @@ void e2fsck_pass1_run(e2fsck_t ctx)
             fs->super->s_mkfs_time < fs->super->s_inodes_count))
                low_dtime_check = 0;
 
-       if (ext2fs_has_feature_mmp(fs->super) &&
-           fs->super->s_mmp_block > fs->super->s_first_data_block &&
-           fs->super->s_mmp_block < ext2fs_blocks_count(fs->super))
-               ext2fs_mark_block_bitmap2(ctx->block_found_map,
-                                         fs->super->s_mmp_block);
-
        /* Set up ctx->lost_and_found if possible */
        (void) e2fsck_get_lost_and_found(ctx, 0);
 
@@ -1727,8 +1801,10 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                                failed_csum = 0;
                        }
 
+                       e2fsck_pass1_block_map_lock(ctx);
                        pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
                                                          &pb.fs_meta_blocks);
+                       e2fsck_pass1_block_map_unlock(ctx);
                        if (pctx.errcode) {
                                pctx.num = 4;
                                fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
@@ -2075,9 +2151,6 @@ void e2fsck_pass1_run(e2fsck_t ctx)
        ext2fs_close_inode_scan(scan);
        scan = NULL;
 
-       reserve_block_for_root_repair(ctx);
-       reserve_block_for_lnf_repair(ctx);
-
        /*
         * If any extended attribute blocks' reference counts need to
         * be adjusted, either up (ctx->refcount_extra), or down
@@ -2105,11 +2178,6 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                ctx->ea_block_quota_inodes = 0;
        }
 
-       if (ctx->invalid_bitmaps) {
-               e2fsck_pass1_fix_lock(ctx);
-               handle_fs_bad_blocks(ctx);
-               e2fsck_pass1_fix_unlock(ctx);
-       }
 
        /* We don't need the block_ea_map any more */
        if (ctx->block_ea_map) {
@@ -2120,29 +2188,6 @@ void e2fsck_pass1_run(e2fsck_t ctx)
        /* We don't need the encryption policy => ID map any more */
        destroy_encryption_policy_map(ctx);
 
-       if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
-               clear_problem_context(&pctx);
-               e2fsck_pass1_fix_lock(ctx);
-               pctx.errcode = ext2fs_create_resize_inode(fs);
-               e2fsck_pass1_fix_unlock(ctx);
-               if (pctx.errcode) {
-                       if (!fix_problem(ctx, PR_1_RESIZE_INODE_CREATE,
-                                        &pctx)) {
-                               ctx->flags |= E2F_FLAG_ABORT;
-                               goto endit;
-                       }
-                       pctx.errcode = 0;
-               }
-               if (!pctx.errcode) {
-                       e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
-                                         "recreate inode");
-                       inode->i_mtime = ctx->now;
-                       e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
-                                          "recreate inode");
-               }
-               ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
-       }
-
        if (ctx->flags & E2F_FLAG_RESTART) {
                /*
                 * Only the master copy of the superblock and block
@@ -2167,13 +2212,6 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                }
        }
 
-       if (ctx->block_dup_map) {
-               if (ctx->options & E2F_OPT_PREEN) {
-                       clear_problem_context(&pctx);
-                       fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
-               }
-               e2fsck_pass1_dupblocks(ctx, block_buf);
-       }
        ctx->flags |= E2F_FLAG_ALLOC_OK;
 endit:
        e2fsck_use_inode_shortcuts(ctx, 0);
@@ -2428,10 +2466,10 @@ static errcode_t e2fsck_pass1_thread_prepare(e2fsck_t global_ctx, e2fsck_t *thre
        assert(global_ctx->inode_reg_map == NULL);
        assert(global_ctx->inodes_to_rebuild == NULL);
 
-       assert(global_ctx->block_found_map == NULL);
+       assert(global_ctx->block_found_map != NULL);
+       assert(global_ctx->block_metadata_map != NULL);
        assert(global_ctx->block_dup_map == NULL);
        assert(global_ctx->block_ea_map == NULL);
-       assert(global_ctx->block_metadata_map == NULL);
        assert(global_ctx->fs->dblist == NULL);
 
        retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &thread_context);
@@ -2595,10 +2633,8 @@ static int e2fsck_pass1_thread_join_one(e2fsck_t global_ctx, e2fsck_t thread_ctx
        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;
        ext2_icount_t inode_count = global_ctx->inode_count;
        ext2_icount_t inode_link_info = global_ctx->inode_link_info;
@@ -2641,10 +2677,8 @@ static int e2fsck_pass1_thread_join_one(e2fsck_t global_ctx, e2fsck_t thread_ctx
        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;
+       global_ctx->block_dup_map = block_dup_map;
        global_ctx->dir_info = dir_info;
        e2fsck_pass1_merge_dir_info(global_ctx, thread_ctx);
        global_ctx->dx_dir_info = dx_dir_info;
@@ -2741,25 +2775,10 @@ static int e2fsck_pass1_thread_join_one(e2fsck_t global_ctx, e2fsck_t thread_ctx
        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;
 }
@@ -2783,10 +2802,7 @@ static int e2fsck_pass1_thread_join(e2fsck_t global_ctx, e2fsck_t thread_ctx)
        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);
        e2fsck_free_dir_info(thread_ctx);
        ext2fs_free_icount(thread_ctx->inode_count);
        ext2fs_free_icount(thread_ctx->inode_link_info);
@@ -2967,6 +2983,7 @@ static void e2fsck_pass1_multithread(e2fsck_t global_ctx)
        errcode_t                        retval;
 
        pthread_mutex_init(&global_ctx->fs_fix_mutex, NULL);
+       pthread_mutex_init(&global_ctx->fs_block_map_mutex, NULL);
        retval = e2fsck_pass1_threads_start(&infos, num_threads, global_ctx);
        if (retval) {
                com_err(global_ctx->program_name, retval,
@@ -3018,17 +3035,25 @@ static int multiple_threads_supported(e2fsck_t ctx)
 
 void e2fsck_pass1(e2fsck_t ctx)
 {
+       errcode_t retval;
+       int multiple = 0;
 
        init_ext2_max_sizes();
+       retval = e2fsck_pass1_prepare(ctx);
+       if (retval)
+               return;
 #ifdef HAVE_PTHREAD
        if (multiple_threads_supported(ctx)) {
+               multiple = 1;
                e2fsck_pass1_multithread(ctx);
-               return;
+       } else {
+               fprintf(stderr, "Fall through single thread for pass1 "
+                               "because tdb could not handle properly\n");
        }
-       fprintf(stderr, "Fall through single thread for pass1 "
-                       "because tdb could not handle properly\n");
 #endif
-       e2fsck_pass1_run(ctx);
+       if (!multiple)
+               e2fsck_pass1_run(ctx);
+       e2fsck_pass1_post(ctx);
 }
 
 #undef FINISH_INODE_LOOP
@@ -3235,9 +3260,14 @@ static void alloc_imagic_map(e2fsck_t ctx)
  * WARNING: Assumes checks have already been done to make sure block
  * is valid.  This is true in both process_block and process_bad_block.
  */
-static _INLINE_ void mark_block_used(e2fsck_t ctx, blk64_t block)
+static _INLINE_ void mark_block_used_unlocked(e2fsck_t ctx, blk64_t block)
 {
-       struct          problem_context pctx;
+       struct problem_context pctx;
+       e2fsck_t global_ctx;
+
+       global_ctx = ctx->global_ctx;
+       if (!global_ctx)
+               global_ctx = ctx;
 
        clear_problem_context(&pctx);
 
@@ -3246,11 +3276,15 @@ static _INLINE_ void mark_block_used(e2fsck_t ctx, blk64_t block)
                    !(ctx->options & E2F_OPT_UNSHARE_BLOCKS)) {
                        return;
                }
-               if (!ctx->block_dup_map) {
+               /**
+                * this should be safe because this operation has
+                * been serialized by mutex.
+                */
+               if (!global_ctx->block_dup_map) {
                        pctx.errcode = e2fsck_allocate_block_bitmap(ctx->fs,
                                        _("multiply claimed block map"),
                                        EXT2FS_BMAP64_RBTREE, "block_dup_map",
-                                       &ctx->block_dup_map);
+                                       &global_ctx->block_dup_map);
                        if (pctx.errcode) {
                                pctx.num = 3;
                                fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
@@ -3260,12 +3294,20 @@ static _INLINE_ void mark_block_used(e2fsck_t ctx, blk64_t block)
                                return;
                        }
                }
-               ext2fs_fast_mark_block_bitmap2(ctx->block_dup_map, block);
+               ext2fs_fast_mark_block_bitmap2(global_ctx->block_dup_map, block);
        } else {
                ext2fs_fast_mark_block_bitmap2(ctx->block_found_map, block);
        }
 }
 
+static _INLINE_ void mark_block_used(e2fsck_t ctx, blk64_t block)
+{
+       e2fsck_pass1_block_map_lock(ctx);
+       mark_block_used_unlocked(ctx, block);
+       e2fsck_pass1_block_map_unlock(ctx);
+
+}
+
 /*
  * When cluster size is greater than one block, it is caller's responsibility
  * to make sure block parameter starts at a cluster boundary.
@@ -3273,14 +3315,16 @@ static _INLINE_ void mark_block_used(e2fsck_t ctx, blk64_t block)
 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))
+       e2fsck_pass1_block_map_lock(ctx);
+       if (ext2fs_test_block_bitmap_range2(ctx->block_found_map, block, num)) {
                ext2fs_mark_block_bitmap_range2(ctx->block_found_map, block, num);
-       else {
+       else {
                unsigned int i;
 
                for (i = 0; i < num; i += EXT2FS_CLUSTER_RATIO(ctx->fs))
-                       mark_block_used(ctx, block + i);
+                       mark_block_used_unlocked(ctx, block + i);
        }
+       e2fsck_pass1_block_map_unlock(ctx);
 }
 
 static errcode_t _INLINE_ e2fsck_write_ext_attr3(e2fsck_t ctx, blk64_t block,
@@ -4891,10 +4935,12 @@ static int process_bad_block(ext2_filsys fs,
        }
 
        if (blockcnt < 0) {
+               e2fsck_pass1_block_map_lock(ctx);
                if (ext2fs_test_block_bitmap2(p->fs_meta_blocks, blk)) {
                        p->bbcheck = 1;
                        if (fix_problem(ctx, PR_1_BB_FS_BLOCK, pctx)) {
                                *block_nr = 0;
+                               e2fsck_pass1_block_map_unlock(ctx);
                                return BLOCK_CHANGED;
                        }
                } else if (ext2fs_test_block_bitmap2(ctx->block_found_map,
@@ -4903,12 +4949,17 @@ static int process_bad_block(ext2_filsys fs,
                        if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK,
                                        pctx)) {
                                *block_nr = 0;
+                               e2fsck_pass1_block_map_unlock(ctx);
                                return BLOCK_CHANGED;
                        }
-                       if (e2fsck_should_abort(ctx))
+                       if (e2fsck_should_abort(ctx)) {
+                               e2fsck_pass1_block_map_unlock(ctx);
                                return BLOCK_ABORT;
-               } else
-                       mark_block_used(ctx, blk);
+                       }
+               } else {
+                       mark_block_used_unlocked(ctx, blk);
+               }
+               e2fsck_pass1_block_map_unlock(ctx);
                return 0;
        }
 #if 0
@@ -4921,10 +4972,13 @@ static int process_bad_block(ext2_filsys fs,
         * there's an overlap between the filesystem table blocks
         * (bitmaps and inode table) and the bad block list.
         */
+       e2fsck_pass1_block_map_lock(ctx);
        if (!ext2fs_test_block_bitmap2(ctx->block_found_map, blk)) {
                ext2fs_mark_block_bitmap2(ctx->block_found_map, blk);
+               e2fsck_pass1_block_map_unlock(ctx);
                return 0;
        }
+       e2fsck_pass1_block_map_unlock(ctx);
        /*
         * Try to find the where the filesystem block was used...
         */
@@ -5079,6 +5133,7 @@ static void new_table_block(e2fsck_t ctx, blk64_t first_block, dgrp_t group,
        fix_problem(ctx, (old_block ? PR_1_RELOC_FROM_TO :
                          PR_1_RELOC_TO), &pctx);
        pctx.blk2 = 0;
+       e2fsck_pass1_block_map_lock(ctx);
        for (i = 0; i < num; i++) {
                pctx.blk = i;
                ext2fs_mark_block_bitmap2(ctx->block_found_map, (*new_block)+i);
@@ -5099,6 +5154,7 @@ static void new_table_block(e2fsck_t ctx, blk64_t first_block, dgrp_t group,
                if (pctx.errcode)
                        fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx);
        }
+       e2fsck_pass1_block_map_unlock(ctx);
        ext2fs_free_mem(&buf);
 }
 
index 9470068..93cd96c 100644 (file)
@@ -575,23 +575,34 @@ void e2fsck_read_inode_full(e2fsck_t ctx, unsigned long ino,
 }
 
 #ifdef HAVE_PTHREAD
+#define e2fsck_get_lock_context(ctx)           \
+       e2fsck_t global_ctx = ctx->global_ctx;  \
+       if (!global_ctx)                        \
+               global_ctx = ctx;               \
+
 void e2fsck_pass1_fix_lock(e2fsck_t ctx)
 {
-       e2fsck_t global_ctx = ctx->global_ctx;
-       if (!global_ctx)
-               global_ctx = ctx;
-
+       e2fsck_get_lock_context(ctx);
        pthread_mutex_lock(&global_ctx->fs_fix_mutex);
 }
 
 void e2fsck_pass1_fix_unlock(e2fsck_t ctx)
 {
-       e2fsck_t global_ctx = ctx->global_ctx;
-       if (!global_ctx)
-               global_ctx = ctx;
-
+       e2fsck_get_lock_context(ctx);
        pthread_mutex_unlock(&global_ctx->fs_fix_mutex);
 }
+
+void e2fsck_pass1_block_map_lock(e2fsck_t ctx)
+{
+       e2fsck_get_lock_context(ctx);
+       pthread_mutex_lock(&global_ctx->fs_block_map_mutex);
+}
+
+void e2fsck_pass1_block_map_unlock(e2fsck_t ctx)
+{
+       e2fsck_get_lock_context(ctx);
+       pthread_mutex_unlock(&global_ctx->fs_block_map_mutex);
+}
 #else
 void e2fsck_pass1_fix_lock(e2fsck_t ctx)
 {
@@ -602,6 +613,15 @@ void e2fsck_pass1_fix_unlock(e2fsck_t ctx)
 {
 
 }
+
+void e2fsck_pass1_block_map_lock(e2fsck_t ctx)
+{
+
+}
+
+void e2fsck_pass1_block_map_unlock(e2fsck_t ctx)
+{
+}
 #endif
 
 void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
index 8d2acd2..4db68d9 100644 (file)
@@ -1,7 +1,7 @@
 ext2fs_open2: Bad magic number in super-block
 ../e2fsck/e2fsck: Superblock invalid, trying backup blocks...
+Pass 1: Checking inodes, blocks, and sizes
 [Thread 0] Scan group range [0, 2)
-[Thread 0] Pass 1: Checking inodes, blocks, and sizes
 [Thread 0] Scanned group range [0, 2), inodes 3008
 Pass 2: Checking directory structure
 Pass 3: Checking directory connectivity
index 8d2acd2..4db68d9 100644 (file)
@@ -1,7 +1,7 @@
 ext2fs_open2: Bad magic number in super-block
 ../e2fsck/e2fsck: Superblock invalid, trying backup blocks...
+Pass 1: Checking inodes, blocks, and sizes
 [Thread 0] Scan group range [0, 2)
-[Thread 0] Pass 1: Checking inodes, blocks, and sizes
 [Thread 0] Scanned group range [0, 2), inodes 3008
 Pass 2: Checking directory structure
 Pass 3: Checking directory connectivity
index f85a338..eda2fca 100644 (file)
@@ -1,7 +1,7 @@
 ext2fs_open2: Bad magic number in super-block
 ../e2fsck/e2fsck: Superblock invalid, trying backup blocks...
+Pass 1: Checking inodes, blocks, and sizes
 [Thread 0] Scan group range [0, 2)
-[Thread 0] Pass 1: Checking inodes, blocks, and sizes
 [Thread 0] Scanned group range [0, 2), inodes 3008
 Pass 2: Checking directory structure
 Pass 3: Checking directory connectivity