aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLi Xi <lixi@ddn.com>2019-09-05 19:40:36 +0800
committerTheodore Ts'o <tytso@mit.edu>2021-01-25 15:17:30 -0500
commita8b483a1e7987a6dddc32bc82db06f649d245630 (patch)
tree76995fd69bfa18cb02f1b922ba4494e07c729c15
parentf3c2256490297201c63139ba0fea5c6b09bca3cf (diff)
downloade2fsprogs-a8b483a1e7987a6dddc32bc82db06f649d245630.tar.gz
e2fsck: add debug codes for multiple threads
These debug codes are added to run the multiple pass1 check thread one by one in order. If all the codes are correct, fsck of multiple threads should have exactly the same outcome with single thread. 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/e2fsck.h16
-rw-r--r--e2fsck/pass1.c29
2 files changed, 45 insertions, 0 deletions
diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h
index 531a353e9..349395b1e 100644
--- a/e2fsck/e2fsck.h
+++ b/e2fsck/e2fsck.h
@@ -450,6 +450,18 @@ struct e2fsck_struct {
};
#ifdef HAVE_PTHREAD
+#ifdef DEBUG_THREADS
+/*
+ * Enabling DEBUG_THREADS would cause the parallel
+ * fsck threads run sequentially.
+ */
+struct e2fsck_thread_debug {
+ pthread_mutex_t etd_mutex;
+ pthread_cond_t etd_cond;
+ int etd_finished_threads;
+};
+#endif
+
struct e2fsck_thread_info {
/* ID returned by pthread_create() */
pthread_t eti_thread_id;
@@ -459,7 +471,11 @@ struct e2fsck_thread_info {
int eti_started;
/* Context used for this thread */
e2fsck_t eti_thread_ctx;
+#ifdef DEBUG_THREADS
+ struct e2fsck_thread_debug *eti_debug;
+#endif
};
+
#endif
/* Data structures to evaluate whether an extent tree needs rebuilding. */
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index b01b415a6..e0a671b06 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -2641,6 +2641,18 @@ static void *e2fsck_pass1_thread(void *arg)
{
struct e2fsck_thread_info *info = arg;
e2fsck_t thread_ctx = info->eti_thread_ctx;
+#ifdef DEBUG_THREADS
+ struct e2fsck_thread_debug *thread_debug = info->eti_debug;
+#endif
+
+#ifdef DEBUG_THREADS
+ pthread_mutex_lock(&thread_debug->etd_mutex);
+ while (info->eti_thread_index > thread_debug->etd_finished_threads) {
+ pthread_cond_wait(&thread_debug->etd_cond,
+ &thread_debug->etd_mutex);
+ }
+ pthread_mutex_unlock(&thread_debug->etd_mutex);
+#endif
#ifdef HAVE_SETJMP_H
/*
@@ -2665,6 +2677,14 @@ out:
thread_ctx->thread_info.et_group_start,
thread_ctx->thread_info.et_group_end,
thread_ctx->thread_info.et_inode_number);
+
+#ifdef DEBUG_THREADS
+ pthread_mutex_lock(&thread_debug->etd_mutex);
+ thread_debug->etd_finished_threads++;
+ pthread_cond_broadcast(&thread_debug->etd_cond);
+ pthread_mutex_unlock(&thread_debug->etd_mutex);
+#endif
+
return NULL;
}
@@ -2678,6 +2698,12 @@ static int e2fsck_pass1_threads_start(struct e2fsck_thread_info **pinfo,
struct e2fsck_thread_info *tmp_pinfo;
int i;
e2fsck_t thread_ctx;
+#ifdef DEBUG_THREADS
+ struct e2fsck_thread_debug thread_debug =
+ {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0};
+
+ thread_debug.etd_finished_threads = 0;
+#endif
retval = pthread_attr_init(&attr);
if (retval) {
@@ -2698,6 +2724,9 @@ static int e2fsck_pass1_threads_start(struct e2fsck_thread_info **pinfo,
for (i = 0; i < num_threads; i++) {
tmp_pinfo = &infos[i];
tmp_pinfo->eti_thread_index = i;
+#ifdef DEBUG_THREADS
+ tmp_pinfo->eti_debug = &thread_debug;
+#endif
retval = e2fsck_pass1_thread_prepare(global_ctx, &thread_ctx,
i, num_threads);
if (retval) {