Commit 7eb8ff02 authored by Li Lingfeng's avatar Li Lingfeng Committed by Song Liu

md: Hold mddev->reconfig_mutex when trying to get mddev->sync_thread

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: default avatarLi Lingfeng <lilingfeng3@huawei.com>
Reviewed-by: default avatarYu Kuai <yukuai3@huawei.com>
Link: https://lore.kernel.org/r/20230803071711.2546560-1-lilingfeng@huaweicloud.comSigned-off-by: default avatarSong Liu <song@kernel.org>
parent 892da88d
...@@ -952,8 +952,8 @@ static int join(struct mddev *mddev, int nodes) ...@@ -952,8 +952,8 @@ static int join(struct mddev *mddev, int nodes)
return 0; return 0;
err: err:
set_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state); set_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state);
md_unregister_thread(&cinfo->recovery_thread); md_unregister_thread(mddev, &cinfo->recovery_thread);
md_unregister_thread(&cinfo->recv_thread); md_unregister_thread(mddev, &cinfo->recv_thread);
lockres_free(cinfo->message_lockres); lockres_free(cinfo->message_lockres);
lockres_free(cinfo->token_lockres); lockres_free(cinfo->token_lockres);
lockres_free(cinfo->ack_lockres); lockres_free(cinfo->ack_lockres);
...@@ -1015,8 +1015,8 @@ static int leave(struct mddev *mddev) ...@@ -1015,8 +1015,8 @@ static int leave(struct mddev *mddev)
resync_bitmap(mddev); resync_bitmap(mddev);
set_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state); set_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state);
md_unregister_thread(&cinfo->recovery_thread); md_unregister_thread(mddev, &cinfo->recovery_thread);
md_unregister_thread(&cinfo->recv_thread); md_unregister_thread(mddev, &cinfo->recv_thread);
lockres_free(cinfo->message_lockres); lockres_free(cinfo->message_lockres);
lockres_free(cinfo->token_lockres); lockres_free(cinfo->token_lockres);
lockres_free(cinfo->ack_lockres); lockres_free(cinfo->ack_lockres);
......
...@@ -6258,7 +6258,7 @@ static void mddev_detach(struct mddev *mddev) ...@@ -6258,7 +6258,7 @@ static void mddev_detach(struct mddev *mddev)
mddev->pers->quiesce(mddev, 1); mddev->pers->quiesce(mddev, 1);
mddev->pers->quiesce(mddev, 0); mddev->pers->quiesce(mddev, 0);
} }
md_unregister_thread(&mddev->thread); md_unregister_thread(mddev, &mddev->thread);
if (mddev->queue) if (mddev->queue)
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ 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 *), ...@@ -7990,9 +7990,10 @@ struct md_thread *md_register_thread(void (*run) (struct md_thread *),
} }
EXPORT_SYMBOL(md_register_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) if (!thread)
return; return;
...@@ -9484,7 +9485,7 @@ void md_reap_sync_thread(struct mddev *mddev) ...@@ -9484,7 +9485,7 @@ void md_reap_sync_thread(struct mddev *mddev)
bool is_reshaped = false; bool is_reshaped = false;
/* resync has finished, collect result */ /* resync has finished, collect result */
md_unregister_thread(&mddev->sync_thread); md_unregister_thread(mddev, &mddev->sync_thread);
atomic_inc(&mddev->sync_seq); atomic_inc(&mddev->sync_seq);
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) && if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
......
...@@ -761,7 +761,7 @@ extern struct md_thread *md_register_thread( ...@@ -761,7 +761,7 @@ extern struct md_thread *md_register_thread(
void (*run)(struct md_thread *thread), void (*run)(struct md_thread *thread),
struct mddev *mddev, struct mddev *mddev,
const char *name); 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_wakeup_thread(struct md_thread __rcu *thread);
extern void md_check_recovery(struct mddev *mddev); extern void md_check_recovery(struct mddev *mddev);
extern void md_reap_sync_thread(struct mddev *mddev); extern void md_reap_sync_thread(struct mddev *mddev);
......
...@@ -3156,7 +3156,7 @@ static int raid1_run(struct mddev *mddev) ...@@ -3156,7 +3156,7 @@ static int raid1_run(struct mddev *mddev)
* RAID1 needs at least one disk in active * RAID1 needs at least one disk in active
*/ */
if (conf->raid_disks - mddev->degraded < 1) { if (conf->raid_disks - mddev->degraded < 1) {
md_unregister_thread(&conf->thread); md_unregister_thread(mddev, &conf->thread);
ret = -EINVAL; ret = -EINVAL;
goto abort; goto abort;
} }
...@@ -3183,7 +3183,7 @@ static int raid1_run(struct mddev *mddev) ...@@ -3183,7 +3183,7 @@ static int raid1_run(struct mddev *mddev)
ret = md_integrity_register(mddev); ret = md_integrity_register(mddev);
if (ret) { if (ret) {
md_unregister_thread(&mddev->thread); md_unregister_thread(mddev, &mddev->thread);
goto abort; goto abort;
} }
return 0; return 0;
......
...@@ -4320,7 +4320,7 @@ static int raid10_run(struct mddev *mddev) ...@@ -4320,7 +4320,7 @@ static int raid10_run(struct mddev *mddev)
return 0; return 0;
out_free_conf: out_free_conf:
md_unregister_thread(&mddev->thread); md_unregister_thread(mddev, &mddev->thread);
raid10_free_conf(conf); raid10_free_conf(conf);
mddev->private = NULL; mddev->private = NULL;
out: out:
......
...@@ -3168,7 +3168,7 @@ void r5l_exit_log(struct r5conf *conf) ...@@ -3168,7 +3168,7 @@ void r5l_exit_log(struct r5conf *conf)
{ {
struct r5l_log *log = conf->log; 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 * 'reconfig_mutex' is held by caller, set 'confg->log' to NULL to
......
...@@ -8107,7 +8107,7 @@ static int raid5_run(struct mddev *mddev) ...@@ -8107,7 +8107,7 @@ static int raid5_run(struct mddev *mddev)
return 0; return 0;
abort: abort:
md_unregister_thread(&mddev->thread); md_unregister_thread(mddev, &mddev->thread);
print_raid5_conf(conf); print_raid5_conf(conf);
free_conf(conf); free_conf(conf);
mddev->private = NULL; mddev->private = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment