md: Hold mddev->reconfig_mutex when trying to get mddev->sync_thread
authorLi Lingfeng <lilingfeng3@huawei.com>
Thu, 3 Aug 2023 07:17:11 +0000 (15:17 +0800)
committerSong Liu <song@kernel.org>
Tue, 15 Aug 2023 16:40:26 +0000 (09:40 -0700)
Commit ba9d9f1a707f ("Revert "md: unlock mddev before reap sync_thread in
action_store"") removed the scenario of calling md_unregister_thread()
without holding mddev->reconfig_mutex, so add a lock holding check before
acquiring mddev->sync_thread by passing mdev to md_unregister_thread().

Signed-off-by: Li Lingfeng <lilingfeng3@huawei.com>
Reviewed-by: Yu Kuai <yukuai3@huawei.com>
Link: https://lore.kernel.org/r/20230803071711.2546560-1-lilingfeng@huaweicloud.com
Signed-off-by: Song Liu <song@kernel.org>
drivers/md/md-cluster.c
drivers/md/md.c
drivers/md/md.h
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5-cache.c
drivers/md/raid5.c

index 3d9fd74..1e26eb2 100644 (file)
@@ -952,8 +952,8 @@ static int join(struct mddev *mddev, int nodes)
        return 0;
 err:
        set_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state);
-       md_unregister_thread(&cinfo->recovery_thread);
-       md_unregister_thread(&cinfo->recv_thread);
+       md_unregister_thread(mddev, &cinfo->recovery_thread);
+       md_unregister_thread(mddev, &cinfo->recv_thread);
        lockres_free(cinfo->message_lockres);
        lockres_free(cinfo->token_lockres);
        lockres_free(cinfo->ack_lockres);
@@ -1015,8 +1015,8 @@ static int leave(struct mddev *mddev)
                resync_bitmap(mddev);
 
        set_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state);
-       md_unregister_thread(&cinfo->recovery_thread);
-       md_unregister_thread(&cinfo->recv_thread);
+       md_unregister_thread(mddev, &cinfo->recovery_thread);
+       md_unregister_thread(mddev, &cinfo->recv_thread);
        lockres_free(cinfo->message_lockres);
        lockres_free(cinfo->token_lockres);
        lockres_free(cinfo->ack_lockres);
index a3d9827..5c3c19b 100644 (file)
@@ -6258,7 +6258,7 @@ static void mddev_detach(struct mddev *mddev)
                mddev->pers->quiesce(mddev, 1);
                mddev->pers->quiesce(mddev, 0);
        }
-       md_unregister_thread(&mddev->thread);
+       md_unregister_thread(mddev, &mddev->thread);
        if (mddev->queue)
                blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
 }
@@ -7990,9 +7990,10 @@ struct md_thread *md_register_thread(void (*run) (struct md_thread *),
 }
 EXPORT_SYMBOL(md_register_thread);
 
-void md_unregister_thread(struct md_thread __rcu **threadp)
+void md_unregister_thread(struct mddev *mddev, struct md_thread __rcu **threadp)
 {
-       struct md_thread *thread = rcu_dereference_protected(*threadp, true);
+       struct md_thread *thread = rcu_dereference_protected(*threadp,
+                                       lockdep_is_held(&mddev->reconfig_mutex));
 
        if (!thread)
                return;
@@ -9484,7 +9485,7 @@ void md_reap_sync_thread(struct mddev *mddev)
        bool is_reshaped = false;
 
        /* resync has finished, collect result */
-       md_unregister_thread(&mddev->sync_thread);
+       md_unregister_thread(mddev, &mddev->sync_thread);
        atomic_inc(&mddev->sync_seq);
 
        if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
index 8ae9574..9bcb77b 100644 (file)
@@ -761,7 +761,7 @@ extern struct md_thread *md_register_thread(
        void (*run)(struct md_thread *thread),
        struct mddev *mddev,
        const char *name);
-extern void md_unregister_thread(struct md_thread __rcu **threadp);
+extern void md_unregister_thread(struct mddev *mddev, struct md_thread __rcu **threadp);
 extern void md_wakeup_thread(struct md_thread __rcu *thread);
 extern void md_check_recovery(struct mddev *mddev);
 extern void md_reap_sync_thread(struct mddev *mddev);
index b920f92..c18b7c0 100644 (file)
@@ -3156,7 +3156,7 @@ static int raid1_run(struct mddev *mddev)
         * RAID1 needs at least one disk in active
         */
        if (conf->raid_disks - mddev->degraded < 1) {
-               md_unregister_thread(&conf->thread);
+               md_unregister_thread(mddev, &conf->thread);
                ret = -EINVAL;
                goto abort;
        }
@@ -3183,7 +3183,7 @@ static int raid1_run(struct mddev *mddev)
 
        ret = md_integrity_register(mddev);
        if (ret) {
-               md_unregister_thread(&mddev->thread);
+               md_unregister_thread(mddev, &mddev->thread);
                goto abort;
        }
        return 0;
index 7704a4c..0234131 100644 (file)
@@ -4320,7 +4320,7 @@ static int raid10_run(struct mddev *mddev)
        return 0;
 
 out_free_conf:
-       md_unregister_thread(&mddev->thread);
+       md_unregister_thread(mddev, &mddev->thread);
        raid10_free_conf(conf);
        mddev->private = NULL;
 out:
index 2eac4a5..a29b965 100644 (file)
@@ -3168,7 +3168,7 @@ void r5l_exit_log(struct r5conf *conf)
 {
        struct r5l_log *log = conf->log;
 
-       md_unregister_thread(&log->reclaim_thread);
+       md_unregister_thread(conf->mddev, &log->reclaim_thread);
 
        /*
         * 'reconfig_mutex' is held by caller, set 'confg->log' to NULL to
index 32a8719..4cb9c60 100644 (file)
@@ -8107,7 +8107,7 @@ static int raid5_run(struct mddev *mddev)
 
        return 0;
 abort:
-       md_unregister_thread(&mddev->thread);
+       md_unregister_thread(mddev, &mddev->thread);
        print_raid5_conf(conf);
        free_conf(conf);
        mddev->private = NULL;