diff options
Diffstat (limited to 'kernel/rcutree_trace.c')
| -rw-r--r-- | kernel/rcutree_trace.c | 148 |
1 files changed, 78 insertions, 70 deletions
diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c index d4bc16ddd1d4..abffb486e94e 100644 --- a/kernel/rcutree_trace.c +++ b/kernel/rcutree_trace.c | |||
| @@ -46,6 +46,31 @@ | |||
| 46 | #define RCU_TREE_NONCORE | 46 | #define RCU_TREE_NONCORE |
| 47 | #include "rcutree.h" | 47 | #include "rcutree.h" |
| 48 | 48 | ||
| 49 | static int show_rcubarrier(struct seq_file *m, void *unused) | ||
| 50 | { | ||
| 51 | struct rcu_state *rsp; | ||
| 52 | |||
| 53 | for_each_rcu_flavor(rsp) | ||
| 54 | seq_printf(m, "%s: %c bcc: %d nbd: %lu\n", | ||
| 55 | rsp->name, rsp->rcu_barrier_in_progress ? 'B' : '.', | ||
| 56 | atomic_read(&rsp->barrier_cpu_count), | ||
| 57 | rsp->n_barrier_done); | ||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | static int rcubarrier_open(struct inode *inode, struct file *file) | ||
| 62 | { | ||
| 63 | return single_open(file, show_rcubarrier, NULL); | ||
| 64 | } | ||
| 65 | |||
| 66 | static const struct file_operations rcubarrier_fops = { | ||
| 67 | .owner = THIS_MODULE, | ||
| 68 | .open = rcubarrier_open, | ||
| 69 | .read = seq_read, | ||
| 70 | .llseek = seq_lseek, | ||
| 71 | .release = single_release, | ||
| 72 | }; | ||
| 73 | |||
| 49 | #ifdef CONFIG_RCU_BOOST | 74 | #ifdef CONFIG_RCU_BOOST |
| 50 | 75 | ||
| 51 | static char convert_kthread_status(unsigned int kthread_status) | 76 | static char convert_kthread_status(unsigned int kthread_status) |
| @@ -95,24 +120,16 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) | |||
| 95 | rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted); | 120 | rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted); |
| 96 | } | 121 | } |
| 97 | 122 | ||
| 98 | #define PRINT_RCU_DATA(name, func, m) \ | ||
| 99 | do { \ | ||
| 100 | int _p_r_d_i; \ | ||
| 101 | \ | ||
| 102 | for_each_possible_cpu(_p_r_d_i) \ | ||
| 103 | func(m, &per_cpu(name, _p_r_d_i)); \ | ||
| 104 | } while (0) | ||
| 105 | |||
| 106 | static int show_rcudata(struct seq_file *m, void *unused) | 123 | static int show_rcudata(struct seq_file *m, void *unused) |
| 107 | { | 124 | { |
| 108 | #ifdef CONFIG_TREE_PREEMPT_RCU | 125 | int cpu; |
| 109 | seq_puts(m, "rcu_preempt:\n"); | 126 | struct rcu_state *rsp; |
| 110 | PRINT_RCU_DATA(rcu_preempt_data, print_one_rcu_data, m); | 127 | |
| 111 | #endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ | 128 | for_each_rcu_flavor(rsp) { |
| 112 | seq_puts(m, "rcu_sched:\n"); | 129 | seq_printf(m, "%s:\n", rsp->name); |
| 113 | PRINT_RCU_DATA(rcu_sched_data, print_one_rcu_data, m); | 130 | for_each_possible_cpu(cpu) |
| 114 | seq_puts(m, "rcu_bh:\n"); | 131 | print_one_rcu_data(m, per_cpu_ptr(rsp->rda, cpu)); |
| 115 | PRINT_RCU_DATA(rcu_bh_data, print_one_rcu_data, m); | 132 | } |
| 116 | return 0; | 133 | return 0; |
| 117 | } | 134 | } |
| 118 | 135 | ||
| @@ -166,6 +183,9 @@ static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp) | |||
| 166 | 183 | ||
| 167 | static int show_rcudata_csv(struct seq_file *m, void *unused) | 184 | static int show_rcudata_csv(struct seq_file *m, void *unused) |
| 168 | { | 185 | { |
| 186 | int cpu; | ||
| 187 | struct rcu_state *rsp; | ||
| 188 | |||
| 169 | seq_puts(m, "\"CPU\",\"Online?\",\"c\",\"g\",\"pq\",\"pgp\",\"pq\","); | 189 | seq_puts(m, "\"CPU\",\"Online?\",\"c\",\"g\",\"pq\",\"pgp\",\"pq\","); |
| 170 | seq_puts(m, "\"dt\",\"dt nesting\",\"dt NMI nesting\",\"df\","); | 190 | seq_puts(m, "\"dt\",\"dt nesting\",\"dt NMI nesting\",\"df\","); |
| 171 | seq_puts(m, "\"of\",\"qll\",\"ql\",\"qs\""); | 191 | seq_puts(m, "\"of\",\"qll\",\"ql\",\"qs\""); |
| @@ -173,14 +193,11 @@ static int show_rcudata_csv(struct seq_file *m, void *unused) | |||
| 173 | seq_puts(m, "\"kt\",\"ktl\""); | 193 | seq_puts(m, "\"kt\",\"ktl\""); |
| 174 | #endif /* #ifdef CONFIG_RCU_BOOST */ | 194 | #endif /* #ifdef CONFIG_RCU_BOOST */ |
| 175 | seq_puts(m, ",\"b\",\"ci\",\"co\",\"ca\"\n"); | 195 | seq_puts(m, ",\"b\",\"ci\",\"co\",\"ca\"\n"); |
| 176 | #ifdef CONFIG_TREE_PREEMPT_RCU | 196 | for_each_rcu_flavor(rsp) { |
| 177 | seq_puts(m, "\"rcu_preempt:\"\n"); | 197 | seq_printf(m, "\"%s:\"\n", rsp->name); |
| 178 | PRINT_RCU_DATA(rcu_preempt_data, print_one_rcu_data_csv, m); | 198 | for_each_possible_cpu(cpu) |
| 179 | #endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ | 199 | print_one_rcu_data_csv(m, per_cpu_ptr(rsp->rda, cpu)); |
| 180 | seq_puts(m, "\"rcu_sched:\"\n"); | 200 | } |
| 181 | PRINT_RCU_DATA(rcu_sched_data, print_one_rcu_data_csv, m); | ||
| 182 | seq_puts(m, "\"rcu_bh:\"\n"); | ||
| 183 | PRINT_RCU_DATA(rcu_bh_data, print_one_rcu_data_csv, m); | ||
| 184 | return 0; | 201 | return 0; |
| 185 | } | 202 | } |
| 186 | 203 | ||
| @@ -201,8 +218,7 @@ static const struct file_operations rcudata_csv_fops = { | |||
| 201 | 218 | ||
| 202 | static void print_one_rcu_node_boost(struct seq_file *m, struct rcu_node *rnp) | 219 | static void print_one_rcu_node_boost(struct seq_file *m, struct rcu_node *rnp) |
| 203 | { | 220 | { |
| 204 | seq_printf(m, "%d:%d tasks=%c%c%c%c kt=%c ntb=%lu neb=%lu nnb=%lu " | 221 | seq_printf(m, "%d:%d tasks=%c%c%c%c kt=%c ntb=%lu neb=%lu nnb=%lu ", |
| 205 | "j=%04x bt=%04x\n", | ||
| 206 | rnp->grplo, rnp->grphi, | 222 | rnp->grplo, rnp->grphi, |
| 207 | "T."[list_empty(&rnp->blkd_tasks)], | 223 | "T."[list_empty(&rnp->blkd_tasks)], |
| 208 | "N."[!rnp->gp_tasks], | 224 | "N."[!rnp->gp_tasks], |
| @@ -210,11 +226,11 @@ static void print_one_rcu_node_boost(struct seq_file *m, struct rcu_node *rnp) | |||
| 210 | "B."[!rnp->boost_tasks], | 226 | "B."[!rnp->boost_tasks], |
| 211 | convert_kthread_status(rnp->boost_kthread_status), | 227 | convert_kthread_status(rnp->boost_kthread_status), |
| 212 | rnp->n_tasks_boosted, rnp->n_exp_boosts, | 228 | rnp->n_tasks_boosted, rnp->n_exp_boosts, |
| 213 | rnp->n_normal_boosts, | 229 | rnp->n_normal_boosts); |
| 230 | seq_printf(m, "j=%04x bt=%04x\n", | ||
| 214 | (int)(jiffies & 0xffff), | 231 | (int)(jiffies & 0xffff), |
| 215 | (int)(rnp->boost_time & 0xffff)); | 232 | (int)(rnp->boost_time & 0xffff)); |
| 216 | seq_printf(m, "%s: nt=%lu egt=%lu bt=%lu nb=%lu ny=%lu nos=%lu\n", | 233 | seq_printf(m, " balk: nt=%lu egt=%lu bt=%lu nb=%lu ny=%lu nos=%lu\n", |
| 217 | " balk", | ||
| 218 | rnp->n_balk_blkd_tasks, | 234 | rnp->n_balk_blkd_tasks, |
| 219 | rnp->n_balk_exp_gp_tasks, | 235 | rnp->n_balk_exp_gp_tasks, |
| 220 | rnp->n_balk_boost_tasks, | 236 | rnp->n_balk_boost_tasks, |
| @@ -270,15 +286,15 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp) | |||
| 270 | struct rcu_node *rnp; | 286 | struct rcu_node *rnp; |
| 271 | 287 | ||
| 272 | gpnum = rsp->gpnum; | 288 | gpnum = rsp->gpnum; |
| 273 | seq_printf(m, "c=%lu g=%lu s=%d jfq=%ld j=%x " | 289 | seq_printf(m, "%s: c=%lu g=%lu s=%d jfq=%ld j=%x ", |
| 274 | "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n", | 290 | rsp->name, rsp->completed, gpnum, rsp->fqs_state, |
| 275 | rsp->completed, gpnum, rsp->fqs_state, | ||
| 276 | (long)(rsp->jiffies_force_qs - jiffies), | 291 | (long)(rsp->jiffies_force_qs - jiffies), |
| 277 | (int)(jiffies & 0xffff), | 292 | (int)(jiffies & 0xffff)); |
| 293 | seq_printf(m, "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n", | ||
| 278 | rsp->n_force_qs, rsp->n_force_qs_ngp, | 294 | rsp->n_force_qs, rsp->n_force_qs_ngp, |
| 279 | rsp->n_force_qs - rsp->n_force_qs_ngp, | 295 | rsp->n_force_qs - rsp->n_force_qs_ngp, |
| 280 | rsp->n_force_qs_lh, rsp->qlen_lazy, rsp->qlen); | 296 | rsp->n_force_qs_lh, rsp->qlen_lazy, rsp->qlen); |
| 281 | for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < NUM_RCU_NODES; rnp++) { | 297 | for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < rcu_num_nodes; rnp++) { |
| 282 | if (rnp->level != level) { | 298 | if (rnp->level != level) { |
| 283 | seq_puts(m, "\n"); | 299 | seq_puts(m, "\n"); |
| 284 | level = rnp->level; | 300 | level = rnp->level; |
| @@ -295,14 +311,10 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp) | |||
| 295 | 311 | ||
| 296 | static int show_rcuhier(struct seq_file *m, void *unused) | 312 | static int show_rcuhier(struct seq_file *m, void *unused) |
| 297 | { | 313 | { |
| 298 | #ifdef CONFIG_TREE_PREEMPT_RCU | 314 | struct rcu_state *rsp; |
| 299 | seq_puts(m, "rcu_preempt:\n"); | 315 | |
| 300 | print_one_rcu_state(m, &rcu_preempt_state); | 316 | for_each_rcu_flavor(rsp) |
| 301 | #endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ | 317 | print_one_rcu_state(m, rsp); |
| 302 | seq_puts(m, "rcu_sched:\n"); | ||
| 303 | print_one_rcu_state(m, &rcu_sched_state); | ||
| 304 | seq_puts(m, "rcu_bh:\n"); | ||
| 305 | print_one_rcu_state(m, &rcu_bh_state); | ||
| 306 | return 0; | 318 | return 0; |
| 307 | } | 319 | } |
| 308 | 320 | ||
| @@ -343,11 +355,10 @@ static void show_one_rcugp(struct seq_file *m, struct rcu_state *rsp) | |||
| 343 | 355 | ||
| 344 | static int show_rcugp(struct seq_file *m, void *unused) | 356 | static int show_rcugp(struct seq_file *m, void *unused) |
| 345 | { | 357 | { |
| 346 | #ifdef CONFIG_TREE_PREEMPT_RCU | 358 | struct rcu_state *rsp; |
| 347 | show_one_rcugp(m, &rcu_preempt_state); | 359 | |
| 348 | #endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ | 360 | for_each_rcu_flavor(rsp) |
| 349 | show_one_rcugp(m, &rcu_sched_state); | 361 | show_one_rcugp(m, rsp); |
| 350 | show_one_rcugp(m, &rcu_bh_state); | ||
| 351 | return 0; | 362 | return 0; |
| 352 | } | 363 | } |
| 353 | 364 | ||
| @@ -366,44 +377,36 @@ static const struct file_operations rcugp_fops = { | |||
| 366 | 377 | ||
| 367 | static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp) | 378 | static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp) |
| 368 | { | 379 | { |
| 369 | seq_printf(m, "%3d%cnp=%ld " | 380 | seq_printf(m, "%3d%cnp=%ld ", |
| 370 | "qsp=%ld rpq=%ld cbr=%ld cng=%ld " | ||
| 371 | "gpc=%ld gps=%ld nf=%ld nn=%ld\n", | ||
| 372 | rdp->cpu, | 381 | rdp->cpu, |
| 373 | cpu_is_offline(rdp->cpu) ? '!' : ' ', | 382 | cpu_is_offline(rdp->cpu) ? '!' : ' ', |
| 374 | rdp->n_rcu_pending, | 383 | rdp->n_rcu_pending); |
| 384 | seq_printf(m, "qsp=%ld rpq=%ld cbr=%ld cng=%ld ", | ||
| 375 | rdp->n_rp_qs_pending, | 385 | rdp->n_rp_qs_pending, |
| 376 | rdp->n_rp_report_qs, | 386 | rdp->n_rp_report_qs, |
| 377 | rdp->n_rp_cb_ready, | 387 | rdp->n_rp_cb_ready, |
| 378 | rdp->n_rp_cpu_needs_gp, | 388 | rdp->n_rp_cpu_needs_gp); |
| 389 | seq_printf(m, "gpc=%ld gps=%ld nf=%ld nn=%ld\n", | ||
| 379 | rdp->n_rp_gp_completed, | 390 | rdp->n_rp_gp_completed, |
| 380 | rdp->n_rp_gp_started, | 391 | rdp->n_rp_gp_started, |
| 381 | rdp->n_rp_need_fqs, | 392 | rdp->n_rp_need_fqs, |
| 382 | rdp->n_rp_need_nothing); | 393 | rdp->n_rp_need_nothing); |
| 383 | } | 394 | } |
| 384 | 395 | ||
| 385 | static void print_rcu_pendings(struct seq_file *m, struct rcu_state *rsp) | 396 | static int show_rcu_pending(struct seq_file *m, void *unused) |
| 386 | { | 397 | { |
| 387 | int cpu; | 398 | int cpu; |
| 388 | struct rcu_data *rdp; | 399 | struct rcu_data *rdp; |
| 389 | 400 | struct rcu_state *rsp; | |
| 390 | for_each_possible_cpu(cpu) { | 401 | |
| 391 | rdp = per_cpu_ptr(rsp->rda, cpu); | 402 | for_each_rcu_flavor(rsp) { |
| 392 | if (rdp->beenonline) | 403 | seq_printf(m, "%s:\n", rsp->name); |
| 393 | print_one_rcu_pending(m, rdp); | 404 | for_each_possible_cpu(cpu) { |
| 405 | rdp = per_cpu_ptr(rsp->rda, cpu); | ||
| 406 | if (rdp->beenonline) | ||
| 407 | print_one_rcu_pending(m, rdp); | ||
| 408 | } | ||
| 394 | } | 409 | } |
| 395 | } | ||
| 396 | |||
| 397 | static int show_rcu_pending(struct seq_file *m, void *unused) | ||
| 398 | { | ||
| 399 | #ifdef CONFIG_TREE_PREEMPT_RCU | ||
| 400 | seq_puts(m, "rcu_preempt:\n"); | ||
| 401 | print_rcu_pendings(m, &rcu_preempt_state); | ||
| 402 | #endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ | ||
| 403 | seq_puts(m, "rcu_sched:\n"); | ||
| 404 | print_rcu_pendings(m, &rcu_sched_state); | ||
| 405 | seq_puts(m, "rcu_bh:\n"); | ||
| 406 | print_rcu_pendings(m, &rcu_bh_state); | ||
| 407 | return 0; | 410 | return 0; |
| 408 | } | 411 | } |
| 409 | 412 | ||
| @@ -453,6 +456,11 @@ static int __init rcutree_trace_init(void) | |||
| 453 | if (!rcudir) | 456 | if (!rcudir) |
| 454 | goto free_out; | 457 | goto free_out; |
| 455 | 458 | ||
| 459 | retval = debugfs_create_file("rcubarrier", 0444, rcudir, | ||
| 460 | NULL, &rcubarrier_fops); | ||
| 461 | if (!retval) | ||
| 462 | goto free_out; | ||
| 463 | |||
| 456 | retval = debugfs_create_file("rcudata", 0444, rcudir, | 464 | retval = debugfs_create_file("rcudata", 0444, rcudir, |
| 457 | NULL, &rcudata_fops); | 465 | NULL, &rcudata_fops); |
| 458 | if (!retval) | 466 | if (!retval) |
