diff options
Diffstat (limited to 'kernel/rcutree_trace.c')
-rw-r--r-- | kernel/rcutree_trace.c | 330 |
1 files changed, 162 insertions, 168 deletions
diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c index 693513bc50e6..0d095dcaa670 100644 --- a/kernel/rcutree_trace.c +++ b/kernel/rcutree_trace.c | |||
@@ -46,29 +46,58 @@ | |||
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) | 49 | #define ulong2long(a) (*(long *)(&(a))) |
50 | |||
51 | static int r_open(struct inode *inode, struct file *file, | ||
52 | const struct seq_operations *op) | ||
50 | { | 53 | { |
51 | struct rcu_state *rsp; | 54 | int ret = seq_open(file, op); |
55 | if (!ret) { | ||
56 | struct seq_file *m = (struct seq_file *)file->private_data; | ||
57 | m->private = inode->i_private; | ||
58 | } | ||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | static void *r_start(struct seq_file *m, loff_t *pos) | ||
63 | { | ||
64 | struct rcu_state *rsp = (struct rcu_state *)m->private; | ||
65 | *pos = cpumask_next(*pos - 1, cpu_possible_mask); | ||
66 | if ((*pos) < nr_cpu_ids) | ||
67 | return per_cpu_ptr(rsp->rda, *pos); | ||
68 | return NULL; | ||
69 | } | ||
52 | 70 | ||
53 | for_each_rcu_flavor(rsp) | 71 | static void *r_next(struct seq_file *m, void *v, loff_t *pos) |
54 | seq_printf(m, "%s: bcc: %d nbd: %lu\n", | 72 | { |
55 | rsp->name, | 73 | (*pos)++; |
56 | atomic_read(&rsp->barrier_cpu_count), | 74 | return r_start(m, pos); |
57 | rsp->n_barrier_done); | 75 | } |
76 | |||
77 | static void r_stop(struct seq_file *m, void *v) | ||
78 | { | ||
79 | } | ||
80 | |||
81 | static int show_rcubarrier(struct seq_file *m, void *v) | ||
82 | { | ||
83 | struct rcu_state *rsp = (struct rcu_state *)m->private; | ||
84 | seq_printf(m, "bcc: %d nbd: %lu\n", | ||
85 | atomic_read(&rsp->barrier_cpu_count), | ||
86 | rsp->n_barrier_done); | ||
58 | return 0; | 87 | return 0; |
59 | } | 88 | } |
60 | 89 | ||
61 | static int rcubarrier_open(struct inode *inode, struct file *file) | 90 | static int rcubarrier_open(struct inode *inode, struct file *file) |
62 | { | 91 | { |
63 | return single_open(file, show_rcubarrier, NULL); | 92 | return single_open(file, show_rcubarrier, inode->i_private); |
64 | } | 93 | } |
65 | 94 | ||
66 | static const struct file_operations rcubarrier_fops = { | 95 | static const struct file_operations rcubarrier_fops = { |
67 | .owner = THIS_MODULE, | 96 | .owner = THIS_MODULE, |
68 | .open = rcubarrier_open, | 97 | .open = rcubarrier_open, |
69 | .read = seq_read, | 98 | .read = seq_read, |
70 | .llseek = seq_lseek, | 99 | .llseek = no_llseek, |
71 | .release = single_release, | 100 | .release = seq_release, |
72 | }; | 101 | }; |
73 | 102 | ||
74 | #ifdef CONFIG_RCU_BOOST | 103 | #ifdef CONFIG_RCU_BOOST |
@@ -84,12 +113,14 @@ static char convert_kthread_status(unsigned int kthread_status) | |||
84 | 113 | ||
85 | static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) | 114 | static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) |
86 | { | 115 | { |
116 | long ql, qll; | ||
117 | |||
87 | if (!rdp->beenonline) | 118 | if (!rdp->beenonline) |
88 | return; | 119 | return; |
89 | seq_printf(m, "%3d%cc=%lu g=%lu pq=%d qp=%d", | 120 | seq_printf(m, "%3d%cc=%ld g=%ld pq=%d qp=%d", |
90 | rdp->cpu, | 121 | rdp->cpu, |
91 | cpu_is_offline(rdp->cpu) ? '!' : ' ', | 122 | cpu_is_offline(rdp->cpu) ? '!' : ' ', |
92 | rdp->completed, rdp->gpnum, | 123 | ulong2long(rdp->completed), ulong2long(rdp->gpnum), |
93 | rdp->passed_quiesce, rdp->qs_pending); | 124 | rdp->passed_quiesce, rdp->qs_pending); |
94 | seq_printf(m, " dt=%d/%llx/%d df=%lu", | 125 | seq_printf(m, " dt=%d/%llx/%d df=%lu", |
95 | atomic_read(&rdp->dynticks->dynticks), | 126 | atomic_read(&rdp->dynticks->dynticks), |
@@ -97,8 +128,11 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) | |||
97 | rdp->dynticks->dynticks_nmi_nesting, | 128 | rdp->dynticks->dynticks_nmi_nesting, |
98 | rdp->dynticks_fqs); | 129 | rdp->dynticks_fqs); |
99 | seq_printf(m, " of=%lu", rdp->offline_fqs); | 130 | seq_printf(m, " of=%lu", rdp->offline_fqs); |
131 | rcu_nocb_q_lengths(rdp, &ql, &qll); | ||
132 | qll += rdp->qlen_lazy; | ||
133 | ql += rdp->qlen; | ||
100 | seq_printf(m, " ql=%ld/%ld qs=%c%c%c%c", | 134 | seq_printf(m, " ql=%ld/%ld qs=%c%c%c%c", |
101 | rdp->qlen_lazy, rdp->qlen, | 135 | qll, ql, |
102 | ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] != | 136 | ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] != |
103 | rdp->nxttail[RCU_NEXT_TAIL]], | 137 | rdp->nxttail[RCU_NEXT_TAIL]], |
104 | ".R"[rdp->nxttail[RCU_WAIT_TAIL] != | 138 | ".R"[rdp->nxttail[RCU_WAIT_TAIL] != |
@@ -114,101 +148,67 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) | |||
114 | per_cpu(rcu_cpu_kthread_loops, rdp->cpu) & 0xffff); | 148 | per_cpu(rcu_cpu_kthread_loops, rdp->cpu) & 0xffff); |
115 | #endif /* #ifdef CONFIG_RCU_BOOST */ | 149 | #endif /* #ifdef CONFIG_RCU_BOOST */ |
116 | seq_printf(m, " b=%ld", rdp->blimit); | 150 | seq_printf(m, " b=%ld", rdp->blimit); |
117 | seq_printf(m, " ci=%lu co=%lu ca=%lu\n", | 151 | seq_printf(m, " ci=%lu nci=%lu co=%lu ca=%lu\n", |
118 | rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted); | 152 | rdp->n_cbs_invoked, rdp->n_nocbs_invoked, |
153 | rdp->n_cbs_orphaned, rdp->n_cbs_adopted); | ||
119 | } | 154 | } |
120 | 155 | ||
121 | static int show_rcudata(struct seq_file *m, void *unused) | 156 | static int show_rcudata(struct seq_file *m, void *v) |
122 | { | 157 | { |
123 | int cpu; | 158 | print_one_rcu_data(m, (struct rcu_data *)v); |
124 | struct rcu_state *rsp; | ||
125 | |||
126 | for_each_rcu_flavor(rsp) { | ||
127 | seq_printf(m, "%s:\n", rsp->name); | ||
128 | for_each_possible_cpu(cpu) | ||
129 | print_one_rcu_data(m, per_cpu_ptr(rsp->rda, cpu)); | ||
130 | } | ||
131 | return 0; | 159 | return 0; |
132 | } | 160 | } |
133 | 161 | ||
162 | static const struct seq_operations rcudate_op = { | ||
163 | .start = r_start, | ||
164 | .next = r_next, | ||
165 | .stop = r_stop, | ||
166 | .show = show_rcudata, | ||
167 | }; | ||
168 | |||
134 | static int rcudata_open(struct inode *inode, struct file *file) | 169 | static int rcudata_open(struct inode *inode, struct file *file) |
135 | { | 170 | { |
136 | return single_open(file, show_rcudata, NULL); | 171 | return r_open(inode, file, &rcudate_op); |
137 | } | 172 | } |
138 | 173 | ||
139 | static const struct file_operations rcudata_fops = { | 174 | static const struct file_operations rcudata_fops = { |
140 | .owner = THIS_MODULE, | 175 | .owner = THIS_MODULE, |
141 | .open = rcudata_open, | 176 | .open = rcudata_open, |
142 | .read = seq_read, | 177 | .read = seq_read, |
143 | .llseek = seq_lseek, | 178 | .llseek = no_llseek, |
144 | .release = single_release, | 179 | .release = seq_release, |
145 | }; | 180 | }; |
146 | 181 | ||
147 | static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp) | 182 | static int show_rcuexp(struct seq_file *m, void *v) |
148 | { | ||
149 | if (!rdp->beenonline) | ||
150 | return; | ||
151 | seq_printf(m, "%d,%s,%lu,%lu,%d,%d", | ||
152 | rdp->cpu, | ||
153 | cpu_is_offline(rdp->cpu) ? "\"N\"" : "\"Y\"", | ||
154 | rdp->completed, rdp->gpnum, | ||
155 | rdp->passed_quiesce, rdp->qs_pending); | ||
156 | seq_printf(m, ",%d,%llx,%d,%lu", | ||
157 | atomic_read(&rdp->dynticks->dynticks), | ||
158 | rdp->dynticks->dynticks_nesting, | ||
159 | rdp->dynticks->dynticks_nmi_nesting, | ||
160 | rdp->dynticks_fqs); | ||
161 | seq_printf(m, ",%lu", rdp->offline_fqs); | ||
162 | seq_printf(m, ",%ld,%ld,\"%c%c%c%c\"", rdp->qlen_lazy, rdp->qlen, | ||
163 | ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] != | ||
164 | rdp->nxttail[RCU_NEXT_TAIL]], | ||
165 | ".R"[rdp->nxttail[RCU_WAIT_TAIL] != | ||
166 | rdp->nxttail[RCU_NEXT_READY_TAIL]], | ||
167 | ".W"[rdp->nxttail[RCU_DONE_TAIL] != | ||
168 | rdp->nxttail[RCU_WAIT_TAIL]], | ||
169 | ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]]); | ||
170 | #ifdef CONFIG_RCU_BOOST | ||
171 | seq_printf(m, ",%d,\"%c\"", | ||
172 | per_cpu(rcu_cpu_has_work, rdp->cpu), | ||
173 | convert_kthread_status(per_cpu(rcu_cpu_kthread_status, | ||
174 | rdp->cpu))); | ||
175 | #endif /* #ifdef CONFIG_RCU_BOOST */ | ||
176 | seq_printf(m, ",%ld", rdp->blimit); | ||
177 | seq_printf(m, ",%lu,%lu,%lu\n", | ||
178 | rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted); | ||
179 | } | ||
180 | |||
181 | static int show_rcudata_csv(struct seq_file *m, void *unused) | ||
182 | { | 183 | { |
183 | int cpu; | 184 | struct rcu_state *rsp = (struct rcu_state *)m->private; |
184 | struct rcu_state *rsp; | 185 | |
185 | 186 | seq_printf(m, "s=%lu d=%lu w=%lu tf=%lu wd1=%lu wd2=%lu n=%lu sc=%lu dt=%lu dl=%lu dx=%lu\n", | |
186 | seq_puts(m, "\"CPU\",\"Online?\",\"c\",\"g\",\"pq\",\"pq\","); | 187 | atomic_long_read(&rsp->expedited_start), |
187 | seq_puts(m, "\"dt\",\"dt nesting\",\"dt NMI nesting\",\"df\","); | 188 | atomic_long_read(&rsp->expedited_done), |
188 | seq_puts(m, "\"of\",\"qll\",\"ql\",\"qs\""); | 189 | atomic_long_read(&rsp->expedited_wrap), |
189 | #ifdef CONFIG_RCU_BOOST | 190 | atomic_long_read(&rsp->expedited_tryfail), |
190 | seq_puts(m, "\"kt\",\"ktl\""); | 191 | atomic_long_read(&rsp->expedited_workdone1), |
191 | #endif /* #ifdef CONFIG_RCU_BOOST */ | 192 | atomic_long_read(&rsp->expedited_workdone2), |
192 | seq_puts(m, ",\"b\",\"ci\",\"co\",\"ca\"\n"); | 193 | atomic_long_read(&rsp->expedited_normal), |
193 | for_each_rcu_flavor(rsp) { | 194 | atomic_long_read(&rsp->expedited_stoppedcpus), |
194 | seq_printf(m, "\"%s:\"\n", rsp->name); | 195 | atomic_long_read(&rsp->expedited_done_tries), |
195 | for_each_possible_cpu(cpu) | 196 | atomic_long_read(&rsp->expedited_done_lost), |
196 | print_one_rcu_data_csv(m, per_cpu_ptr(rsp->rda, cpu)); | 197 | atomic_long_read(&rsp->expedited_done_exit)); |
197 | } | ||
198 | return 0; | 198 | return 0; |
199 | } | 199 | } |
200 | 200 | ||
201 | static int rcudata_csv_open(struct inode *inode, struct file *file) | 201 | static int rcuexp_open(struct inode *inode, struct file *file) |
202 | { | 202 | { |
203 | return single_open(file, show_rcudata_csv, NULL); | 203 | return single_open(file, show_rcuexp, inode->i_private); |
204 | } | 204 | } |
205 | 205 | ||
206 | static const struct file_operations rcudata_csv_fops = { | 206 | static const struct file_operations rcuexp_fops = { |
207 | .owner = THIS_MODULE, | 207 | .owner = THIS_MODULE, |
208 | .open = rcudata_csv_open, | 208 | .open = rcuexp_open, |
209 | .read = seq_read, | 209 | .read = seq_read, |
210 | .llseek = seq_lseek, | 210 | .llseek = no_llseek, |
211 | .release = single_release, | 211 | .release = seq_release, |
212 | }; | 212 | }; |
213 | 213 | ||
214 | #ifdef CONFIG_RCU_BOOST | 214 | #ifdef CONFIG_RCU_BOOST |
@@ -254,27 +254,11 @@ static const struct file_operations rcu_node_boost_fops = { | |||
254 | .owner = THIS_MODULE, | 254 | .owner = THIS_MODULE, |
255 | .open = rcu_node_boost_open, | 255 | .open = rcu_node_boost_open, |
256 | .read = seq_read, | 256 | .read = seq_read, |
257 | .llseek = seq_lseek, | 257 | .llseek = no_llseek, |
258 | .release = single_release, | 258 | .release = single_release, |
259 | }; | 259 | }; |
260 | 260 | ||
261 | /* | 261 | #endif /* #ifdef CONFIG_RCU_BOOST */ |
262 | * Create the rcuboost debugfs entry. Standard error return. | ||
263 | */ | ||
264 | static int rcu_boost_trace_create_file(struct dentry *rcudir) | ||
265 | { | ||
266 | return !debugfs_create_file("rcuboost", 0444, rcudir, NULL, | ||
267 | &rcu_node_boost_fops); | ||
268 | } | ||
269 | |||
270 | #else /* #ifdef CONFIG_RCU_BOOST */ | ||
271 | |||
272 | static int rcu_boost_trace_create_file(struct dentry *rcudir) | ||
273 | { | ||
274 | return 0; /* There cannot be an error if we didn't create it! */ | ||
275 | } | ||
276 | |||
277 | #endif /* #else #ifdef CONFIG_RCU_BOOST */ | ||
278 | 262 | ||
279 | static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp) | 263 | static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp) |
280 | { | 264 | { |
@@ -283,8 +267,9 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp) | |||
283 | struct rcu_node *rnp; | 267 | struct rcu_node *rnp; |
284 | 268 | ||
285 | gpnum = rsp->gpnum; | 269 | gpnum = rsp->gpnum; |
286 | seq_printf(m, "%s: c=%lu g=%lu s=%d jfq=%ld j=%x ", | 270 | seq_printf(m, "c=%ld g=%ld s=%d jfq=%ld j=%x ", |
287 | rsp->name, rsp->completed, gpnum, rsp->fqs_state, | 271 | ulong2long(rsp->completed), ulong2long(gpnum), |
272 | rsp->fqs_state, | ||
288 | (long)(rsp->jiffies_force_qs - jiffies), | 273 | (long)(rsp->jiffies_force_qs - jiffies), |
289 | (int)(jiffies & 0xffff)); | 274 | (int)(jiffies & 0xffff)); |
290 | seq_printf(m, "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n", | 275 | seq_printf(m, "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n", |
@@ -306,26 +291,24 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp) | |||
306 | seq_puts(m, "\n"); | 291 | seq_puts(m, "\n"); |
307 | } | 292 | } |
308 | 293 | ||
309 | static int show_rcuhier(struct seq_file *m, void *unused) | 294 | static int show_rcuhier(struct seq_file *m, void *v) |
310 | { | 295 | { |
311 | struct rcu_state *rsp; | 296 | struct rcu_state *rsp = (struct rcu_state *)m->private; |
312 | 297 | print_one_rcu_state(m, rsp); | |
313 | for_each_rcu_flavor(rsp) | ||
314 | print_one_rcu_state(m, rsp); | ||
315 | return 0; | 298 | return 0; |
316 | } | 299 | } |
317 | 300 | ||
318 | static int rcuhier_open(struct inode *inode, struct file *file) | 301 | static int rcuhier_open(struct inode *inode, struct file *file) |
319 | { | 302 | { |
320 | return single_open(file, show_rcuhier, NULL); | 303 | return single_open(file, show_rcuhier, inode->i_private); |
321 | } | 304 | } |
322 | 305 | ||
323 | static const struct file_operations rcuhier_fops = { | 306 | static const struct file_operations rcuhier_fops = { |
324 | .owner = THIS_MODULE, | 307 | .owner = THIS_MODULE, |
325 | .open = rcuhier_open, | 308 | .open = rcuhier_open, |
326 | .read = seq_read, | 309 | .read = seq_read, |
327 | .llseek = seq_lseek, | 310 | .llseek = no_llseek, |
328 | .release = single_release, | 311 | .release = seq_release, |
329 | }; | 312 | }; |
330 | 313 | ||
331 | static void show_one_rcugp(struct seq_file *m, struct rcu_state *rsp) | 314 | static void show_one_rcugp(struct seq_file *m, struct rcu_state *rsp) |
@@ -338,42 +321,42 @@ static void show_one_rcugp(struct seq_file *m, struct rcu_state *rsp) | |||
338 | struct rcu_node *rnp = &rsp->node[0]; | 321 | struct rcu_node *rnp = &rsp->node[0]; |
339 | 322 | ||
340 | raw_spin_lock_irqsave(&rnp->lock, flags); | 323 | raw_spin_lock_irqsave(&rnp->lock, flags); |
341 | completed = rsp->completed; | 324 | completed = ACCESS_ONCE(rsp->completed); |
342 | gpnum = rsp->gpnum; | 325 | gpnum = ACCESS_ONCE(rsp->gpnum); |
343 | if (rsp->completed == rsp->gpnum) | 326 | if (completed == gpnum) |
344 | gpage = 0; | 327 | gpage = 0; |
345 | else | 328 | else |
346 | gpage = jiffies - rsp->gp_start; | 329 | gpage = jiffies - rsp->gp_start; |
347 | gpmax = rsp->gp_max; | 330 | gpmax = rsp->gp_max; |
348 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 331 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
349 | seq_printf(m, "%s: completed=%ld gpnum=%lu age=%ld max=%ld\n", | 332 | seq_printf(m, "completed=%ld gpnum=%ld age=%ld max=%ld\n", |
350 | rsp->name, completed, gpnum, gpage, gpmax); | 333 | ulong2long(completed), ulong2long(gpnum), gpage, gpmax); |
351 | } | 334 | } |
352 | 335 | ||
353 | static int show_rcugp(struct seq_file *m, void *unused) | 336 | static int show_rcugp(struct seq_file *m, void *v) |
354 | { | 337 | { |
355 | struct rcu_state *rsp; | 338 | struct rcu_state *rsp = (struct rcu_state *)m->private; |
356 | 339 | show_one_rcugp(m, rsp); | |
357 | for_each_rcu_flavor(rsp) | ||
358 | show_one_rcugp(m, rsp); | ||
359 | return 0; | 340 | return 0; |
360 | } | 341 | } |
361 | 342 | ||
362 | static int rcugp_open(struct inode *inode, struct file *file) | 343 | static int rcugp_open(struct inode *inode, struct file *file) |
363 | { | 344 | { |
364 | return single_open(file, show_rcugp, NULL); | 345 | return single_open(file, show_rcugp, inode->i_private); |
365 | } | 346 | } |
366 | 347 | ||
367 | static const struct file_operations rcugp_fops = { | 348 | static const struct file_operations rcugp_fops = { |
368 | .owner = THIS_MODULE, | 349 | .owner = THIS_MODULE, |
369 | .open = rcugp_open, | 350 | .open = rcugp_open, |
370 | .read = seq_read, | 351 | .read = seq_read, |
371 | .llseek = seq_lseek, | 352 | .llseek = no_llseek, |
372 | .release = single_release, | 353 | .release = seq_release, |
373 | }; | 354 | }; |
374 | 355 | ||
375 | static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp) | 356 | static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp) |
376 | { | 357 | { |
358 | if (!rdp->beenonline) | ||
359 | return; | ||
377 | seq_printf(m, "%3d%cnp=%ld ", | 360 | seq_printf(m, "%3d%cnp=%ld ", |
378 | rdp->cpu, | 361 | rdp->cpu, |
379 | cpu_is_offline(rdp->cpu) ? '!' : ' ', | 362 | cpu_is_offline(rdp->cpu) ? '!' : ' ', |
@@ -389,34 +372,30 @@ static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp) | |||
389 | rdp->n_rp_need_nothing); | 372 | rdp->n_rp_need_nothing); |
390 | } | 373 | } |
391 | 374 | ||
392 | static int show_rcu_pending(struct seq_file *m, void *unused) | 375 | static int show_rcu_pending(struct seq_file *m, void *v) |
393 | { | 376 | { |
394 | int cpu; | 377 | print_one_rcu_pending(m, (struct rcu_data *)v); |
395 | struct rcu_data *rdp; | ||
396 | struct rcu_state *rsp; | ||
397 | |||
398 | for_each_rcu_flavor(rsp) { | ||
399 | seq_printf(m, "%s:\n", rsp->name); | ||
400 | for_each_possible_cpu(cpu) { | ||
401 | rdp = per_cpu_ptr(rsp->rda, cpu); | ||
402 | if (rdp->beenonline) | ||
403 | print_one_rcu_pending(m, rdp); | ||
404 | } | ||
405 | } | ||
406 | return 0; | 378 | return 0; |
407 | } | 379 | } |
408 | 380 | ||
381 | static const struct seq_operations rcu_pending_op = { | ||
382 | .start = r_start, | ||
383 | .next = r_next, | ||
384 | .stop = r_stop, | ||
385 | .show = show_rcu_pending, | ||
386 | }; | ||
387 | |||
409 | static int rcu_pending_open(struct inode *inode, struct file *file) | 388 | static int rcu_pending_open(struct inode *inode, struct file *file) |
410 | { | 389 | { |
411 | return single_open(file, show_rcu_pending, NULL); | 390 | return r_open(inode, file, &rcu_pending_op); |
412 | } | 391 | } |
413 | 392 | ||
414 | static const struct file_operations rcu_pending_fops = { | 393 | static const struct file_operations rcu_pending_fops = { |
415 | .owner = THIS_MODULE, | 394 | .owner = THIS_MODULE, |
416 | .open = rcu_pending_open, | 395 | .open = rcu_pending_open, |
417 | .read = seq_read, | 396 | .read = seq_read, |
418 | .llseek = seq_lseek, | 397 | .llseek = no_llseek, |
419 | .release = single_release, | 398 | .release = seq_release, |
420 | }; | 399 | }; |
421 | 400 | ||
422 | static int show_rcutorture(struct seq_file *m, void *unused) | 401 | static int show_rcutorture(struct seq_file *m, void *unused) |
@@ -446,43 +425,58 @@ static struct dentry *rcudir; | |||
446 | 425 | ||
447 | static int __init rcutree_trace_init(void) | 426 | static int __init rcutree_trace_init(void) |
448 | { | 427 | { |
428 | struct rcu_state *rsp; | ||
449 | struct dentry *retval; | 429 | struct dentry *retval; |
430 | struct dentry *rspdir; | ||
450 | 431 | ||
451 | rcudir = debugfs_create_dir("rcu", NULL); | 432 | rcudir = debugfs_create_dir("rcu", NULL); |
452 | if (!rcudir) | 433 | if (!rcudir) |
453 | goto free_out; | 434 | goto free_out; |
454 | 435 | ||
455 | retval = debugfs_create_file("rcubarrier", 0444, rcudir, | 436 | for_each_rcu_flavor(rsp) { |
456 | NULL, &rcubarrier_fops); | 437 | rspdir = debugfs_create_dir(rsp->name, rcudir); |
457 | if (!retval) | 438 | if (!rspdir) |
458 | goto free_out; | 439 | goto free_out; |
459 | 440 | ||
460 | retval = debugfs_create_file("rcudata", 0444, rcudir, | 441 | retval = debugfs_create_file("rcudata", 0444, |
461 | NULL, &rcudata_fops); | 442 | rspdir, rsp, &rcudata_fops); |
462 | if (!retval) | 443 | if (!retval) |
463 | goto free_out; | 444 | goto free_out; |
464 | 445 | ||
465 | retval = debugfs_create_file("rcudata.csv", 0444, rcudir, | 446 | retval = debugfs_create_file("rcuexp", 0444, |
466 | NULL, &rcudata_csv_fops); | 447 | rspdir, rsp, &rcuexp_fops); |
467 | if (!retval) | 448 | if (!retval) |
468 | goto free_out; | 449 | goto free_out; |
469 | 450 | ||
470 | if (rcu_boost_trace_create_file(rcudir)) | 451 | retval = debugfs_create_file("rcu_pending", 0444, |
471 | goto free_out; | 452 | rspdir, rsp, &rcu_pending_fops); |
453 | if (!retval) | ||
454 | goto free_out; | ||
455 | |||
456 | retval = debugfs_create_file("rcubarrier", 0444, | ||
457 | rspdir, rsp, &rcubarrier_fops); | ||
458 | if (!retval) | ||
459 | goto free_out; | ||
472 | 460 | ||
473 | retval = debugfs_create_file("rcugp", 0444, rcudir, NULL, &rcugp_fops); | 461 | #ifdef CONFIG_RCU_BOOST |
474 | if (!retval) | 462 | if (rsp == &rcu_preempt_state) { |
475 | goto free_out; | 463 | retval = debugfs_create_file("rcuboost", 0444, |
464 | rspdir, NULL, &rcu_node_boost_fops); | ||
465 | if (!retval) | ||
466 | goto free_out; | ||
467 | } | ||
468 | #endif | ||
476 | 469 | ||
477 | retval = debugfs_create_file("rcuhier", 0444, rcudir, | 470 | retval = debugfs_create_file("rcugp", 0444, |
478 | NULL, &rcuhier_fops); | 471 | rspdir, rsp, &rcugp_fops); |
479 | if (!retval) | 472 | if (!retval) |
480 | goto free_out; | 473 | goto free_out; |
481 | 474 | ||
482 | retval = debugfs_create_file("rcu_pending", 0444, rcudir, | 475 | retval = debugfs_create_file("rcuhier", 0444, |
483 | NULL, &rcu_pending_fops); | 476 | rspdir, rsp, &rcuhier_fops); |
484 | if (!retval) | 477 | if (!retval) |
485 | goto free_out; | 478 | goto free_out; |
479 | } | ||
486 | 480 | ||
487 | retval = debugfs_create_file("rcutorture", 0444, rcudir, | 481 | retval = debugfs_create_file("rcutorture", 0444, rcudir, |
488 | NULL, &rcutorture_fops); | 482 | NULL, &rcutorture_fops); |