diff options
Diffstat (limited to 'kernel/rcutree.c')
-rw-r--r-- | kernel/rcutree.c | 40 |
1 files changed, 21 insertions, 19 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 9b36d6d7fb97..b79bfcd28e95 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c | |||
@@ -51,7 +51,7 @@ | |||
51 | 51 | ||
52 | /* Data structures. */ | 52 | /* Data structures. */ |
53 | 53 | ||
54 | static struct lock_class_key rcu_root_class; | 54 | static struct lock_class_key rcu_node_class[NUM_RCU_LVLS]; |
55 | 55 | ||
56 | #define RCU_STATE_INITIALIZER(name) { \ | 56 | #define RCU_STATE_INITIALIZER(name) { \ |
57 | .level = { &name.node[0] }, \ | 57 | .level = { &name.node[0] }, \ |
@@ -936,6 +936,7 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp) | |||
936 | { | 936 | { |
937 | unsigned long flags; | 937 | unsigned long flags; |
938 | unsigned long mask; | 938 | unsigned long mask; |
939 | int need_quiet = 0; | ||
939 | struct rcu_data *rdp = rsp->rda[cpu]; | 940 | struct rcu_data *rdp = rsp->rda[cpu]; |
940 | struct rcu_node *rnp; | 941 | struct rcu_node *rnp; |
941 | 942 | ||
@@ -949,29 +950,30 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp) | |||
949 | spin_lock(&rnp->lock); /* irqs already disabled. */ | 950 | spin_lock(&rnp->lock); /* irqs already disabled. */ |
950 | rnp->qsmaskinit &= ~mask; | 951 | rnp->qsmaskinit &= ~mask; |
951 | if (rnp->qsmaskinit != 0) { | 952 | if (rnp->qsmaskinit != 0) { |
952 | spin_unlock(&rnp->lock); /* irqs remain disabled. */ | 953 | if (rnp != rdp->mynode) |
954 | spin_unlock(&rnp->lock); /* irqs remain disabled. */ | ||
953 | break; | 955 | break; |
954 | } | 956 | } |
955 | 957 | if (rnp == rdp->mynode) | |
956 | /* | 958 | need_quiet = rcu_preempt_offline_tasks(rsp, rnp, rdp); |
957 | * If there was a task blocking the current grace period, | 959 | else |
958 | * and if all CPUs have checked in, we need to propagate | 960 | spin_unlock(&rnp->lock); /* irqs remain disabled. */ |
959 | * the quiescent state up the rcu_node hierarchy. But that | ||
960 | * is inconvenient at the moment due to deadlock issues if | ||
961 | * this should end the current grace period. So set the | ||
962 | * offlined CPU's bit in ->qsmask in order to force the | ||
963 | * next force_quiescent_state() invocation to clean up this | ||
964 | * mess in a deadlock-free manner. | ||
965 | */ | ||
966 | if (rcu_preempt_offline_tasks(rsp, rnp, rdp) && !rnp->qsmask) | ||
967 | rnp->qsmask |= mask; | ||
968 | |||
969 | mask = rnp->grpmask; | 961 | mask = rnp->grpmask; |
970 | spin_unlock(&rnp->lock); /* irqs remain disabled. */ | ||
971 | rnp = rnp->parent; | 962 | rnp = rnp->parent; |
972 | } while (rnp != NULL); | 963 | } while (rnp != NULL); |
973 | 964 | ||
974 | spin_unlock_irqrestore(&rsp->onofflock, flags); | 965 | /* |
966 | * We still hold the leaf rcu_node structure lock here, and | ||
967 | * irqs are still disabled. The reason for this subterfuge is | ||
968 | * because invoking task_quiet() with ->onofflock held leads | ||
969 | * to deadlock. | ||
970 | */ | ||
971 | spin_unlock(&rsp->onofflock); /* irqs remain disabled. */ | ||
972 | rnp = rdp->mynode; | ||
973 | if (need_quiet) | ||
974 | task_quiet(rnp, flags); | ||
975 | else | ||
976 | spin_unlock_irqrestore(&rnp->lock, flags); | ||
975 | 977 | ||
976 | rcu_adopt_orphan_cbs(rsp); | 978 | rcu_adopt_orphan_cbs(rsp); |
977 | } | 979 | } |
@@ -1731,6 +1733,7 @@ static void __init rcu_init_one(struct rcu_state *rsp) | |||
1731 | rnp = rsp->level[i]; | 1733 | rnp = rsp->level[i]; |
1732 | for (j = 0; j < rsp->levelcnt[i]; j++, rnp++) { | 1734 | for (j = 0; j < rsp->levelcnt[i]; j++, rnp++) { |
1733 | spin_lock_init(&rnp->lock); | 1735 | spin_lock_init(&rnp->lock); |
1736 | lockdep_set_class(&rnp->lock, &rcu_node_class[i]); | ||
1734 | rnp->gpnum = 0; | 1737 | rnp->gpnum = 0; |
1735 | rnp->qsmask = 0; | 1738 | rnp->qsmask = 0; |
1736 | rnp->qsmaskinit = 0; | 1739 | rnp->qsmaskinit = 0; |
@@ -1753,7 +1756,6 @@ static void __init rcu_init_one(struct rcu_state *rsp) | |||
1753 | INIT_LIST_HEAD(&rnp->blocked_tasks[1]); | 1756 | INIT_LIST_HEAD(&rnp->blocked_tasks[1]); |
1754 | } | 1757 | } |
1755 | } | 1758 | } |
1756 | lockdep_set_class(&rcu_get_root(rsp)->lock, &rcu_root_class); | ||
1757 | } | 1759 | } |
1758 | 1760 | ||
1759 | /* | 1761 | /* |