diff options
| -rw-r--r-- | kernel/rcu/tree.c | 7 | 
1 files changed, 6 insertions, 1 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 4ea28e820f4a..c080c6ed66af 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3926,6 +3926,7 @@ static void rcu_migrate_callbacks(int cpu, struct rcu_state *rsp)  	struct rcu_data *my_rdp;  	struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);  	struct rcu_node *rnp = rdp->mynode;  /* Outgoing CPU's rdp & rnp. */ +	struct rcu_node *rnp_root = rcu_get_root(rdp->rsp);  	if (rcu_is_nocb_cpu(cpu) || rcu_segcblist_empty(&rdp->cblist))  		return;  /* No callbacks to migrate. */ @@ -3936,7 +3937,11 @@ static void rcu_migrate_callbacks(int cpu, struct rcu_state *rsp)  		local_irq_restore(flags);  		return;  	} -	raw_spin_lock(&rsp->orphan_lock); /* irqs already disabled. */ +	raw_spin_lock_rcu_node(rnp_root); /* irqs already disabled. */ +	rcu_advance_cbs(rsp, rnp_root, rdp); /* Leverage recent GPs. */ +	raw_spin_unlock_rcu_node(rnp_root); + +	raw_spin_lock(&rsp->orphan_lock);  	rcu_send_cbs_to_orphanage(cpu, rsp, rnp, rdp);  	rcu_adopt_orphan_cbs(rsp, flags);  	raw_spin_unlock_irqrestore(&rsp->orphan_lock, flags);  | 

