Whamcloud - gitweb
e2fsck: allow admin specify number of threads
authorWang Shilong <wshilong@ddn.com>
Mon, 9 Mar 2020 07:11:10 +0000 (15:11 +0800)
committerAndreas Dilger <adilger@whamcloud.com>
Mon, 19 Sep 2022 23:16:08 +0000 (17:16 -0600)
-m option is introduced to specify number of threads for pfsck.

E2fsprogs-commit: e3bb22efe1c62f8c81686e1d8d065a4943e14bd3

Change-Id: I856d06e0c62f23bdd84e7b6bf53cdc4a46dd58da
Signed-off-by: Wang Shilong <wshilong@ddn.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
e2fsck/e2fsck.h
e2fsck/pass1.c
e2fsck/unix.c
tests/f_multithread/script
tests/f_multithread_completion/script
tests/f_multithread_logfile/script
tests/f_multithread_no/script
tests/f_multithread_preen/script
tests/f_multithread_yes/script

index 2cb7c5d..5192368 100644 (file)
@@ -490,6 +490,7 @@ struct e2fsck_struct {
        /* Fast commit replay state */
        struct e2fsck_fc_replay_state fc_replay_state;
 #ifdef HAVE_PTHREAD
+       __u32                    fs_num_threads;
        /* serialize fix operation for multiple threads */
        pthread_mutex_t          fs_fix_mutex;
        /* protect block_found_map, block_dup_map */
@@ -727,6 +728,7 @@ int check_backup_super_block(e2fsck_t ctx);
 void check_resize_inode(e2fsck_t ctx);
 
 /* util.c */
+#define E2FSCK_MAX_THREADS     (65536)
 extern void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned long size,
                                    const char *description);
 extern int ask(e2fsck_t ctx, const char * string, int def);
index bf5ea21..1b927ba 100644 (file)
@@ -1199,6 +1199,97 @@ static int e2fsck_should_abort(e2fsck_t ctx)
        return 0;
 }
 
+static void init_ext2_max_sizes()
+{
+       int     i;
+       __u64   max_sizes;
+
+       /*
+        * Init ext2_max_sizes which will be immutable and shared between
+        * threads
+        */
+#define EXT2_BPP(bits) (1ULL << ((bits) - 2))
+
+       for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
+               max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
+               max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
+               max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
+               max_sizes = (max_sizes * (1UL << i));
+               ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
+       }
+#undef EXT2_BPP
+}
+
+#ifdef HAVE_PTHREAD
+/* TODO: tdb needs to be handled properly for multiple threads*/
+static int multiple_threads_supported(e2fsck_t ctx)
+{
+#ifdef CONFIG_TDB
+       unsigned int            threshold;
+       ext2_ino_t              num_dirs;
+       errcode_t               retval;
+       char                    *tdb_dir;
+       int                     enable;
+
+       profile_get_string(ctx->profile, "scratch_files", "directory", 0, 0,
+                          &tdb_dir);
+       profile_get_uint(ctx->profile, "scratch_files",
+                        "numdirs_threshold", 0, 0, &threshold);
+       profile_get_boolean(ctx->profile, "scratch_files",
+                           "icount", 0, 1, &enable);
+
+       retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
+       if (retval)
+               num_dirs = 1024;        /* Guess */
+
+       /* tdb is unsupported now */
+       if (enable && tdb_dir && !access(tdb_dir, W_OK) &&
+           (!threshold || num_dirs > threshold))
+               return 0;
+#endif
+       return 1;
+}
+
+/**
+ * Even though we could specify number of threads,
+ * but it might be more than the whole filesystem
+ * block groups, correct it here.
+ */
+static void e2fsck_pass1_set_thread_num(e2fsck_t ctx)
+{
+       unsigned flexbg_size = 1;
+       ext2_filsys fs = ctx->fs;
+       int num_threads = ctx->fs_num_threads;
+       int max_threads;
+
+       if (num_threads < 1) {
+               num_threads = 1;
+               goto out;
+       }
+
+       if (!multiple_threads_supported(ctx)) {
+               num_threads = 1;
+               fprintf(stderr, "Fall through single thread for pass1 "
+                       "because tdb could not handle properly\n");
+               goto out;
+       }
+
+       if (ext2fs_has_feature_flex_bg(fs->super))
+               flexbg_size = 1 << fs->super->s_log_groups_per_flex;
+       max_threads = fs->group_desc_count / flexbg_size;
+       if (max_threads == 0)
+               max_threads = 1;
+
+       if (num_threads > max_threads) {
+               fprintf(stderr, "Use max possible thread num: %d instead\n",
+                               max_threads);
+               num_threads = max_threads;
+       }
+out:
+       ctx->fs_num_threads = num_threads;
+}
+#endif
+
 /*
  * We need call mark_table_blocks() before multiple
  * thread start, since all known system blocks should be
@@ -1209,6 +1300,11 @@ static errcode_t e2fsck_pass1_prepare(e2fsck_t ctx)
        struct problem_context pctx;
        ext2_filsys fs = ctx->fs;
 
+       init_ext2_max_sizes();
+#ifdef HAVE_PTHREAD
+       e2fsck_pass1_set_thread_num(ctx);
+#endif
+
        clear_problem_context(&pctx);
        if (!(ctx->options & E2F_OPT_PREEN))
                fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
@@ -2244,27 +2340,6 @@ endit:
                ctx->invalid_bitmaps++;
 }
 
-static void init_ext2_max_sizes()
-{
-       int     i;
-       __u64   max_sizes;
-
-       /*
-        * Init ext2_max_sizes which will be immutable and shared between
-        * threads
-        */
-#define EXT2_BPP(bits) (1ULL << ((bits) - 2))
-
-       for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
-               max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
-               max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
-               max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
-               max_sizes = (max_sizes * (1UL << i));
-               ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
-       }
-#undef EXT2_BPP
-}
-
 #ifdef HAVE_PTHREAD
 static errcode_t e2fsck_pass1_copy_bitmap(ext2_filsys fs, ext2fs_generic_bitmap *src,
                                          ext2fs_generic_bitmap *dest)
@@ -3256,9 +3331,9 @@ static int e2fsck_pass1_threads_start(struct e2fsck_thread_info **pinfo,
 
 static void e2fsck_pass1_multithread(e2fsck_t global_ctx)
 {
-       struct e2fsck_thread_info       *infos = NULL;
-       int                              num_threads = 1;
-       errcode_t                        retval;
+       struct e2fsck_thread_info *infos = NULL;
+       int num_threads = global_ctx->fs_num_threads;
+       errcode_t retval;
 
        retval = e2fsck_pass1_threads_start(&infos, num_threads, global_ctx);
        if (retval) {
@@ -3280,54 +3355,22 @@ out_abort:
 }
 #endif
 
-/* TODO: tdb needs to be handled properly for multiple threads*/
-static int multiple_threads_supported(e2fsck_t ctx)
-{
-#ifdef CONFIG_TDB
-       unsigned int            threshold;
-       ext2_ino_t              num_dirs;
-       errcode_t               retval;
-       char                    *tdb_dir;
-       int                     enable;
-
-       profile_get_string(ctx->profile, "scratch_files", "directory", 0, 0,
-                          &tdb_dir);
-       profile_get_uint(ctx->profile, "scratch_files",
-                        "numdirs_threshold", 0, 0, &threshold);
-       profile_get_boolean(ctx->profile, "scratch_files",
-                           "icount", 0, 1, &enable);
-
-       retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
-       if (retval)
-               num_dirs = 1024;        /* Guess */
-
-       /* tdb is unsupported now */
-       if (enable && tdb_dir && !access(tdb_dir, W_OK) &&
-           (!threshold || num_dirs > threshold))
-               return 0;
- #endif
-       return 1;
-}
-
 void e2fsck_pass1(e2fsck_t ctx)
 {
        errcode_t retval;
-       int multiple = 0;
+       int need_single = 1;
 
-       init_ext2_max_sizes();
        retval = e2fsck_pass1_prepare(ctx);
        if (retval)
                return;
 #ifdef HAVE_PTHREAD
-       if (multiple_threads_supported(ctx)) {
-               multiple = 1;
+       if (ctx->fs_num_threads > 1 ||
+           ctx->options & E2F_OPT_MULTITHREAD) {
+               need_single = 0;
                e2fsck_pass1_multithread(ctx);
-       } else {
-               fprintf(stderr, "Fall through single thread for pass1 "
-                               "because tdb could not handle properly\n");
        }
 #endif
-       if (!multiple)
+       if (need_single)
                e2fsck_pass1_run(ctx);
        e2fsck_pass1_post(ctx);
 }
index d253525..0b80264 100644 (file)
@@ -827,6 +827,10 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
 #ifdef CONFIG_JBD_DEBUG
        char            *jbd_debug;
 #endif
+#ifdef HAVE_PTHREAD
+       char            *pm;
+       unsigned long   thread_num;
+#endif
        unsigned long long phys_mem_kb, blk;
 
        retval = e2fsck_allocate_context(&ctx);
@@ -859,7 +863,7 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
        ctx->readahead_kb = ~0ULL;
 
 #ifdef HAVE_PTHREAD
-       while ((c = getopt(argc, argv, "pamnyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDkz:")) != EOF)
+       while ((c = getopt(argc, argv, "pam:nyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDkz:")) != EOF)
 #else
        while ((c = getopt(argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDkz:")) != EOF)
 #endif
@@ -905,7 +909,18 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
                        break;
 #ifdef HAVE_PTHREAD
                case 'm':
+                       thread_num = strtoul(optarg, &pm, 0);
+                       if (*pm)
+                               fatal_error(ctx,
+                                       _("Invalid multiple thread num.\n"));
+                       if (thread_num > E2FSCK_MAX_THREADS) {
+                               fprintf(stderr,
+                                       _("threads %lu too large (max %lu)\n"),
+                                       thread_num, E2FSCK_MAX_THREADS);
+                               fatal_error(ctx, 0);
+                       }
                        ctx->options |= E2F_OPT_MULTITHREAD;
+                       ctx->fs_num_threads = thread_num;
                        break;
 #endif
                case 'n':
index 0fe96cd..83cd0f0 100644 (file)
@@ -1,4 +1,4 @@
-FSCK_OPT="-fy -m"
+FSCK_OPT="-fy -m1"
 SECOND_FSCK_OPT=-yf
 
 . $cmd_dir/run_e2fsck
index bf23cd6..0ec1381 100644 (file)
@@ -1,4 +1,4 @@
-FSCK_OPT="-fy -m -C 1"
+FSCK_OPT="-fy -m1 -C 1"
 SECOND_FSCK_OPT=-yf
 
 . $cmd_dir/run_e2fsck
index 4f9ca6f..dbb6531 100644 (file)
@@ -1,5 +1,5 @@
 LOG_FNAME="f_multithread_logfile_xxx"
-FSCK_OPT="-fy -m -y -E log_filename=$LOG_FNAME"
+FSCK_OPT="-fy -m1 -y -E log_filename=$LOG_FNAME"
 SKIP_VERIFY="true"
 ONE_PASS_ONLY="true"
 SKIP_CLEANUP="true"
index b93deb3..db791e1 100644 (file)
@@ -1,4 +1,4 @@
-FSCK_OPT="-fn -m"
+FSCK_OPT="-fn -m1"
 SECOND_FSCK_OPT=-yf
 
 . $cmd_dir/run_e2fsck
index ecb79cd..8965f4a 100644 (file)
@@ -1,4 +1,4 @@
-FSCK_OPT="-fp -m"
+FSCK_OPT="-fp -m1"
 SECOND_FSCK_OPT=-yf
 
 . $cmd_dir/run_e2fsck
index 38891f6..8b4aa9b 100644 (file)
@@ -1,4 +1,4 @@
-FSCK_OPT="-f -m"
+FSCK_OPT="-f -m1"
 SECOND_FSCK_OPT=-yf
 
 . $cmd_dir/run_e2fsck