Whamcloud - gitweb
e2fsck: wait fix thread finish before checking
authorWang Shilong <wshilong@ddn.com>
Thu, 14 May 2020 14:16:50 +0000 (22:16 +0800)
committerAndreas Dilger <adilger@whamcloud.com>
Mon, 19 Sep 2022 23:16:09 +0000 (17:16 -0600)
Before proceeding next inodes, waitting existed
fixing finished.

E2fsprogs-commit: ae4a78493b16d01d7dbe628ec9064216f960bd16

Change-Id: I159082381e66bd51b3558a65ef45e936aa741370
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.c
e2fsck/e2fsck.h
e2fsck/pass1.c
e2fsck/util.c

index 1e295e3..a5150da 100644 (file)
@@ -187,6 +187,9 @@ errcode_t e2fsck_reset_context(e2fsck_t ctx)
        ctx->fs_fragmented_dir = 0;
        ctx->large_files = 0;
        ctx->large_dirs = 0;
+#ifdef HAVE_PTHREAD
+       ctx->fs_need_locking = 0;
+#endif
 
        for (i=0; i < MAX_EXTENT_DEPTH_COUNT; i++)
                ctx->extent_depth_count[i] = 0;
index 5192368..8fe0f91 100644 (file)
@@ -491,8 +491,9 @@ struct e2fsck_struct {
        struct e2fsck_fc_replay_state fc_replay_state;
 #ifdef HAVE_PTHREAD
        __u32                    fs_num_threads;
+       int                      fs_need_locking;
        /* serialize fix operation for multiple threads */
-       pthread_mutex_t          fs_fix_mutex;
+       pthread_rwlock_t         fs_fix_rwlock;
        /* protect block_found_map, block_dup_map */
        pthread_rwlock_t         fs_block_map_rwlock;
 #endif
@@ -554,6 +555,8 @@ extern int e2fsck_strnlen(const char * s, int count);
 
 extern void e2fsck_pass1(e2fsck_t ctx);
 extern void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
+extern void e2fsck_pass1_check_lock(e2fsck_t ctx);
+extern void e2fsck_pass1_check_unlock(e2fsck_t ctx);
 extern void e2fsck_pass2(e2fsck_t ctx);
 extern void e2fsck_pass3(e2fsck_t ctx);
 extern void e2fsck_pass4(e2fsck_t ctx);
index 2d62e0c..e858286 100644 (file)
@@ -991,8 +991,10 @@ static void finish_processing_inode(e2fsck_t ctx, ext2_ino_t ino,
 #define FINISH_INODE_LOOP(ctx, ino, pctx, failed_csum) \
        do { \
                finish_processing_inode((ctx), (ino), (pctx), (failed_csum)); \
-               if ((ctx)->flags & E2F_FLAG_ABORT) \
+               if ((ctx)->flags & E2F_FLAG_ABORT) { \
+                       e2fsck_pass1_check_unlock(ctx); \
                        return; \
+               } \
        } while (0)
 
 static int could_be_block_map(ext2_filsys fs, struct ext2_inode *inode)
@@ -1374,8 +1376,10 @@ static errcode_t e2fsck_pass1_prepare(e2fsck_t ctx)
                ext2fs_mark_block_bitmap2(ctx->block_found_map,
                                          fs->super->s_mmp_block);
 #ifdef HAVE_PTHREAD
-       pthread_mutex_init(&ctx->fs_fix_mutex, NULL);
+       pthread_rwlock_init(&ctx->fs_fix_rwlock, NULL);
        pthread_rwlock_init(&ctx->fs_block_map_rwlock, NULL);
+       if (ctx->fs_num_threads > 1)
+               ctx->fs_need_locking = 1;
 #endif
 
        return 0;
@@ -1662,6 +1666,7 @@ void e2fsck_pass1_run(e2fsck_t ctx)
 #endif
 
        while (1) {
+               e2fsck_pass1_check_lock(ctx);
                if (ino % (fs->super->s_inodes_per_group * 4) == 1) {
                        if (e2fsck_mmp_update(fs))
                                fatal_error(ctx, 0);
@@ -1672,8 +1677,10 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                if (ino > ino_threshold)
                        pass1_readahead(ctx, &ra_group, &ino_threshold);
                ehandler_operation(old_op);
-               if (e2fsck_should_abort(ctx))
+               if (e2fsck_should_abort(ctx)) {
+                       e2fsck_pass1_check_unlock(ctx);
                        goto endit;
+               }
                if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
                        /*
                         * If badblocks says badblocks is bad, offer to clear
@@ -1694,27 +1701,45 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                                        fix_problem(ctx, PR_1_ISCAN_ERROR,
                                                    &pctx);
                                        ctx->flags |= E2F_FLAG_ABORT;
+                                       e2fsck_pass1_check_unlock(ctx);
+                                       goto endit;
                                } else
                                        ctx->flags |= E2F_FLAG_RESTART;
-                               goto endit;
+                               err = ext2fs_inode_scan_goto_blockgroup(scan,
+                                                                       0);
+                               if (err) {
+                                       fix_problem(ctx, PR_1_ISCAN_ERROR,
+                                                   &pctx);
+                                       ctx->flags |= E2F_FLAG_ABORT;
+                                       e2fsck_pass1_check_unlock(ctx);
+                                       goto endit;
+                               }
+                               e2fsck_pass1_check_unlock(ctx);
+                               continue;
                        }
                        if (!ctx->inode_bb_map)
                                alloc_bb_map(ctx);
                        ext2fs_mark_inode_bitmap2(ctx->inode_bb_map, ino);
                        ext2fs_mark_inode_bitmap2(ctx->inode_used_map, ino);
+                       e2fsck_pass1_check_unlock(ctx);
                        continue;
                }
-               if (pctx.errcode == EXT2_ET_SCAN_FINISHED)
+               if (pctx.errcode == EXT2_ET_SCAN_FINISHED) {
+                       e2fsck_pass1_check_unlock(ctx);
                        break;
+               }
                if (pctx.errcode &&
                    pctx.errcode != EXT2_ET_INODE_CSUM_INVALID &&
                    pctx.errcode != EXT2_ET_INODE_IS_GARBAGE) {
                        fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
                        ctx->flags |= E2F_FLAG_ABORT;
+                       e2fsck_pass1_check_unlock(ctx);
                        goto endit;
                }
-               if (!ino)
+               if (!ino) {
+                       e2fsck_pass1_check_unlock(ctx);
                        break;
+               }
 #ifdef HAVE_PTHREAD
                if (ctx->global_ctx)
                        ctx->thread_info.et_inode_number++;
@@ -1767,6 +1792,7 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                                pctx.num = inode->i_links_count;
                                fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
                                ctx->flags |= E2F_FLAG_ABORT;
+                               e2fsck_pass1_check_unlock(ctx);
                                goto endit;
                        }
                } else if ((ino >= EXT2_FIRST_INODE(fs->super)) &&
@@ -1781,6 +1807,7 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                                }
                        }
                        FINISH_INODE_LOOP(ctx, ino, &pctx, failed_csum);
+                       e2fsck_pass1_check_unlock(ctx);
                        continue;
                }
 
@@ -1801,6 +1828,7 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                                                               &pctx);
                        if (res < 0) {
                                /* skip FINISH_INODE_LOOP */
+                               e2fsck_pass1_check_unlock(ctx);
                                continue;
                        }
                }
@@ -1821,6 +1849,7 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                        } else if (fix_problem(ctx, PR_1_INLINE_DATA_SET, &pctx)) {
                                e2fsck_clear_inode(ctx, ino, inode, 0, "pass1");
                                /* skip FINISH_INODE_LOOP */
+                               e2fsck_pass1_check_unlock(ctx);
                                continue;
                        }
                }
@@ -1865,6 +1894,7 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                                        if (err) {
                                                pctx.errcode = err;
                                                ctx->flags |= E2F_FLAG_ABORT;
+                                               e2fsck_pass1_check_unlock(ctx);
                                                goto endit;
                                        }
                                        inode->i_flags &= ~EXT4_INLINE_DATA_FL;
@@ -1879,6 +1909,7 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                                /* Some other kind of non-xattr error? */
                                pctx.errcode = err;
                                ctx->flags |= E2F_FLAG_ABORT;
+                               e2fsck_pass1_check_unlock(ctx);
                                goto endit;
                        }
                }
@@ -1916,6 +1947,7 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                                        ext2fs_mark_inode_bitmap2(ctx->inode_used_map,
                                                                 ino);
                                /* skip FINISH_INODE_LOOP */
+                               e2fsck_pass1_check_unlock(ctx);
                                continue;
                        }
                }
@@ -1979,6 +2011,7 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                                pctx.num = 4;
                                fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
                                ctx->flags |= E2F_FLAG_ABORT;
+                               e2fsck_pass1_check_unlock(ctx);
                                goto endit;
                        }
                        pb.ino = EXT2_BAD_INO;
@@ -1996,16 +2029,19 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                        if (pctx.errcode) {
                                fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
                                ctx->flags |= E2F_FLAG_ABORT;
+                               e2fsck_pass1_check_unlock(ctx);
                                goto endit;
                        }
                        if (pb.bbcheck)
                                if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
                                ctx->flags |= E2F_FLAG_ABORT;
+                               e2fsck_pass1_check_unlock(ctx);
                                goto endit;
                        }
                        ext2fs_mark_inode_bitmap2(ctx->inode_used_map, ino);
                        clear_problem_context(&pctx);
                        FINISH_INODE_LOOP(ctx, ino, &pctx, failed_csum);
+                       e2fsck_pass1_check_unlock(ctx);
                        continue;
                } else if (ino == EXT2_ROOT_INO) {
                        /*
@@ -2047,6 +2083,7 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                                }
                                check_blocks(ctx, &pctx, block_buf, NULL);
                                FINISH_INODE_LOOP(ctx, ino, &pctx, failed_csum);
+                               e2fsck_pass1_check_unlock(ctx);
                                continue;
                        }
                        if ((inode->i_links_count ||
@@ -2074,6 +2111,7 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                                }
                                check_blocks(ctx, &pctx, block_buf, NULL);
                                FINISH_INODE_LOOP(ctx, ino, &pctx, failed_csum);
+                               e2fsck_pass1_check_unlock(ctx);
                                continue;
                        }
                        if ((inode->i_links_count ||
@@ -2112,11 +2150,13 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                        }
                        check_blocks(ctx, &pctx, block_buf, NULL);
                        FINISH_INODE_LOOP(ctx, ino, &pctx, failed_csum);
+                       e2fsck_pass1_check_unlock(ctx);
                        continue;
                }
 
                if (!inode->i_links_count) {
                        FINISH_INODE_LOOP(ctx, ino, &pctx, failed_csum);
+                       e2fsck_pass1_check_unlock(ctx);
                        continue;
                }
                /*
@@ -2226,12 +2266,14 @@ void e2fsck_pass1_run(e2fsck_t ctx)
                        ctx->fs_symlinks_count++;
                        if (inode->i_flags & EXT4_INLINE_DATA_FL) {
                                FINISH_INODE_LOOP(ctx, ino, &pctx, failed_csum);
+                               e2fsck_pass1_check_unlock(ctx);
                                continue;
                        } else if (ext2fs_is_fast_symlink(inode)) {
                                ctx->fs_fast_symlinks_count++;
                                check_blocks(ctx, &pctx, block_buf,
                                             &ea_ibody_quota);
                                FINISH_INODE_LOOP(ctx, ino, &pctx, failed_csum);
+                               e2fsck_pass1_check_unlock(ctx);
                                continue;
                        }
                }
@@ -2279,16 +2321,21 @@ void e2fsck_pass1_run(e2fsck_t ctx)
 
                FINISH_INODE_LOOP(ctx, ino, &pctx, failed_csum);
 
-               if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
+               if (e2fsck_should_abort(ctx)) {
+                       e2fsck_pass1_check_unlock(ctx);
                        goto endit;
+               }
 
                if (process_inode_count >= ctx->process_inode_size) {
                        process_inodes(ctx, block_buf, inodes_to_process,
                                       &process_inode_count);
 
-                       if (e2fsck_should_abort(ctx))
+                       if (e2fsck_should_abort(ctx)) {
+                               e2fsck_pass1_check_unlock(ctx);
                                goto endit;
+                       }
                }
+               e2fsck_pass1_check_unlock(ctx);
        }
        process_inodes(ctx, block_buf, inodes_to_process,
                       &process_inode_count);
@@ -3363,6 +3410,8 @@ void e2fsck_pass1(e2fsck_t ctx)
                need_single = 0;
                e2fsck_pass1_multithread(ctx);
        }
+       /* No lock is needed at this time */
+       ctx->fs_need_locking = 0;
 #endif
        if (need_single)
                e2fsck_pass1_run(ctx);
index 5714576..b7c1e7a 100644 (file)
@@ -82,7 +82,8 @@ void fatal_error(e2fsck_t ctx, const char *msg)
        }
 out:
        ctx->flags |= E2F_FLAG_ABORT;
-       if (ctx->flags & E2F_FLAG_SETJMP_OK)
+       if (!(ctx->options & E2F_OPT_MULTITHREAD) &&
+           ctx->flags & E2F_FLAG_SETJMP_OK)
                longjmp(ctx->abort_loc, 1);
        if (ctx->logf)
                fprintf(ctx->logf, "Exit status: %d\n", exit_value);
@@ -580,38 +581,79 @@ void e2fsck_read_inode_full(e2fsck_t ctx, unsigned long ino,
        if (!global_ctx)                        \
                global_ctx = ctx;               \
 
+/**
+ * before we hold write lock, read lock should
+ * has been held.
+ */
 void e2fsck_pass1_fix_lock(e2fsck_t ctx)
 {
+       int err;
+
+       if (!ctx->fs_need_locking)
+               return;
+
        e2fsck_get_lock_context(ctx);
-       pthread_mutex_lock(&global_ctx->fs_fix_mutex);
+       err = pthread_rwlock_trywrlock(&global_ctx->fs_fix_rwlock);
+       assert(err != 0);
+       pthread_rwlock_unlock(&global_ctx->fs_fix_rwlock);
+       pthread_rwlock_wrlock(&global_ctx->fs_fix_rwlock);
 }
 
 void e2fsck_pass1_fix_unlock(e2fsck_t ctx)
 {
+       if (!ctx->fs_need_locking)
+               return;
        e2fsck_get_lock_context(ctx);
-       pthread_mutex_unlock(&global_ctx->fs_fix_mutex);
+       /* unlock write lock */
+       pthread_rwlock_unlock(&global_ctx->fs_fix_rwlock);
+       /* get read lock again */
+       pthread_rwlock_rdlock(&global_ctx->fs_fix_rwlock);
+}
+
+void e2fsck_pass1_check_lock(e2fsck_t ctx)
+{
+       if (!ctx->fs_need_locking)
+               return;
+       e2fsck_get_lock_context(ctx);
+       pthread_rwlock_rdlock(&global_ctx->fs_fix_rwlock);
+}
+
+void e2fsck_pass1_check_unlock(e2fsck_t ctx)
+{
+       if (!ctx->fs_need_locking)
+               return;
+       e2fsck_get_lock_context(ctx);
+       pthread_rwlock_unlock(&global_ctx->fs_fix_rwlock);
 }
 
 void e2fsck_pass1_block_map_w_lock(e2fsck_t ctx)
 {
+       if (!ctx->fs_need_locking)
+               return;
        e2fsck_get_lock_context(ctx);
        pthread_rwlock_wrlock(&global_ctx->fs_block_map_rwlock);
 }
 
 void e2fsck_pass1_block_map_w_unlock(e2fsck_t ctx)
 {
+       if (!ctx->fs_need_locking)
+               return;
        e2fsck_get_lock_context(ctx);
        pthread_rwlock_unlock(&global_ctx->fs_block_map_rwlock);
 }
 
 void e2fsck_pass1_block_map_r_lock(e2fsck_t ctx)
 {
+       if (!ctx->fs_need_locking)
+               return;
        e2fsck_get_lock_context(ctx);
        pthread_rwlock_rdlock(&global_ctx->fs_block_map_rwlock);
 }
 
 void e2fsck_pass1_block_map_r_unlock(e2fsck_t ctx)
 {
+       if (!ctx->fs_need_locking)
+               return;
        e2fsck_get_lock_context(ctx);
        pthread_rwlock_unlock(&global_ctx->fs_block_map_rwlock);
  }
@@ -625,6 +667,14 @@ void e2fsck_pass1_fix_unlock(e2fsck_t ctx)
 {
 
 }
+void e2fsck_pass1_check_lock(e2fsck_t ctx)
+{
+
+}
+void e2fsck_pass1_check_unlock(e2fsck_t ctx)
+{
+
+}
 void e2fsck_pass1_block_map_w_lock(e2fsck_t ctx)
 {