Skip to content

Commit 3e3c4f0

Browse files
paulmckrcuNeeraj Upadhyay
authored andcommitted
rcuscale: Make rcu_scale_writer() tolerate repeated GFP_KERNEL failure
Under some conditions, kmalloc(GFP_KERNEL) allocations have been observed to repeatedly fail. This situation has been observed to cause one of the rcu_scale_writer() instances to loop indefinitely retrying memory allocation for an asynchronous grace-period primitive. The problem is that if memory is short, all the other instances will allocate all available memory before the looping task is awakened from its rcu_barrier*() call. This in turn results in hangs, so that rcuscale fails to complete. This commit therefore removes the tight retry loop, so that when this condition occurs, the affected task is still passing through the full loop with its full set of termination checks. This spreads the risk of indefinite memory-allocation retry failures across all instances of rcu_scale_writer() tasks, which in turn prevents the hangs. Signed-off-by: "Paul E. McKenney" <[email protected]> Signed-off-by: Neeraj Upadhyay <[email protected]>
1 parent abaf132 commit 3e3c4f0

File tree

1 file changed

+6
-3
lines changed

1 file changed

+6
-3
lines changed

kernel/rcu/rcuscale.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -520,30 +520,33 @@ rcu_scale_writer(void *arg)
520520

521521
jdone = jiffies + minruntime * HZ;
522522
do {
523+
bool gp_succeeded = false;
524+
523525
if (writer_holdoff)
524526
udelay(writer_holdoff);
525527
if (writer_holdoff_jiffies)
526528
schedule_timeout_idle(torture_random(&tr) % writer_holdoff_jiffies + 1);
527529
wdp = &wdpp[i];
528530
*wdp = ktime_get_mono_fast_ns();
529531
if (gp_async && !WARN_ON_ONCE(!cur_ops->async)) {
530-
retry:
531532
if (!rhp)
532533
rhp = kmalloc(sizeof(*rhp), GFP_KERNEL);
533534
if (rhp && atomic_read(this_cpu_ptr(&n_async_inflight)) < gp_async_max) {
534535
atomic_inc(this_cpu_ptr(&n_async_inflight));
535536
cur_ops->async(rhp, rcu_scale_async_cb);
536537
rhp = NULL;
538+
gp_succeeded = true;
537539
} else if (!kthread_should_stop()) {
538540
cur_ops->gp_barrier();
539-
goto retry;
540541
} else {
541542
kfree(rhp); /* Because we are stopping. */
542543
}
543544
} else if (gp_exp) {
544545
cur_ops->exp_sync();
546+
gp_succeeded = true;
545547
} else {
546548
cur_ops->sync();
549+
gp_succeeded = true;
547550
}
548551
t = ktime_get_mono_fast_ns();
549552
*wdp = t - *wdp;
@@ -599,7 +602,7 @@ rcu_scale_writer(void *arg)
599602
__func__, me, started, done, writer_done[me], atomic_read(&n_rcu_scale_writer_finished), i, jiffies - jdone);
600603
selfreport = true;
601604
}
602-
if (started && !alldone && i < MAX_MEAS - 1)
605+
if (gp_succeeded && started && !alldone && i < MAX_MEAS - 1)
603606
i++;
604607
rcu_scale_wait_shutdown();
605608
} while (!torture_must_stop());

0 commit comments

Comments
 (0)