aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutree_plugin.h
diff options
context:
space:
mode:
authorPaul E. McKenney <paul.mckenney@linaro.org>2011-07-10 18:57:35 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2011-07-13 11:17:56 -0400
commitb0d304172f49061b4ff78f9e2b02719ac69c8a7e (patch)
tree882123e565ced895910490514f6e676c708b5001 /kernel/rcutree_plugin.h
parent620917de59eeb934b9f8cf35cc2d95c1ac8ed0fc (diff)
rcu: Prevent RCU callbacks from executing before scheduler initialized
Under some rare but real combinations of configuration parameters, RCU callbacks are posted during early boot that use kernel facilities that are not yet initialized. Therefore, when these callbacks are invoked, hard hangs and crashes ensue. This commit therefore prevents RCU callbacks from being invoked until after the scheduler is fully up and running, as in after multiple tasks have been spawned. It might well turn out that a better approach is to identify the specific RCU callbacks that are causing this problem, but that discussion will wait until such time as someone really needs an RCU callback to be invoked (as opposed to merely registered) during early boot. Reported-by: julie Sullivan <kernelmail.jms@gmail.com> Reported-by: RKK <kulkarni.ravi4@gmail.com> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Tested-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Tested-by: julie Sullivan <kernelmail.jms@gmail.com> Tested-by: RKK <kulkarni.ravi4@gmail.com>
Diffstat (limited to 'kernel/rcutree_plugin.h')
-rw-r--r--kernel/rcutree_plugin.h15
1 files changed, 11 insertions, 4 deletions
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index 14dc7dd00902..75113cb7c4fb 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -1532,7 +1532,7 @@ static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu)
1532 struct sched_param sp; 1532 struct sched_param sp;
1533 struct task_struct *t; 1533 struct task_struct *t;
1534 1534
1535 if (!rcu_kthreads_spawnable || 1535 if (!rcu_scheduler_fully_active ||
1536 per_cpu(rcu_cpu_kthread_task, cpu) != NULL) 1536 per_cpu(rcu_cpu_kthread_task, cpu) != NULL)
1537 return 0; 1537 return 0;
1538 t = kthread_create(rcu_cpu_kthread, (void *)(long)cpu, "rcuc%d", cpu); 1538 t = kthread_create(rcu_cpu_kthread, (void *)(long)cpu, "rcuc%d", cpu);
@@ -1639,7 +1639,7 @@ static int __cpuinit rcu_spawn_one_node_kthread(struct rcu_state *rsp,
1639 struct sched_param sp; 1639 struct sched_param sp;
1640 struct task_struct *t; 1640 struct task_struct *t;
1641 1641
1642 if (!rcu_kthreads_spawnable || 1642 if (!rcu_scheduler_fully_active ||
1643 rnp->qsmaskinit == 0) 1643 rnp->qsmaskinit == 0)
1644 return 0; 1644 return 0;
1645 if (rnp->node_kthread_task == NULL) { 1645 if (rnp->node_kthread_task == NULL) {
@@ -1665,7 +1665,7 @@ static int __init rcu_spawn_kthreads(void)
1665 int cpu; 1665 int cpu;
1666 struct rcu_node *rnp; 1666 struct rcu_node *rnp;
1667 1667
1668 rcu_kthreads_spawnable = 1; 1668 rcu_scheduler_fully_active = 1;
1669 for_each_possible_cpu(cpu) { 1669 for_each_possible_cpu(cpu) {
1670 per_cpu(rcu_cpu_has_work, cpu) = 0; 1670 per_cpu(rcu_cpu_has_work, cpu) = 0;
1671 if (cpu_online(cpu)) 1671 if (cpu_online(cpu))
@@ -1687,7 +1687,7 @@ static void __cpuinit rcu_prepare_kthreads(int cpu)
1687 struct rcu_node *rnp = rdp->mynode; 1687 struct rcu_node *rnp = rdp->mynode;
1688 1688
1689 /* Fire up the incoming CPU's kthread and leaf rcu_node kthread. */ 1689 /* Fire up the incoming CPU's kthread and leaf rcu_node kthread. */
1690 if (rcu_kthreads_spawnable) { 1690 if (rcu_scheduler_fully_active) {
1691 (void)rcu_spawn_one_cpu_kthread(cpu); 1691 (void)rcu_spawn_one_cpu_kthread(cpu);
1692 if (rnp->node_kthread_task == NULL) 1692 if (rnp->node_kthread_task == NULL)
1693 (void)rcu_spawn_one_node_kthread(rcu_state, rnp); 1693 (void)rcu_spawn_one_node_kthread(rcu_state, rnp);
@@ -1726,6 +1726,13 @@ static void rcu_cpu_kthread_setrt(int cpu, int to_rt)
1726{ 1726{
1727} 1727}
1728 1728
1729static int __init rcu_scheduler_really_started(void)
1730{
1731 rcu_scheduler_fully_active = 1;
1732 return 0;
1733}
1734early_initcall(rcu_scheduler_really_started);
1735
1729static void __cpuinit rcu_prepare_kthreads(int cpu) 1736static void __cpuinit rcu_prepare_kthreads(int cpu)
1730{ 1737{
1731} 1738}