summaryrefslogtreecommitdiff
path: root/drivers/md
diff options
context:
space:
mode:
authorYu Kuai <yukuai3@huawei.com>2023-05-29 21:20:34 +0800
committerSong Liu <song@kernel.org>2023-07-27 00:13:28 -0700
commit6f56f0c4f1241f1694a6a9438dd4f78d4513a917 (patch)
tree3b41e3b51cf8e5c1c21a056103722137c6e367e8 /drivers/md
parent64e5e09afc14f8cc9058b0ed5c9cc4c8cd126b85 (diff)
md: add a mutex to synchronize idle and frozen in action_store()
Currently, for idle and frozen, action_store will hold 'reconfig_mutex' and call md_reap_sync_thread() to stop sync thread, however, this will cause deadlock (explained in the next patch). In order to fix the problem, following patch will release 'reconfig_mutex' and wait on 'resync_wait', like md_set_readonly() and do_md_stop() does. Consider that action_store() will set/clear 'MD_RECOVERY_FROZEN' unconditionally, which might cause unexpected problems, for example, frozen just set 'MD_RECOVERY_FROZEN' and is still in progress, while 'idle' clear 'MD_RECOVERY_FROZEN' and new sync thread is started, which might starve in progress frozen. A mutex is added to synchronize idle and frozen from action_store(). Signed-off-by: Yu Kuai <yukuai3@huawei.com> Signed-off-by: Song Liu <song@kernel.org> Link: https://lore.kernel.org/r/20230529132037.2124527-4-yukuai1@huaweicloud.com
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/md.c5
-rw-r--r--drivers/md/md.h3
2 files changed, 8 insertions, 0 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 7fa91f0e5620..3d7e87cab8ad 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -643,6 +643,7 @@ void mddev_init(struct mddev *mddev)
{
mutex_init(&mddev->open_mutex);
mutex_init(&mddev->reconfig_mutex);
+ mutex_init(&mddev->sync_mutex);
mutex_init(&mddev->bitmap_info.mutex);
INIT_LIST_HEAD(&mddev->disks);
INIT_LIST_HEAD(&mddev->all_mddevs);
@@ -4777,14 +4778,18 @@ static void stop_sync_thread(struct mddev *mddev)
static void idle_sync_thread(struct mddev *mddev)
{
+ mutex_lock(&mddev->sync_mutex);
clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
stop_sync_thread(mddev);
+ mutex_unlock(&mddev->sync_mutex);
}
static void frozen_sync_thread(struct mddev *mddev)
{
+ mutex_lock(&mddev->sync_mutex);
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
stop_sync_thread(mddev);
+ mutex_unlock(&mddev->sync_mutex);
}
static ssize_t
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 1aef86bf3fc3..18c168bf5fab 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -535,6 +535,9 @@ struct mddev {
*/
struct list_head deleting;
+ /* Used to synchronize idle and frozen for action_store() */
+ struct mutex sync_mutex;
+
bool has_superblocks:1;
bool fail_last_dev:1;
bool serialize_policy:1;