Merge branch 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux...
[linux-block.git] / kernel / rcupdate.c
index eae29c25fb14019ff7b172db80cd0b6aec4e4327..bd5d5c8e51408343f3067a80611d5d1fed8ca89d 100644 (file)
@@ -217,9 +217,13 @@ static void rcu_migrate_callback(struct rcu_head *notused)
                wake_up(&rcu_migrate_wq);
 }
 
+extern int rcu_cpu_notify(struct notifier_block *self,
+                         unsigned long action, void *hcpu);
+
 static int __cpuinit rcu_barrier_cpu_hotplug(struct notifier_block *self,
                unsigned long action, void *hcpu)
 {
+       rcu_cpu_notify(self, action, hcpu);
        if (action == CPU_DYING) {
                /*
                 * preempt_disable() in on_each_cpu() prevents stop_machine(),
@@ -234,7 +238,8 @@ static int __cpuinit rcu_barrier_cpu_hotplug(struct notifier_block *self,
                call_rcu_bh(rcu_migrate_head, rcu_migrate_callback);
                call_rcu_sched(rcu_migrate_head + 1, rcu_migrate_callback);
                call_rcu(rcu_migrate_head + 2, rcu_migrate_callback);
-       } else if (action == CPU_POST_DEAD) {
+       } else if (action == CPU_DOWN_PREPARE) {
+               /* Don't need to wait until next removal operation. */
                /* rcu_migrate_head is protected by cpu_add_remove_lock */
                wait_migrated_callbacks();
        }
@@ -244,8 +249,18 @@ static int __cpuinit rcu_barrier_cpu_hotplug(struct notifier_block *self,
 
 void __init rcu_init(void)
 {
+       int i;
+
        __rcu_init();
-       hotcpu_notifier(rcu_barrier_cpu_hotplug, 0);
+       cpu_notifier(rcu_barrier_cpu_hotplug, 0);
+
+       /*
+        * We don't need protection against CPU-hotplug here because
+        * this is called early in boot, before either interrupts
+        * or the scheduler are operational.
+        */
+       for_each_online_cpu(i)
+               rcu_barrier_cpu_hotplug(NULL, CPU_UP_PREPARE, (void *)(long)i);
 }
 
 void rcu_scheduler_starting(void)