Commit cd32b27a authored by Yu Kuai's avatar Yu Kuai Committed by Song Liu
Browse files

md/dm-raid: don't call md_reap_sync_thread() directly



Currently md_reap_sync_thread() is called from raid_message() directly
without holding 'reconfig_mutex', this is definitely unsafe because
md_reap_sync_thread() can change many fields that is protected by
'reconfig_mutex'.

However, hold 'reconfig_mutex' here is still problematic because this
will cause deadlock, for example, commit 130443d6 ("md: refactor
idle/frozen_sync_thread() to fix deadlock").

Fix this problem by using stop_sync_thread() to unregister sync_thread,
like md/raid did.

Fixes: be83651f ("DM RAID: Add message/status support for changing sync action")
Cc: stable@vger.kernel.org # v6.7+
Signed-off-by: default avatarYu Kuai <yukuai3@huawei.com>
Signed-off-by: default avatarXiao Ni <xni@redhat.com>
Acked-by: default avatarMike Snitzer <snitzer@kernel.org>
Signed-off-by: default avatarSong Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20240305072306.2562024-7-yukuai1@huaweicloud.com
parent 16c4770c
Loading
Loading
Loading
Loading
+18 −10
Original line number Diff line number Diff line
@@ -3719,6 +3719,7 @@ static int raid_message(struct dm_target *ti, unsigned int argc, char **argv,
{
	struct raid_set *rs = ti->private;
	struct mddev *mddev = &rs->md;
	int ret = 0;

	if (!mddev->pers || !mddev->pers->sync_request)
		return -EINVAL;
@@ -3726,17 +3727,24 @@ static int raid_message(struct dm_target *ti, unsigned int argc, char **argv,
	if (test_bit(RT_FLAG_RS_SUSPENDED, &rs->runtime_flags))
		return -EBUSY;

	if (!strcasecmp(argv[0], "frozen"))
		set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
	else
		clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
	if (!strcasecmp(argv[0], "frozen")) {
		ret = mddev_lock(mddev);
		if (ret)
			return ret;

		md_frozen_sync_thread(mddev);
		mddev_unlock(mddev);
	} else if (!strcasecmp(argv[0], "idle")) {
		ret = mddev_lock(mddev);
		if (ret)
			return ret;

	if (!strcasecmp(argv[0], "idle") || !strcasecmp(argv[0], "frozen")) {
		if (mddev->sync_thread) {
			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
			md_reap_sync_thread(mddev);
		md_idle_sync_thread(mddev);
		mddev_unlock(mddev);
	}
	} else if (decipher_sync_action(mddev, mddev->recovery) != st_idle)

	clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
	if (decipher_sync_action(mddev, mddev->recovery) != st_idle)
		return -EBUSY;
	else if (!strcasecmp(argv[0], "resync"))
		; /* MD_RECOVERY_NEEDED set below */