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

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.com


Signed-off-by: default avatarSong Liu <song@kernel.org>
parent 892da88d
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -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);
+5 −4
Original line number Diff line number Diff line
@@ -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) &&
+1 −1
Original line number Diff line number Diff line
@@ -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);
+2 −2
Original line number Diff line number Diff line
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -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:
Loading