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

[ Upstream commit cd32b27a66 ]

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 130443d60b ("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: be83651f00 ("DM RAID: Add message/status support for changing sync action")
Cc: stable@vger.kernel.org # v6.7+
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
Signed-off-by: Xiao Ni <xni@redhat.com>
Acked-by: Mike Snitzer <snitzer@kernel.org>
Signed-off-by: Song Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20240305072306.2562024-7-yukuai1@huaweicloud.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Yu Kuai 2024-03-05 15:23:03 +08:00 committed by Greg Kroah-Hartman
parent eaa8fc9b09
commit 9e59b8d76f

View file

@ -3719,6 +3719,7 @@ static int raid_message(struct dm_target *ti, unsigned int argc, char **argv,
{ {
struct raid_set *rs = ti->private; struct raid_set *rs = ti->private;
struct mddev *mddev = &rs->md; struct mddev *mddev = &rs->md;
int ret = 0;
if (!mddev->pers || !mddev->pers->sync_request) if (!mddev->pers || !mddev->pers->sync_request)
return -EINVAL; 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)) if (test_bit(RT_FLAG_RS_SUSPENDED, &rs->runtime_flags))
return -EBUSY; return -EBUSY;
if (!strcasecmp(argv[0], "frozen")) if (!strcasecmp(argv[0], "frozen")) {
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery); ret = mddev_lock(mddev);
else if (ret)
clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); return ret;
if (!strcasecmp(argv[0], "idle") || !strcasecmp(argv[0], "frozen")) { md_frozen_sync_thread(mddev);
if (mddev->sync_thread) { mddev_unlock(mddev);
set_bit(MD_RECOVERY_INTR, &mddev->recovery); } else if (!strcasecmp(argv[0], "idle")) {
md_reap_sync_thread(mddev); ret = mddev_lock(mddev);
} if (ret)
} else if (decipher_sync_action(mddev, mddev->recovery) != st_idle) return ret;
md_idle_sync_thread(mddev);
mddev_unlock(mddev);
}
clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
if (decipher_sync_action(mddev, mddev->recovery) != st_idle)
return -EBUSY; return -EBUSY;
else if (!strcasecmp(argv[0], "resync")) else if (!strcasecmp(argv[0], "resync"))
; /* MD_RECOVERY_NEEDED set below */ ; /* MD_RECOVERY_NEEDED set below */