Skip to content

Commit 25db5f2

Browse files
XiaoNi87YuKuai-huawei
authored andcommitted
md: add legacy_async_del_gendisk mode
commit 9e59d60 ("md: call del_gendisk in control path") changes the async way to sync way of calling del_gendisk. But it breaks mdadm --assemble command. The assemble command runs like this: 1. create the array 2. stop the array 3. access the sysfs files after stopping The sync way calls del_gendisk in step 2, so all sysfs files are removed. Now to avoid breaking mdadm assemble command, this patch adds the parameter legacy_async_del_gendisk that can be used to choose which way. The default is async way. In future, we plan to change default to sync way in kernel 7.0. Then users need to upgrade to mdadm 4.5+ which removes step 2. Fixes: 9e59d60 ("md: call del_gendisk in control path") Reported-by: Mikulas Patocka <[email protected]> Closes: https://lore.kernel.org/linux-raid/CAMw=ZnQ=ET2St-+hnhsuq34rRPnebqcXqP1QqaHW5Bh4aaaZ4g@mail.gmail.com/T/#t Suggested-and-reviewed-by: Yu Kuai <[email protected]> Signed-off-by: Xiao Ni <[email protected]> Reviewed-by: Paul Menzel <[email protected]> Link: https://lore.kernel.org/linux-raid/[email protected] Signed-off-by: Yu Kuai <[email protected]>
1 parent 0452f08 commit 25db5f2

File tree

1 file changed

+42
-14
lines changed

1 file changed

+42
-14
lines changed

drivers/md/md.c

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ static int start_readonly;
339339
* so all the races disappear.
340340
*/
341341
static bool create_on_open = true;
342+
static bool legacy_async_del_gendisk = true;
342343

343344
/*
344345
* We have a system wide 'event count' that is incremented
@@ -877,15 +878,18 @@ void mddev_unlock(struct mddev *mddev)
877878
export_rdev(rdev, mddev);
878879
}
879880

880-
/* Call del_gendisk after release reconfig_mutex to avoid
881-
* deadlock (e.g. call del_gendisk under the lock and an
882-
* access to sysfs files waits the lock)
883-
* And MD_DELETED is only used for md raid which is set in
884-
* do_md_stop. dm raid only uses md_stop to stop. So dm raid
885-
* doesn't need to check MD_DELETED when getting reconfig lock
886-
*/
887-
if (test_bit(MD_DELETED, &mddev->flags))
888-
del_gendisk(mddev->gendisk);
881+
if (!legacy_async_del_gendisk) {
882+
/*
883+
* Call del_gendisk after release reconfig_mutex to avoid
884+
* deadlock (e.g. call del_gendisk under the lock and an
885+
* access to sysfs files waits the lock)
886+
* And MD_DELETED is only used for md raid which is set in
887+
* do_md_stop. dm raid only uses md_stop to stop. So dm raid
888+
* doesn't need to check MD_DELETED when getting reconfig lock
889+
*/
890+
if (test_bit(MD_DELETED, &mddev->flags))
891+
del_gendisk(mddev->gendisk);
892+
}
889893
}
890894
EXPORT_SYMBOL_GPL(mddev_unlock);
891895

@@ -5818,6 +5822,13 @@ static void md_kobj_release(struct kobject *ko)
58185822
{
58195823
struct mddev *mddev = container_of(ko, struct mddev, kobj);
58205824

5825+
if (legacy_async_del_gendisk) {
5826+
if (mddev->sysfs_state)
5827+
sysfs_put(mddev->sysfs_state);
5828+
if (mddev->sysfs_level)
5829+
sysfs_put(mddev->sysfs_level);
5830+
del_gendisk(mddev->gendisk);
5831+
}
58215832
put_disk(mddev->gendisk);
58225833
}
58235834

@@ -6021,6 +6032,9 @@ static int md_alloc_and_put(dev_t dev, char *name)
60216032
{
60226033
struct mddev *mddev = md_alloc(dev, name);
60236034

6035+
if (legacy_async_del_gendisk)
6036+
pr_warn("md: async del_gendisk mode will be removed in future, please upgrade to mdadm-4.5+\n");
6037+
60246038
if (IS_ERR(mddev))
60256039
return PTR_ERR(mddev);
60266040
mddev_put(mddev);
@@ -6431,10 +6445,22 @@ static void md_clean(struct mddev *mddev)
64316445
mddev->persistent = 0;
64326446
mddev->level = LEVEL_NONE;
64336447
mddev->clevel[0] = 0;
6434-
/* if UNTIL_STOP is set, it's cleared here */
6435-
mddev->hold_active = 0;
6436-
/* Don't clear MD_CLOSING, or mddev can be opened again. */
6437-
mddev->flags &= BIT_ULL_MASK(MD_CLOSING);
6448+
6449+
/*
6450+
* For legacy_async_del_gendisk mode, it can stop the array in the
6451+
* middle of assembling it, then it still can access the array. So
6452+
* it needs to clear MD_CLOSING. If not legacy_async_del_gendisk,
6453+
* it can't open the array again after stopping it. So it doesn't
6454+
* clear MD_CLOSING.
6455+
*/
6456+
if (legacy_async_del_gendisk && mddev->hold_active) {
6457+
clear_bit(MD_CLOSING, &mddev->flags);
6458+
} else {
6459+
/* if UNTIL_STOP is set, it's cleared here */
6460+
mddev->hold_active = 0;
6461+
/* Don't clear MD_CLOSING, or mddev can be opened again. */
6462+
mddev->flags &= BIT_ULL_MASK(MD_CLOSING);
6463+
}
64386464
mddev->sb_flags = 0;
64396465
mddev->ro = MD_RDWR;
64406466
mddev->metadata_type[0] = 0;
@@ -6658,7 +6684,8 @@ static int do_md_stop(struct mddev *mddev, int mode)
66586684

66596685
export_array(mddev);
66606686
md_clean(mddev);
6661-
set_bit(MD_DELETED, &mddev->flags);
6687+
if (!legacy_async_del_gendisk)
6688+
set_bit(MD_DELETED, &mddev->flags);
66626689
}
66636690
md_new_event();
66646691
sysfs_notify_dirent_safe(mddev->sysfs_state);
@@ -10392,6 +10419,7 @@ module_param_call(start_ro, set_ro, get_ro, NULL, S_IRUSR|S_IWUSR);
1039210419
module_param(start_dirty_degraded, int, S_IRUGO|S_IWUSR);
1039310420
module_param_call(new_array, add_named_array, NULL, NULL, S_IWUSR);
1039410421
module_param(create_on_open, bool, S_IRUSR|S_IWUSR);
10422+
module_param(legacy_async_del_gendisk, bool, 0600);
1039510423

1039610424
MODULE_LICENSE("GPL");
1039710425
MODULE_DESCRIPTION("MD RAID framework");

0 commit comments

Comments
 (0)