aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2015-01-19 22:57:32 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2015-02-26 15:01:28 -0500
commit143da9c2fc030a5774674f2ebc2f934fab3dcd9a (patch)
treeba3537cce8b630a56f47f99267cf8047205fd393 /kernel
parent2723249a31a68ccc0ec8ac59a905d7f9430bf8f6 (diff)
rcu: Prevent early-boot RCU callbacks from splatting
Currently, a call_rcu() that precedes rcu_init() will splat due to the callback lists not having yet been initialized. This commit causes the first such callback to initialize the boot CPU's RCU callback list. Note that this commit does not change rcu_init()-time initialization, which means that the callback will be discarded at rcu_init() time. Fixing this is the job of later commits. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/rcu/tree.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index d2fa95e4a268..fcfdbe53bb70 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -2838,11 +2838,21 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
2838 2838
2839 if (cpu != -1) 2839 if (cpu != -1)
2840 rdp = per_cpu_ptr(rsp->rda, cpu); 2840 rdp = per_cpu_ptr(rsp->rda, cpu);
2841 offline = !__call_rcu_nocb(rdp, head, lazy, flags); 2841 if (likely(rdp->mynode)) {
2842 WARN_ON_ONCE(offline); 2842 /* Post-boot, so this should be for a no-CBs CPU. */
2843 /* _call_rcu() is illegal on offline CPU; leak the callback. */ 2843 offline = !__call_rcu_nocb(rdp, head, lazy, flags);
2844 local_irq_restore(flags); 2844 WARN_ON_ONCE(offline);
2845 return; 2845 /* Offline CPU, _call_rcu() illegal, leak callback. */
2846 local_irq_restore(flags);
2847 return;
2848 }
2849 /*
2850 * Very early boot, before rcu_init(). Initialize if needed
2851 * and then drop through to queue the callback.
2852 */
2853 BUG_ON(cpu != -1);
2854 if (!likely(rdp->nxtlist))
2855 init_default_callback_list(rdp);
2846 } 2856 }
2847 ACCESS_ONCE(rdp->qlen) = rdp->qlen + 1; 2857 ACCESS_ONCE(rdp->qlen) = rdp->qlen + 1;
2848 if (lazy) 2858 if (lazy)