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

Commit 3acd9eb3 authored by Paul E. McKenney's avatar Paul E. McKenney Committed by Ingo Molnar
Browse files

rcu: Fix deadlock in TREE_PREEMPT_RCU CPU stall detection



Under TREE_PREEMPT_RCU, print_other_cpu_stall() invokes
rcu_print_task_stall() with the root rcu_node structure's ->lock
held, and rcu_print_task_stall() acquires that same lock for
self-deadlock. Fix this by removing the lock acquisition from
rcu_print_task_stall(), and making all callers acquire the lock
instead.

Tested-by: default avatarJohn Kacur <jkacur@redhat.com>
Tested-by: default avatarThomas Gleixner <tglx@linutronix.de>
Located-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: laijs@cn.fujitsu.com
Cc: dipankar@in.ibm.com
Cc: mathieu.desnoyers@polymtl.ca
Cc: josh@joshtriplett.org
Cc: dvhltc@us.ibm.com
Cc: niv@us.ibm.com
Cc: peterz@infradead.org
Cc: rostedt@goodmis.org
Cc: Valdis.Kletnieks@vt.edu
Cc: dhowells@redhat.com
LKML-Reference: <1266887105-1528-19-git-send-email-paulmck@linux.vnet.ibm.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 1304afb2
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -476,7 +476,9 @@ static void print_other_cpu_stall(struct rcu_state *rsp)


	printk(KERN_ERR "INFO: RCU detected CPU stalls:");
	printk(KERN_ERR "INFO: RCU detected CPU stalls:");
	rcu_for_each_leaf_node(rsp, rnp) {
	rcu_for_each_leaf_node(rsp, rnp) {
		raw_spin_lock_irqsave(&rnp->lock, flags);
		rcu_print_task_stall(rnp);
		rcu_print_task_stall(rnp);
		raw_spin_unlock_irqrestore(&rnp->lock, flags);
		if (rnp->qsmask == 0)
		if (rnp->qsmask == 0)
			continue;
			continue;
		for (cpu = 0; cpu <= rnp->grphi - rnp->grplo; cpu++)
		for (cpu = 0; cpu <= rnp->grphi - rnp->grplo; cpu++)
+0 −3
Original line number Original line Diff line number Diff line
@@ -318,18 +318,15 @@ EXPORT_SYMBOL_GPL(__rcu_read_unlock);
 */
 */
static void rcu_print_task_stall(struct rcu_node *rnp)
static void rcu_print_task_stall(struct rcu_node *rnp)
{
{
	unsigned long flags;
	struct list_head *lp;
	struct list_head *lp;
	int phase;
	int phase;
	struct task_struct *t;
	struct task_struct *t;


	if (rcu_preempted_readers(rnp)) {
	if (rcu_preempted_readers(rnp)) {
		raw_spin_lock_irqsave(&rnp->lock, flags);
		phase = rnp->gpnum & 0x1;
		phase = rnp->gpnum & 0x1;
		lp = &rnp->blocked_tasks[phase];
		lp = &rnp->blocked_tasks[phase];
		list_for_each_entry(t, lp, rcu_node_entry)
		list_for_each_entry(t, lp, rcu_node_entry)
			printk(" P%d", t->pid);
			printk(" P%d", t->pid);
		raw_spin_unlock_irqrestore(&rnp->lock, flags);
	}
	}
}
}