diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/rcu/tree.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index d2fa95e4a268..fcfdbe53bb70 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c | |||
@@ -2838,11 +2838,21 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu), | |||
2838 | 2838 | ||
2839 | if (cpu != -1) | 2839 | if (cpu != -1) |
2840 | rdp = per_cpu_ptr(rsp->rda, cpu); | 2840 | rdp = per_cpu_ptr(rsp->rda, cpu); |
2841 | offline = !__call_rcu_nocb(rdp, head, lazy, flags); | 2841 | if (likely(rdp->mynode)) { |
2842 | WARN_ON_ONCE(offline); | 2842 | /* Post-boot, so this should be for a no-CBs CPU. */ |
2843 | /* _call_rcu() is illegal on offline CPU; leak the callback. */ | 2843 | offline = !__call_rcu_nocb(rdp, head, lazy, flags); |
2844 | local_irq_restore(flags); | 2844 | WARN_ON_ONCE(offline); |
2845 | return; | 2845 | /* Offline CPU, _call_rcu() illegal, leak callback. */ |
2846 | local_irq_restore(flags); | ||
2847 | return; | ||
2848 | } | ||
2849 | /* | ||
2850 | * Very early boot, before rcu_init(). Initialize if needed | ||
2851 | * and then drop through to queue the callback. | ||
2852 | */ | ||
2853 | BUG_ON(cpu != -1); | ||
2854 | if (!likely(rdp->nxtlist)) | ||
2855 | init_default_callback_list(rdp); | ||
2846 | } | 2856 | } |
2847 | ACCESS_ONCE(rdp->qlen) = rdp->qlen + 1; | 2857 | ACCESS_ONCE(rdp->qlen) = rdp->qlen + 1; |
2848 | if (lazy) | 2858 | if (lazy) |