diff options
| author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2018-05-15 19:23:23 -0400 |
|---|---|---|
| committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2018-07-12 18:39:10 -0400 |
| commit | f2e2df59786d7bd52e6e7e2d10c1c6ba433a0ee7 (patch) | |
| tree | 83228ad0b1384cdb37e5be871f21f9d1cbababc8 /kernel | |
| parent | fea3f222d3523dfdd0e86b11227d3cda20765102 (diff) | |
rcu: Add diagnostics for offline CPUs failing to report QS
CPUs are expected to report quiescent states when coming online and
when going offline, and grace-period initialization is supposed to
handle any race conditions where a CPU's ->qsmask bit is set just after
it goes offline. This commit adds diagnostics for the case where an
offline CPU nevertheless has a grace period waiting on it.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/rcu/tree.c | 22 | ||||
| -rw-r--r-- | kernel/rcu/tree.h | 1 |
2 files changed, 23 insertions, 0 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index ee218d743226..d3333ee2c6f5 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c | |||
| @@ -1188,6 +1188,27 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp) | |||
| 1188 | smp_store_release(ruqp, true); | 1188 | smp_store_release(ruqp, true); |
| 1189 | } | 1189 | } |
| 1190 | 1190 | ||
| 1191 | /* If waiting too long on an offline CPU, complain. */ | ||
| 1192 | if (!(rdp->grpmask & rcu_rnp_online_cpus(rnp)) && | ||
| 1193 | time_after(jiffies, rdp->rsp->gp_start + HZ)) { | ||
| 1194 | bool onl; | ||
| 1195 | struct rcu_node *rnp1; | ||
| 1196 | |||
| 1197 | WARN_ON(1); /* Offline CPUs are supposed to report QS! */ | ||
| 1198 | pr_info("%s: grp: %d-%d level: %d ->gp_seq %ld ->completedqs %ld\n", | ||
| 1199 | __func__, rnp->grplo, rnp->grphi, rnp->level, | ||
| 1200 | (long)rnp->gp_seq, (long)rnp->completedqs); | ||
| 1201 | for (rnp1 = rnp; rnp1; rnp1 = rnp1->parent) | ||
| 1202 | pr_info("%s: %d:%d ->qsmask %#lx ->qsmaskinit %#lx ->qsmaskinitnext %#lx ->rcu_gp_init_mask %#lx\n", | ||
| 1203 | __func__, rnp1->grplo, rnp1->grphi, rnp1->qsmask, rnp1->qsmaskinit, rnp1->qsmaskinitnext, rnp1->rcu_gp_init_mask); | ||
| 1204 | onl = !!(rdp->grpmask & rcu_rnp_online_cpus(rnp)); | ||
| 1205 | pr_info("%s %d: %c online: %ld(%d) offline: %ld(%d)\n", | ||
| 1206 | __func__, rdp->cpu, ".o"[onl], | ||
| 1207 | (long)rdp->rcu_onl_gp_seq, rdp->rcu_onl_gp_flags, | ||
| 1208 | (long)rdp->rcu_ofl_gp_seq, rdp->rcu_ofl_gp_flags); | ||
| 1209 | return 1; /* Break things loose after complaining. */ | ||
| 1210 | } | ||
| 1211 | |||
| 1191 | /* | 1212 | /* |
| 1192 | * A CPU running for an extended time within the kernel can | 1213 | * A CPU running for an extended time within the kernel can |
| 1193 | * delay RCU grace periods. When the CPU is in NO_HZ_FULL mode, | 1214 | * delay RCU grace periods. When the CPU is in NO_HZ_FULL mode, |
| @@ -1967,6 +1988,7 @@ static bool rcu_gp_init(struct rcu_state *rsp) | |||
| 1967 | rnp->grphi, rnp->qsmask); | 1988 | rnp->grphi, rnp->qsmask); |
| 1968 | /* Quiescent states for tasks on any now-offline CPUs. */ | 1989 | /* Quiescent states for tasks on any now-offline CPUs. */ |
| 1969 | mask = rnp->qsmask & ~rnp->qsmaskinitnext; | 1990 | mask = rnp->qsmask & ~rnp->qsmaskinitnext; |
| 1991 | rnp->rcu_gp_init_mask = mask; | ||
| 1970 | if ((mask || rnp->wait_blkd_tasks) && rcu_is_leaf_node(rnp)) | 1992 | if ((mask || rnp->wait_blkd_tasks) && rcu_is_leaf_node(rnp)) |
| 1971 | rcu_report_qs_rnp(mask, rsp, rnp, rnp->gp_seq, flags); | 1993 | rcu_report_qs_rnp(mask, rsp, rnp, rnp->gp_seq, flags); |
| 1972 | else | 1994 | else |
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h index 8077aff7ab40..d51e6edc8e83 100644 --- a/kernel/rcu/tree.h +++ b/kernel/rcu/tree.h | |||
| @@ -90,6 +90,7 @@ struct rcu_node { | |||
| 90 | /* an rcu_data structure, otherwise, each */ | 90 | /* an rcu_data structure, otherwise, each */ |
| 91 | /* bit corresponds to a child rcu_node */ | 91 | /* bit corresponds to a child rcu_node */ |
| 92 | /* structure. */ | 92 | /* structure. */ |
| 93 | unsigned long rcu_gp_init_mask; /* Mask of offline CPUs at GP init. */ | ||
| 93 | unsigned long qsmaskinit; | 94 | unsigned long qsmaskinit; |
| 94 | /* Per-GP initial value for qsmask. */ | 95 | /* Per-GP initial value for qsmask. */ |
| 95 | /* Initialized from ->qsmaskinitnext at the */ | 96 | /* Initialized from ->qsmaskinitnext at the */ |
