When sync_request() reports a skipped region (*skipped == 1),
md_do_sync()'s main loop advances the cursor and takes an early
continue:
j += sectors;
...
if (last_check + window > io_sectors || j == max_sectors)
continue;
If the personality returns a small span per call (raid10 recovery
returns only 128 sectors), syncing a large, mostly clean array iterates
this branch an enormous number of times without ever yielding the CPU.
On a non-preemptive kernel the resync thread then trips the soft-lockup
watchdog:
watchdog: BUG: soft lockup - CPU#149 stuck for 313s! [mdX_resync]
md_bitmap_start_sync+0x6f/0xe0
raid10_sync_request+0x2c9/0x1530 [raid10]
md_do_sync+0x810/0x1030
md_thread+0xa7/0x150
Add a cond_resched(). This does not reduce the wasted iterations; the
excessive iteration count is a raid10 problem addressed separately.
Cc: stable@vger.kernel.org
Signed-off-by: Yunye Zhao <redacted>
---
drivers/md/md.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index d1465bcd86c8..c2e8b203c4db 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -9881,8 +9881,10 @@ void md_do_sync(struct md_thread *thread)
*/
md_new_event();
- if (last_check + window > io_sectors || j == max_sectors)
+ if (last_check + window > io_sectors || j == max_sectors) {
+ cond_resched();
continue;
+ }
last_check = io_sectors;
repeat:--
2.19.1.6.gb485710b