aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSong Liu <songliubraving@fb.com>2017-11-20 01:17:01 -0500
committerShaohua Li <shli@fb.com>2017-12-11 11:52:34 -0500
commitd5d885fd514fcebc9da5503c88aa0112df7514ef (patch)
tree71cf428b0bba2cf5c1afd32b8a32fc3ab5724708
parent50c4c4e268a2d7a3e58ebb698ac74da0de40ae36 (diff)
md: introduce new personality funciton start()
In do_md_run(), md threads should not wake up until the array is fully initialized in md_run(). However, in raid5_run(), raid5-cache may wake up mddev->thread to flush stripes that need to be written back. This design doesn't break badly right now. But it could lead to bad bug in the future. This patch tries to resolve this problem by splitting start up work into two personality functions, run() and start(). Tasks that do not require the md threads should go into run(), while task that require the md threads go into start(). r5l_load_log() is moved to raid5_start(), so it is not called until the md threads are started in do_md_run(). Signed-off-by: Song Liu <songliubraving@fb.com> Signed-off-by: Shaohua Li <shli@fb.com>
-rw-r--r--drivers/md/dm-raid.c9
-rw-r--r--drivers/md/md.c26
-rw-r--r--drivers/md/md.h8
-rw-r--r--drivers/md/raid5-cache.c22
-rw-r--r--drivers/md/raid5-log.h1
-rw-r--r--drivers/md/raid5.c10
6 files changed, 65 insertions, 11 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 6319d846e0ad..e5ef0757fe23 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -3151,6 +3151,14 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv)
3151 goto bad; 3151 goto bad;
3152 } 3152 }
3153 3153
3154 r = md_start(&rs->md);
3155
3156 if (r) {
3157 ti->error = "Failed to start raid array";
3158 mddev_unlock(&rs->md);
3159 goto bad_md_start;
3160 }
3161
3154 rs->callbacks.congested_fn = raid_is_congested; 3162 rs->callbacks.congested_fn = raid_is_congested;
3155 dm_table_add_target_callbacks(ti->table, &rs->callbacks); 3163 dm_table_add_target_callbacks(ti->table, &rs->callbacks);
3156 3164
@@ -3198,6 +3206,7 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv)
3198 mddev_unlock(&rs->md); 3206 mddev_unlock(&rs->md);
3199 return 0; 3207 return 0;
3200 3208
3209bad_md_start:
3201bad_journal_mode_set: 3210bad_journal_mode_set:
3202bad_stripe_cache: 3211bad_stripe_cache:
3203bad_check_reshape: 3212bad_check_reshape:
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 4e4dee0ec2de..a71adb3c34b9 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -5560,11 +5560,6 @@ int md_run(struct mddev *mddev)
5560 if (start_readonly && mddev->ro == 0) 5560 if (start_readonly && mddev->ro == 0)
5561 mddev->ro = 2; /* read-only, but switch on first write */ 5561 mddev->ro = 2; /* read-only, but switch on first write */
5562 5562
5563 /*
5564 * NOTE: some pers->run(), for example r5l_recovery_log(), wakes
5565 * up mddev->thread. It is important to initialize critical
5566 * resources for mddev->thread BEFORE calling pers->run().
5567 */
5568 err = pers->run(mddev); 5563 err = pers->run(mddev);
5569 if (err) 5564 if (err)
5570 pr_warn("md: pers->run() failed ...\n"); 5565 pr_warn("md: pers->run() failed ...\n");
@@ -5678,6 +5673,9 @@ static int do_md_run(struct mddev *mddev)
5678 if (mddev_is_clustered(mddev)) 5673 if (mddev_is_clustered(mddev))
5679 md_allow_write(mddev); 5674 md_allow_write(mddev);
5680 5675
5676 /* run start up tasks that require md_thread */
5677 md_start(mddev);
5678
5681 md_wakeup_thread(mddev->thread); 5679 md_wakeup_thread(mddev->thread);
5682 md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */ 5680 md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */
5683 5681
@@ -5689,6 +5687,21 @@ out:
5689 return err; 5687 return err;
5690} 5688}
5691 5689
5690int md_start(struct mddev *mddev)
5691{
5692 int ret = 0;
5693
5694 if (mddev->pers->start) {
5695 set_bit(MD_RECOVERY_WAIT, &mddev->recovery);
5696 md_wakeup_thread(mddev->thread);
5697 ret = mddev->pers->start(mddev);
5698 clear_bit(MD_RECOVERY_WAIT, &mddev->recovery);
5699 md_wakeup_thread(mddev->sync_thread);
5700 }
5701 return ret;
5702}
5703EXPORT_SYMBOL_GPL(md_start);
5704
5692static int restart_array(struct mddev *mddev) 5705static int restart_array(struct mddev *mddev)
5693{ 5706{
5694 struct gendisk *disk = mddev->gendisk; 5707 struct gendisk *disk = mddev->gendisk;
@@ -8169,7 +8182,8 @@ void md_do_sync(struct md_thread *thread)
8169 int ret; 8182 int ret;
8170 8183
8171 /* just incase thread restarts... */ 8184 /* just incase thread restarts... */
8172 if (test_bit(MD_RECOVERY_DONE, &mddev->recovery)) 8185 if (test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
8186 test_bit(MD_RECOVERY_WAIT, &mddev->recovery))
8173 return; 8187 return;
8174 if (mddev->ro) {/* never try to sync a read-only array */ 8188 if (mddev->ro) {/* never try to sync a read-only array */
8175 set_bit(MD_RECOVERY_INTR, &mddev->recovery); 8189 set_bit(MD_RECOVERY_INTR, &mddev->recovery);
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 7d6bcf0eba0c..be8f72a9e30b 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -485,6 +485,7 @@ enum recovery_flags {
485 MD_RECOVERY_RESHAPE, /* A reshape is happening */ 485 MD_RECOVERY_RESHAPE, /* A reshape is happening */
486 MD_RECOVERY_FROZEN, /* User request to abort, and not restart, any action */ 486 MD_RECOVERY_FROZEN, /* User request to abort, and not restart, any action */
487 MD_RECOVERY_ERROR, /* sync-action interrupted because io-error */ 487 MD_RECOVERY_ERROR, /* sync-action interrupted because io-error */
488 MD_RECOVERY_WAIT, /* waiting for pers->start() to finish */
488}; 489};
489 490
490static inline int __must_check mddev_lock(struct mddev *mddev) 491static inline int __must_check mddev_lock(struct mddev *mddev)
@@ -523,7 +524,13 @@ struct md_personality
523 struct list_head list; 524 struct list_head list;
524 struct module *owner; 525 struct module *owner;
525 bool (*make_request)(struct mddev *mddev, struct bio *bio); 526 bool (*make_request)(struct mddev *mddev, struct bio *bio);
527 /*
528 * start up works that do NOT require md_thread. tasks that
529 * requires md_thread should go into start()
530 */
526 int (*run)(struct mddev *mddev); 531 int (*run)(struct mddev *mddev);
532 /* start up works that require md threads */
533 int (*start)(struct mddev *mddev);
527 void (*free)(struct mddev *mddev, void *priv); 534 void (*free)(struct mddev *mddev, void *priv);
528 void (*status)(struct seq_file *seq, struct mddev *mddev); 535 void (*status)(struct seq_file *seq, struct mddev *mddev);
529 /* error_handler must set ->faulty and clear ->in_sync 536 /* error_handler must set ->faulty and clear ->in_sync
@@ -687,6 +694,7 @@ extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale);
687 694
688extern void mddev_init(struct mddev *mddev); 695extern void mddev_init(struct mddev *mddev);
689extern int md_run(struct mddev *mddev); 696extern int md_run(struct mddev *mddev);
697extern int md_start(struct mddev *mddev);
690extern void md_stop(struct mddev *mddev); 698extern void md_stop(struct mddev *mddev);
691extern void md_stop_writes(struct mddev *mddev); 699extern void md_stop_writes(struct mddev *mddev);
692extern int md_rdev_init(struct md_rdev *rdev); 700extern int md_rdev_init(struct md_rdev *rdev);
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c
index 39f31f07ffe9..f259a5fd3fbd 100644
--- a/drivers/md/raid5-cache.c
+++ b/drivers/md/raid5-cache.c
@@ -2448,7 +2448,6 @@ static void r5c_recovery_flush_data_only_stripes(struct r5l_log *log,
2448 raid5_release_stripe(sh); 2448 raid5_release_stripe(sh);
2449 } 2449 }
2450 2450
2451 md_wakeup_thread(conf->mddev->thread);
2452 /* reuse conf->wait_for_quiescent in recovery */ 2451 /* reuse conf->wait_for_quiescent in recovery */
2453 wait_event(conf->wait_for_quiescent, 2452 wait_event(conf->wait_for_quiescent,
2454 atomic_read(&conf->active_stripes) == 0); 2453 atomic_read(&conf->active_stripes) == 0);
@@ -3036,6 +3035,23 @@ ioerr:
3036 return ret; 3035 return ret;
3037} 3036}
3038 3037
3038int r5l_start(struct r5l_log *log)
3039{
3040 int ret;
3041
3042 if (!log)
3043 return 0;
3044
3045 ret = r5l_load_log(log);
3046 if (ret) {
3047 struct mddev *mddev = log->rdev->mddev;
3048 struct r5conf *conf = mddev->private;
3049
3050 r5l_exit_log(conf);
3051 }
3052 return ret;
3053}
3054
3039void r5c_update_on_rdev_error(struct mddev *mddev, struct md_rdev *rdev) 3055void r5c_update_on_rdev_error(struct mddev *mddev, struct md_rdev *rdev)
3040{ 3056{
3041 struct r5conf *conf = mddev->private; 3057 struct r5conf *conf = mddev->private;
@@ -3138,13 +3154,9 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
3138 3154
3139 rcu_assign_pointer(conf->log, log); 3155 rcu_assign_pointer(conf->log, log);
3140 3156
3141 if (r5l_load_log(log))
3142 goto error;
3143
3144 set_bit(MD_HAS_JOURNAL, &conf->mddev->flags); 3157 set_bit(MD_HAS_JOURNAL, &conf->mddev->flags);
3145 return 0; 3158 return 0;
3146 3159
3147error:
3148 rcu_assign_pointer(conf->log, NULL); 3160 rcu_assign_pointer(conf->log, NULL);
3149 md_unregister_thread(&log->reclaim_thread); 3161 md_unregister_thread(&log->reclaim_thread);
3150reclaim_thread: 3162reclaim_thread:
diff --git a/drivers/md/raid5-log.h b/drivers/md/raid5-log.h
index 284578b0a349..3860041e8b74 100644
--- a/drivers/md/raid5-log.h
+++ b/drivers/md/raid5-log.h
@@ -32,6 +32,7 @@ extern struct md_sysfs_entry r5c_journal_mode;
32extern void r5c_update_on_rdev_error(struct mddev *mddev, 32extern void r5c_update_on_rdev_error(struct mddev *mddev,
33 struct md_rdev *rdev); 33 struct md_rdev *rdev);
34extern bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect); 34extern bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect);
35extern int r5l_start(struct r5l_log *log);
35 36
36extern struct dma_async_tx_descriptor * 37extern struct dma_async_tx_descriptor *
37ops_run_partial_parity(struct stripe_head *sh, struct raid5_percpu *percpu, 38ops_run_partial_parity(struct stripe_head *sh, struct raid5_percpu *percpu,
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 98ce4272ace9..5a2a29bd02dd 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -8364,6 +8364,13 @@ static int raid5_change_consistency_policy(struct mddev *mddev, const char *buf)
8364 return err; 8364 return err;
8365} 8365}
8366 8366
8367static int raid5_start(struct mddev *mddev)
8368{
8369 struct r5conf *conf = mddev->private;
8370
8371 return r5l_start(conf->log);
8372}
8373
8367static struct md_personality raid6_personality = 8374static struct md_personality raid6_personality =
8368{ 8375{
8369 .name = "raid6", 8376 .name = "raid6",
@@ -8371,6 +8378,7 @@ static struct md_personality raid6_personality =
8371 .owner = THIS_MODULE, 8378 .owner = THIS_MODULE,
8372 .make_request = raid5_make_request, 8379 .make_request = raid5_make_request,
8373 .run = raid5_run, 8380 .run = raid5_run,
8381 .start = raid5_start,
8374 .free = raid5_free, 8382 .free = raid5_free,
8375 .status = raid5_status, 8383 .status = raid5_status,
8376 .error_handler = raid5_error, 8384 .error_handler = raid5_error,
@@ -8395,6 +8403,7 @@ static struct md_personality raid5_personality =
8395 .owner = THIS_MODULE, 8403 .owner = THIS_MODULE,
8396 .make_request = raid5_make_request, 8404 .make_request = raid5_make_request,
8397 .run = raid5_run, 8405 .run = raid5_run,
8406 .start = raid5_start,
8398 .free = raid5_free, 8407 .free = raid5_free,
8399 .status = raid5_status, 8408 .status = raid5_status,
8400 .error_handler = raid5_error, 8409 .error_handler = raid5_error,
@@ -8420,6 +8429,7 @@ static struct md_personality raid4_personality =
8420 .owner = THIS_MODULE, 8429 .owner = THIS_MODULE,
8421 .make_request = raid5_make_request, 8430 .make_request = raid5_make_request,
8422 .run = raid5_run, 8431 .run = raid5_run,
8432 .start = raid5_start,
8423 .free = raid5_free, 8433 .free = raid5_free,
8424 .status = raid5_status, 8434 .status = raid5_status,
8425 .error_handler = raid5_error, 8435 .error_handler = raid5_error,