diff options
Diffstat (limited to 'kernel/rcutree.c')
-rw-r--r-- | kernel/rcutree.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c index d8024192c73b..b4efb9e36680 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c | |||
@@ -676,7 +676,23 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags) | |||
676 | struct rcu_node *rnp = rcu_get_root(rsp); | 676 | struct rcu_node *rnp = rcu_get_root(rsp); |
677 | 677 | ||
678 | if (!cpu_needs_another_gp(rsp, rdp)) { | 678 | if (!cpu_needs_another_gp(rsp, rdp)) { |
679 | spin_unlock_irqrestore(&rnp->lock, flags); | 679 | if (rnp->completed == rsp->completed) { |
680 | spin_unlock_irqrestore(&rnp->lock, flags); | ||
681 | return; | ||
682 | } | ||
683 | spin_unlock(&rnp->lock); /* irqs remain disabled. */ | ||
684 | |||
685 | /* | ||
686 | * Propagate new ->completed value to rcu_node structures | ||
687 | * so that other CPUs don't have to wait until the start | ||
688 | * of the next grace period to process their callbacks. | ||
689 | */ | ||
690 | rcu_for_each_node_breadth_first(rsp, rnp) { | ||
691 | spin_lock(&rnp->lock); /* irqs already disabled. */ | ||
692 | rnp->completed = rsp->completed; | ||
693 | spin_unlock(&rnp->lock); /* irqs remain disabled. */ | ||
694 | } | ||
695 | local_irq_restore(flags); | ||
680 | return; | 696 | return; |
681 | } | 697 | } |
682 | 698 | ||