Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70ff0555 authored by Nick Piggin's avatar Nick Piggin Committed by Linus Torvalds
Browse files

Fix PREEMPT_RCU without HOTPLUG_CPU



PREEMPT_RCU without HOTPLUG_CPU is broken.  The rcu_online_cpu is called
to initially populate rcu_cpu_online_map with all online CPUs when the
hotplug event handler is installed, and also to populate the map with
CPUs as they come online.  The former case is meant to happen with and
without HOTPLUG_CPU, but without HOTPLUG_CPU, the rcu_offline_cpu
function is no-oped -- while it still gets called, it does not set the
rcu CPU map.

With a blank RCU CPU map, grace periods get to tick by completely
oblivious to active RCU read side critical sections.  This results in
free-before-grace bugs.

Fix is obvious once the problem is known. (Also, change __devinit to
__cpuinit so the function gets thrown away on !HOTPLUG_CPU kernels).

Signed-off-by: default avatarNick Piggin <npiggin@suse.de>
Reported-and-tested-by: default avatarAlexey Dobriyan <adobriyan@gmail.com>
Acked-by: default avatarIngo Molnar <mingo@elte.hu>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
[ Nick is my personal hero of the day - Linus ]
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent eb6d42ea
Loading
Loading
Loading
Loading
+8 −12
Original line number Original line Diff line number Diff line
@@ -925,26 +925,22 @@ void rcu_offline_cpu(int cpu)
	spin_unlock_irqrestore(&rdp->lock, flags);
	spin_unlock_irqrestore(&rdp->lock, flags);
}
}


void __devinit rcu_online_cpu(int cpu)
{
	unsigned long flags;

	spin_lock_irqsave(&rcu_ctrlblk.fliplock, flags);
	cpu_set(cpu, rcu_cpu_online_map);
	spin_unlock_irqrestore(&rcu_ctrlblk.fliplock, flags);
}

#else /* #ifdef CONFIG_HOTPLUG_CPU */
#else /* #ifdef CONFIG_HOTPLUG_CPU */


void rcu_offline_cpu(int cpu)
void rcu_offline_cpu(int cpu)
{
{
}
}


void __devinit rcu_online_cpu(int cpu)
#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */

void __cpuinit rcu_online_cpu(int cpu)
{
{
}
	unsigned long flags;


#endif /* #else #ifdef CONFIG_HOTPLUG_CPU */
	spin_lock_irqsave(&rcu_ctrlblk.fliplock, flags);
	cpu_set(cpu, rcu_cpu_online_map);
	spin_unlock_irqrestore(&rcu_ctrlblk.fliplock, flags);
}


static void rcu_process_callbacks(struct softirq_action *unused)
static void rcu_process_callbacks(struct softirq_action *unused)
{
{