Skip to content

Commit 593889c

Browse files
paulmckrcuBoqun Feng
authored andcommitted
srcu: Don't queue workqueue handlers to never-online CPUs
While an srcu_struct structure is in the midst of switching from CPU-0 to all-CPUs state, it can attempt to invoke callbacks for CPUs that have never been online. Worse yet, it can attempt in invoke callbacks for CPUs that never will be online, even including imaginary CPUs not in cpu_possible_mask. This can cause hangs on s390, which is not set up to deal with workqueue handlers being scheduled on such CPUs. This commit therefore causes Tree SRCU to refrain from queueing workqueue handlers on CPUs that have not yet (and might never) come online. Because callbacks are not invoked on CPUs that have not been online, it is an error to invoke call_srcu(), synchronize_srcu(), or synchronize_srcu_expedited() on a CPU that is not yet fully online. However, it turns out to be less code to redirect the callbacks from too-early invocations of call_srcu() than to warn about such invocations. This commit therefore also redirects callbacks queued on not-yet-fully-online CPUs to the boot CPU. Reported-by: Vasily Gorbik <gor@linux.ibm.com> Fixes: 61bbcfb ("srcu: Push srcu_node allocation to GP when non-preemptible") Signed-off-by: Paul E. McKenney <paulmck@kernel.org> Tested-by: Vasily Gorbik <gor@linux.ibm.com> Tested-by: Samir <samir@linux.ibm.com> Reviewed-by: Shrikanth Hegde <sshegde@linux.ibm.com> Cc: Tejun Heo <tj@kernel.org> Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com> Signed-off-by: Boqun Feng <boqun@kernel.org>
1 parent 7fd2df2 commit 593889c

1 file changed

Lines changed: 6 additions & 6 deletions

File tree

kernel/rcu/srcutree.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -897,11 +897,9 @@ static void srcu_schedule_cbs_snp(struct srcu_struct *ssp, struct srcu_node *snp
897897
{
898898
int cpu;
899899

900-
for (cpu = snp->grplo; cpu <= snp->grphi; cpu++) {
901-
if (!(mask & (1UL << (cpu - snp->grplo))))
902-
continue;
903-
srcu_schedule_cbs_sdp(per_cpu_ptr(ssp->sda, cpu), delay);
904-
}
900+
for (cpu = snp->grplo; cpu <= snp->grphi; cpu++)
901+
if ((mask & (1UL << (cpu - snp->grplo))) && rcu_cpu_beenfullyonline(cpu))
902+
srcu_schedule_cbs_sdp(per_cpu_ptr(ssp->sda, cpu), delay);
905903
}
906904

907905
/*
@@ -1322,7 +1320,9 @@ static unsigned long srcu_gp_start_if_needed(struct srcu_struct *ssp,
13221320
*/
13231321
idx = __srcu_read_lock_nmisafe(ssp);
13241322
ss_state = smp_load_acquire(&ssp->srcu_sup->srcu_size_state);
1325-
if (ss_state < SRCU_SIZE_WAIT_CALL)
1323+
// If !rcu_cpu_beenfullyonline(), interrupts are still disabled,
1324+
// so no migration is possible in either direction from this CPU.
1325+
if (ss_state < SRCU_SIZE_WAIT_CALL || !rcu_cpu_beenfullyonline(raw_smp_processor_id()))
13261326
sdp = per_cpu_ptr(ssp->sda, get_boot_cpu_id());
13271327
else
13281328
sdp = raw_cpu_ptr(ssp->sda);

0 commit comments

Comments
 (0)