goto bad;
        }
 
+       r = md_start(&rs->md);
+
+       if (r) {
+               ti->error = "Failed to start raid array";
+               mddev_unlock(&rs->md);
+               goto bad_md_start;
+       }
+
        rs->callbacks.congested_fn = raid_is_congested;
        dm_table_add_target_callbacks(ti->table, &rs->callbacks);
 
        mddev_unlock(&rs->md);
        return 0;
 
+bad_md_start:
 bad_journal_mode_set:
 bad_stripe_cache:
 bad_check_reshape:
 
        if (start_readonly && mddev->ro == 0)
                mddev->ro = 2; /* read-only, but switch on first write */
 
-       /*
-        * NOTE: some pers->run(), for example r5l_recovery_log(), wakes
-        * up mddev->thread. It is important to initialize critical
-        * resources for mddev->thread BEFORE calling pers->run().
-        */
        err = pers->run(mddev);
        if (err)
                pr_warn("md: pers->run() failed ...\n");
        if (mddev_is_clustered(mddev))
                md_allow_write(mddev);
 
+       /* run start up tasks that require md_thread */
+       md_start(mddev);
+
        md_wakeup_thread(mddev->thread);
        md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */
 
        return err;
 }
 
+int md_start(struct mddev *mddev)
+{
+       int ret = 0;
+
+       if (mddev->pers->start) {
+               set_bit(MD_RECOVERY_WAIT, &mddev->recovery);
+               md_wakeup_thread(mddev->thread);
+               ret = mddev->pers->start(mddev);
+               clear_bit(MD_RECOVERY_WAIT, &mddev->recovery);
+               md_wakeup_thread(mddev->sync_thread);
+       }
+       return ret;
+}
+EXPORT_SYMBOL_GPL(md_start);
+
 static int restart_array(struct mddev *mddev)
 {
        struct gendisk *disk = mddev->gendisk;
        int ret;
 
        /* just incase thread restarts... */
-       if (test_bit(MD_RECOVERY_DONE, &mddev->recovery))
+       if (test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
+           test_bit(MD_RECOVERY_WAIT, &mddev->recovery))
                return;
        if (mddev->ro) {/* never try to sync a read-only array */
                set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 
        MD_RECOVERY_RESHAPE,    /* A reshape is happening */
        MD_RECOVERY_FROZEN,     /* User request to abort, and not restart, any action */
        MD_RECOVERY_ERROR,      /* sync-action interrupted because io-error */
+       MD_RECOVERY_WAIT,       /* waiting for pers->start() to finish */
 };
 
 static inline int __must_check mddev_lock(struct mddev *mddev)
        struct list_head list;
        struct module *owner;
        bool (*make_request)(struct mddev *mddev, struct bio *bio);
+       /*
+        * start up works that do NOT require md_thread. tasks that
+        * requires md_thread should go into start()
+        */
        int (*run)(struct mddev *mddev);
+       /* start up works that require md threads */
+       int (*start)(struct mddev *mddev);
        void (*free)(struct mddev *mddev, void *priv);
        void (*status)(struct seq_file *seq, struct mddev *mddev);
        /* error_handler must set ->faulty and clear ->in_sync
 
 extern void mddev_init(struct mddev *mddev);
 extern int md_run(struct mddev *mddev);
+extern int md_start(struct mddev *mddev);
 extern void md_stop(struct mddev *mddev);
 extern void md_stop_writes(struct mddev *mddev);
 extern int md_rdev_init(struct md_rdev *rdev);
 
                raid5_release_stripe(sh);
        }
 
-       md_wakeup_thread(conf->mddev->thread);
        /* reuse conf->wait_for_quiescent in recovery */
        wait_event(conf->wait_for_quiescent,
                   atomic_read(&conf->active_stripes) == 0);
        return ret;
 }
 
+int r5l_start(struct r5l_log *log)
+{
+       int ret;
+
+       if (!log)
+               return 0;
+
+       ret = r5l_load_log(log);
+       if (ret) {
+               struct mddev *mddev = log->rdev->mddev;
+               struct r5conf *conf = mddev->private;
+
+               r5l_exit_log(conf);
+       }
+       return ret;
+}
+
 void r5c_update_on_rdev_error(struct mddev *mddev, struct md_rdev *rdev)
 {
        struct r5conf *conf = mddev->private;
 
        rcu_assign_pointer(conf->log, log);
 
-       if (r5l_load_log(log))
-               goto error;
-
        set_bit(MD_HAS_JOURNAL, &conf->mddev->flags);
        return 0;
 
-error:
        rcu_assign_pointer(conf->log, NULL);
        md_unregister_thread(&log->reclaim_thread);
 reclaim_thread:
 
 extern void r5c_update_on_rdev_error(struct mddev *mddev,
                                     struct md_rdev *rdev);
 extern bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect);
+extern int r5l_start(struct r5l_log *log);
 
 extern struct dma_async_tx_descriptor *
 ops_run_partial_parity(struct stripe_head *sh, struct raid5_percpu *percpu,
 
        return err;
 }
 
+static int raid5_start(struct mddev *mddev)
+{
+       struct r5conf *conf = mddev->private;
+
+       return r5l_start(conf->log);
+}
+
 static struct md_personality raid6_personality =
 {
        .name           = "raid6",
        .owner          = THIS_MODULE,
        .make_request   = raid5_make_request,
        .run            = raid5_run,
+       .start          = raid5_start,
        .free           = raid5_free,
        .status         = raid5_status,
        .error_handler  = raid5_error,
        .owner          = THIS_MODULE,
        .make_request   = raid5_make_request,
        .run            = raid5_run,
+       .start          = raid5_start,
        .free           = raid5_free,
        .status         = raid5_status,
        .error_handler  = raid5_error,
        .owner          = THIS_MODULE,
        .make_request   = raid5_make_request,
        .run            = raid5_run,
+       .start          = raid5_start,
        .free           = raid5_free,
        .status         = raid5_status,
        .error_handler  = raid5_error,