Skip to content

Commit 13017b4

Browse files
Yang ErkunYuKuai-huawei
authored andcommitted
md: make rdev_addable usable for rcu mode
Our testcase trigger panic: BUG: kernel NULL pointer dereference, address: 00000000000000e0 ... Oops: Oops: 0000 [#1] SMP NOPTI CPU: 2 UID: 0 PID: 85 Comm: kworker/2:1 Not tainted 6.16.0+ #94 PREEMPT(none) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.1-2.fc37 04/01/2014 Workqueue: md_misc md_start_sync RIP: 0010:rdev_addable+0x4d/0xf0 ... Call Trace: <TASK> md_start_sync+0x329/0x480 process_one_work+0x226/0x6d0 worker_thread+0x19e/0x340 kthread+0x10f/0x250 ret_from_fork+0x14d/0x180 ret_from_fork_asm+0x1a/0x30 </TASK> Modules linked in: raid10 CR2: 00000000000000e0 ---[ end trace 0000000000000000 ]--- RIP: 0010:rdev_addable+0x4d/0xf0 md_spares_need_change in md_start_sync will call rdev_addable which protected by rcu_read_lock/rcu_read_unlock. This rcu context will help protect rdev won't be released, but rdev->mddev will be set to NULL before we call synchronize_rcu in md_kick_rdev_from_array. Fix this by using READ_ONCE and check does rdev->mddev still alive. Fixes: bc08041 ("md: suspend array in md_start_sync() if array need reconfiguration") Fixes: 570b914 ("md: use RCU lock to protect traversal in md_spares_need_change()") Signed-off-by: Yang Erkun <[email protected]> Link: https://lore.kernel.org/linux-raid/[email protected] Signed-off-by: Yu Kuai <[email protected]>
1 parent 178d139 commit 13017b4

File tree

1 file changed

+7
-1
lines changed

1 file changed

+7
-1
lines changed

drivers/md/md.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9427,6 +9427,12 @@ static bool rdev_is_spare(struct md_rdev *rdev)
94279427

94289428
static bool rdev_addable(struct md_rdev *rdev)
94299429
{
9430+
struct mddev *mddev;
9431+
9432+
mddev = READ_ONCE(rdev->mddev);
9433+
if (!mddev)
9434+
return false;
9435+
94309436
/* rdev is already used, don't add it again. */
94319437
if (test_bit(Candidate, &rdev->flags) || rdev->raid_disk >= 0 ||
94329438
test_bit(Faulty, &rdev->flags))
@@ -9437,7 +9443,7 @@ static bool rdev_addable(struct md_rdev *rdev)
94379443
return true;
94389444

94399445
/* Allow to add if array is read-write. */
9440-
if (md_is_rdwr(rdev->mddev))
9446+
if (md_is_rdwr(mddev))
94419447
return true;
94429448

94439449
/*

0 commit comments

Comments
 (0)