mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 13:53:33 +00:00
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, commit130443d60b
("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
This commit is contained in:
parent
16c4770c75
commit
cd32b27a66
1 changed files with 18 additions and 10 deletions
|
@ -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 */
|
||||||
|
|
Loading…
Reference in a new issue