mirror of https://gitee.com/openkylin/linux.git
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: John Kacur <jkacur@redhat.com> Tested-by: Thomas Gleixner <tglx@linutronix.de> Located-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Paul 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: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
1304afb225
commit
3acd9eb31c
|
@ -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++)
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue