mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
md/raid10: fix missing wakeup in wait_barrier_nolock
Fuzz testing triggered a hung raid10d thread:
INFO: task md0_raid10 blocked for more than 120 seconds.
Call Trace:
raid10d
md_thread
kthread
wait_barrier_nolock() speculatively increments nr_pending. If a
concurrent writer changes resync_lock's sequence, it rolls the count back
with atomic_dec_and_test(). The rollback currently wakes wait_barrier only
when nr_pending reaches zero.
freeze_array() can be waiting for nr_pending == nr_queued + extra while
array_freeze_pending is set. If the rollback changes nr_pending from 2 to
1, the condition becomes true but no wakeup is sent, leaving raid10d
blocked indefinitely.
Also wake wait_barrier when array_freeze_pending is set, matching
allow_barrier().
Fixes: b9b083f904 ("md/raid10: convert resync_lock to use seqlock")
Signed-off-by: Zizhi Wo <wozizhi@huawei.com>
Reviewed-by: Abd-Alrhman Masalkhi <abd.masalkhi@gmail.com>
Link: https://patch.msgid.link/20260817033340.418119-3-wozizhi@huawei.com
Signed-off-by: Yu Kuai <yukuai@fygo.io>
This commit is contained in:
parent
68c51a7b1b
commit
f00eb0ff45
|
|
@ -1010,7 +1010,8 @@ static bool wait_barrier_nolock(struct r10conf *conf)
|
|||
if (!read_seqretry(&conf->resync_lock, seq))
|
||||
return true;
|
||||
|
||||
if (atomic_dec_and_test(&conf->nr_pending))
|
||||
if (atomic_dec_and_test(&conf->nr_pending) ||
|
||||
READ_ONCE(conf->array_freeze_pending))
|
||||
wake_up_barrier(conf);
|
||||
|
||||
return false;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user