diff options
Diffstat (limited to 'net/rxrpc/proc.c')
-rw-r--r-- | net/rxrpc/proc.c | 617 |
1 files changed, 617 insertions, 0 deletions
diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c new file mode 100644 index 000000000000..3b5ecd8e2401 --- /dev/null +++ b/net/rxrpc/proc.c | |||
@@ -0,0 +1,617 @@ | |||
1 | /* proc.c: /proc interface for RxRPC | ||
2 | * | ||
3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/sched.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/proc_fs.h> | ||
16 | #include <linux/seq_file.h> | ||
17 | #include <rxrpc/rxrpc.h> | ||
18 | #include <rxrpc/transport.h> | ||
19 | #include <rxrpc/peer.h> | ||
20 | #include <rxrpc/connection.h> | ||
21 | #include <rxrpc/call.h> | ||
22 | #include <rxrpc/message.h> | ||
23 | #include "internal.h" | ||
24 | |||
25 | static struct proc_dir_entry *proc_rxrpc; | ||
26 | |||
27 | static int rxrpc_proc_transports_open(struct inode *inode, struct file *file); | ||
28 | static void *rxrpc_proc_transports_start(struct seq_file *p, loff_t *pos); | ||
29 | static void *rxrpc_proc_transports_next(struct seq_file *p, void *v, loff_t *pos); | ||
30 | static void rxrpc_proc_transports_stop(struct seq_file *p, void *v); | ||
31 | static int rxrpc_proc_transports_show(struct seq_file *m, void *v); | ||
32 | |||
33 | static struct seq_operations rxrpc_proc_transports_ops = { | ||
34 | .start = rxrpc_proc_transports_start, | ||
35 | .next = rxrpc_proc_transports_next, | ||
36 | .stop = rxrpc_proc_transports_stop, | ||
37 | .show = rxrpc_proc_transports_show, | ||
38 | }; | ||
39 | |||
40 | static struct file_operations rxrpc_proc_transports_fops = { | ||
41 | .open = rxrpc_proc_transports_open, | ||
42 | .read = seq_read, | ||
43 | .llseek = seq_lseek, | ||
44 | .release = seq_release, | ||
45 | }; | ||
46 | |||
47 | static int rxrpc_proc_peers_open(struct inode *inode, struct file *file); | ||
48 | static void *rxrpc_proc_peers_start(struct seq_file *p, loff_t *pos); | ||
49 | static void *rxrpc_proc_peers_next(struct seq_file *p, void *v, loff_t *pos); | ||
50 | static void rxrpc_proc_peers_stop(struct seq_file *p, void *v); | ||
51 | static int rxrpc_proc_peers_show(struct seq_file *m, void *v); | ||
52 | |||
53 | static struct seq_operations rxrpc_proc_peers_ops = { | ||
54 | .start = rxrpc_proc_peers_start, | ||
55 | .next = rxrpc_proc_peers_next, | ||
56 | .stop = rxrpc_proc_peers_stop, | ||
57 | .show = rxrpc_proc_peers_show, | ||
58 | }; | ||
59 | |||
60 | static struct file_operations rxrpc_proc_peers_fops = { | ||
61 | .open = rxrpc_proc_peers_open, | ||
62 | .read = seq_read, | ||
63 | .llseek = seq_lseek, | ||
64 | .release = seq_release, | ||
65 | }; | ||
66 | |||
67 | static int rxrpc_proc_conns_open(struct inode *inode, struct file *file); | ||
68 | static void *rxrpc_proc_conns_start(struct seq_file *p, loff_t *pos); | ||
69 | static void *rxrpc_proc_conns_next(struct seq_file *p, void *v, loff_t *pos); | ||
70 | static void rxrpc_proc_conns_stop(struct seq_file *p, void *v); | ||
71 | static int rxrpc_proc_conns_show(struct seq_file *m, void *v); | ||
72 | |||
73 | static struct seq_operations rxrpc_proc_conns_ops = { | ||
74 | .start = rxrpc_proc_conns_start, | ||
75 | .next = rxrpc_proc_conns_next, | ||
76 | .stop = rxrpc_proc_conns_stop, | ||
77 | .show = rxrpc_proc_conns_show, | ||
78 | }; | ||
79 | |||
80 | static struct file_operations rxrpc_proc_conns_fops = { | ||
81 | .open = rxrpc_proc_conns_open, | ||
82 | .read = seq_read, | ||
83 | .llseek = seq_lseek, | ||
84 | .release = seq_release, | ||
85 | }; | ||
86 | |||
87 | static int rxrpc_proc_calls_open(struct inode *inode, struct file *file); | ||
88 | static void *rxrpc_proc_calls_start(struct seq_file *p, loff_t *pos); | ||
89 | static void *rxrpc_proc_calls_next(struct seq_file *p, void *v, loff_t *pos); | ||
90 | static void rxrpc_proc_calls_stop(struct seq_file *p, void *v); | ||
91 | static int rxrpc_proc_calls_show(struct seq_file *m, void *v); | ||
92 | |||
93 | static struct seq_operations rxrpc_proc_calls_ops = { | ||
94 | .start = rxrpc_proc_calls_start, | ||
95 | .next = rxrpc_proc_calls_next, | ||
96 | .stop = rxrpc_proc_calls_stop, | ||
97 | .show = rxrpc_proc_calls_show, | ||
98 | }; | ||
99 | |||
100 | static struct file_operations rxrpc_proc_calls_fops = { | ||
101 | .open = rxrpc_proc_calls_open, | ||
102 | .read = seq_read, | ||
103 | .llseek = seq_lseek, | ||
104 | .release = seq_release, | ||
105 | }; | ||
106 | |||
107 | static const char *rxrpc_call_states7[] = { | ||
108 | "complet", | ||
109 | "error ", | ||
110 | "rcv_op ", | ||
111 | "rcv_arg", | ||
112 | "got_arg", | ||
113 | "snd_rpl", | ||
114 | "fin_ack", | ||
115 | "snd_arg", | ||
116 | "rcv_rpl", | ||
117 | "got_rpl" | ||
118 | }; | ||
119 | |||
120 | static const char *rxrpc_call_error_states7[] = { | ||
121 | "no_err ", | ||
122 | "loc_abt", | ||
123 | "rmt_abt", | ||
124 | "loc_err", | ||
125 | "rmt_err" | ||
126 | }; | ||
127 | |||
128 | /*****************************************************************************/ | ||
129 | /* | ||
130 | * initialise the /proc/net/rxrpc/ directory | ||
131 | */ | ||
132 | int rxrpc_proc_init(void) | ||
133 | { | ||
134 | struct proc_dir_entry *p; | ||
135 | |||
136 | proc_rxrpc = proc_mkdir("rxrpc", proc_net); | ||
137 | if (!proc_rxrpc) | ||
138 | goto error; | ||
139 | proc_rxrpc->owner = THIS_MODULE; | ||
140 | |||
141 | p = create_proc_entry("calls", 0, proc_rxrpc); | ||
142 | if (!p) | ||
143 | goto error_proc; | ||
144 | p->proc_fops = &rxrpc_proc_calls_fops; | ||
145 | p->owner = THIS_MODULE; | ||
146 | |||
147 | p = create_proc_entry("connections", 0, proc_rxrpc); | ||
148 | if (!p) | ||
149 | goto error_calls; | ||
150 | p->proc_fops = &rxrpc_proc_conns_fops; | ||
151 | p->owner = THIS_MODULE; | ||
152 | |||
153 | p = create_proc_entry("peers", 0, proc_rxrpc); | ||
154 | if (!p) | ||
155 | goto error_calls; | ||
156 | p->proc_fops = &rxrpc_proc_peers_fops; | ||
157 | p->owner = THIS_MODULE; | ||
158 | |||
159 | p = create_proc_entry("transports", 0, proc_rxrpc); | ||
160 | if (!p) | ||
161 | goto error_conns; | ||
162 | p->proc_fops = &rxrpc_proc_transports_fops; | ||
163 | p->owner = THIS_MODULE; | ||
164 | |||
165 | return 0; | ||
166 | |||
167 | error_conns: | ||
168 | remove_proc_entry("connections", proc_rxrpc); | ||
169 | error_calls: | ||
170 | remove_proc_entry("calls", proc_rxrpc); | ||
171 | error_proc: | ||
172 | remove_proc_entry("rxrpc", proc_net); | ||
173 | error: | ||
174 | return -ENOMEM; | ||
175 | } /* end rxrpc_proc_init() */ | ||
176 | |||
177 | /*****************************************************************************/ | ||
178 | /* | ||
179 | * clean up the /proc/net/rxrpc/ directory | ||
180 | */ | ||
181 | void rxrpc_proc_cleanup(void) | ||
182 | { | ||
183 | remove_proc_entry("transports", proc_rxrpc); | ||
184 | remove_proc_entry("peers", proc_rxrpc); | ||
185 | remove_proc_entry("connections", proc_rxrpc); | ||
186 | remove_proc_entry("calls", proc_rxrpc); | ||
187 | |||
188 | remove_proc_entry("rxrpc", proc_net); | ||
189 | |||
190 | } /* end rxrpc_proc_cleanup() */ | ||
191 | |||
192 | /*****************************************************************************/ | ||
193 | /* | ||
194 | * open "/proc/net/rxrpc/transports" which provides a summary of extant transports | ||
195 | */ | ||
196 | static int rxrpc_proc_transports_open(struct inode *inode, struct file *file) | ||
197 | { | ||
198 | struct seq_file *m; | ||
199 | int ret; | ||
200 | |||
201 | ret = seq_open(file, &rxrpc_proc_transports_ops); | ||
202 | if (ret < 0) | ||
203 | return ret; | ||
204 | |||
205 | m = file->private_data; | ||
206 | m->private = PDE(inode)->data; | ||
207 | |||
208 | return 0; | ||
209 | } /* end rxrpc_proc_transports_open() */ | ||
210 | |||
211 | /*****************************************************************************/ | ||
212 | /* | ||
213 | * set up the iterator to start reading from the transports list and return the first item | ||
214 | */ | ||
215 | static void *rxrpc_proc_transports_start(struct seq_file *m, loff_t *_pos) | ||
216 | { | ||
217 | struct list_head *_p; | ||
218 | loff_t pos = *_pos; | ||
219 | |||
220 | /* lock the list against modification */ | ||
221 | down_read(&rxrpc_proc_transports_sem); | ||
222 | |||
223 | /* allow for the header line */ | ||
224 | if (!pos) | ||
225 | return SEQ_START_TOKEN; | ||
226 | pos--; | ||
227 | |||
228 | /* find the n'th element in the list */ | ||
229 | list_for_each(_p, &rxrpc_proc_transports) | ||
230 | if (!pos--) | ||
231 | break; | ||
232 | |||
233 | return _p != &rxrpc_proc_transports ? _p : NULL; | ||
234 | } /* end rxrpc_proc_transports_start() */ | ||
235 | |||
236 | /*****************************************************************************/ | ||
237 | /* | ||
238 | * move to next call in transports list | ||
239 | */ | ||
240 | static void *rxrpc_proc_transports_next(struct seq_file *p, void *v, loff_t *pos) | ||
241 | { | ||
242 | struct list_head *_p; | ||
243 | |||
244 | (*pos)++; | ||
245 | |||
246 | _p = v; | ||
247 | _p = (v == SEQ_START_TOKEN) ? rxrpc_proc_transports.next : _p->next; | ||
248 | |||
249 | return _p != &rxrpc_proc_transports ? _p : NULL; | ||
250 | } /* end rxrpc_proc_transports_next() */ | ||
251 | |||
252 | /*****************************************************************************/ | ||
253 | /* | ||
254 | * clean up after reading from the transports list | ||
255 | */ | ||
256 | static void rxrpc_proc_transports_stop(struct seq_file *p, void *v) | ||
257 | { | ||
258 | up_read(&rxrpc_proc_transports_sem); | ||
259 | |||
260 | } /* end rxrpc_proc_transports_stop() */ | ||
261 | |||
262 | /*****************************************************************************/ | ||
263 | /* | ||
264 | * display a header line followed by a load of call lines | ||
265 | */ | ||
266 | static int rxrpc_proc_transports_show(struct seq_file *m, void *v) | ||
267 | { | ||
268 | struct rxrpc_transport *trans = | ||
269 | list_entry(v, struct rxrpc_transport, proc_link); | ||
270 | |||
271 | /* display header on line 1 */ | ||
272 | if (v == SEQ_START_TOKEN) { | ||
273 | seq_puts(m, "LOCAL USE\n"); | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | /* display one transport per line on subsequent lines */ | ||
278 | seq_printf(m, "%5hu %3d\n", | ||
279 | trans->port, | ||
280 | atomic_read(&trans->usage) | ||
281 | ); | ||
282 | |||
283 | return 0; | ||
284 | } /* end rxrpc_proc_transports_show() */ | ||
285 | |||
286 | /*****************************************************************************/ | ||
287 | /* | ||
288 | * open "/proc/net/rxrpc/peers" which provides a summary of extant peers | ||
289 | */ | ||
290 | static int rxrpc_proc_peers_open(struct inode *inode, struct file *file) | ||
291 | { | ||
292 | struct seq_file *m; | ||
293 | int ret; | ||
294 | |||
295 | ret = seq_open(file, &rxrpc_proc_peers_ops); | ||
296 | if (ret < 0) | ||
297 | return ret; | ||
298 | |||
299 | m = file->private_data; | ||
300 | m->private = PDE(inode)->data; | ||
301 | |||
302 | return 0; | ||
303 | } /* end rxrpc_proc_peers_open() */ | ||
304 | |||
305 | /*****************************************************************************/ | ||
306 | /* | ||
307 | * set up the iterator to start reading from the peers list and return the | ||
308 | * first item | ||
309 | */ | ||
310 | static void *rxrpc_proc_peers_start(struct seq_file *m, loff_t *_pos) | ||
311 | { | ||
312 | struct list_head *_p; | ||
313 | loff_t pos = *_pos; | ||
314 | |||
315 | /* lock the list against modification */ | ||
316 | down_read(&rxrpc_peers_sem); | ||
317 | |||
318 | /* allow for the header line */ | ||
319 | if (!pos) | ||
320 | return SEQ_START_TOKEN; | ||
321 | pos--; | ||
322 | |||
323 | /* find the n'th element in the list */ | ||
324 | list_for_each(_p, &rxrpc_peers) | ||
325 | if (!pos--) | ||
326 | break; | ||
327 | |||
328 | return _p != &rxrpc_peers ? _p : NULL; | ||
329 | } /* end rxrpc_proc_peers_start() */ | ||
330 | |||
331 | /*****************************************************************************/ | ||
332 | /* | ||
333 | * move to next conn in peers list | ||
334 | */ | ||
335 | static void *rxrpc_proc_peers_next(struct seq_file *p, void *v, loff_t *pos) | ||
336 | { | ||
337 | struct list_head *_p; | ||
338 | |||
339 | (*pos)++; | ||
340 | |||
341 | _p = v; | ||
342 | _p = (v == SEQ_START_TOKEN) ? rxrpc_peers.next : _p->next; | ||
343 | |||
344 | return _p != &rxrpc_peers ? _p : NULL; | ||
345 | } /* end rxrpc_proc_peers_next() */ | ||
346 | |||
347 | /*****************************************************************************/ | ||
348 | /* | ||
349 | * clean up after reading from the peers list | ||
350 | */ | ||
351 | static void rxrpc_proc_peers_stop(struct seq_file *p, void *v) | ||
352 | { | ||
353 | up_read(&rxrpc_peers_sem); | ||
354 | |||
355 | } /* end rxrpc_proc_peers_stop() */ | ||
356 | |||
357 | /*****************************************************************************/ | ||
358 | /* | ||
359 | * display a header line followed by a load of conn lines | ||
360 | */ | ||
361 | static int rxrpc_proc_peers_show(struct seq_file *m, void *v) | ||
362 | { | ||
363 | struct rxrpc_peer *peer = list_entry(v, struct rxrpc_peer, proc_link); | ||
364 | signed long timeout; | ||
365 | |||
366 | /* display header on line 1 */ | ||
367 | if (v == SEQ_START_TOKEN) { | ||
368 | seq_puts(m, "LOCAL REMOTE USAGE CONNS TIMEOUT" | ||
369 | " MTU RTT(uS)\n"); | ||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | /* display one peer per line on subsequent lines */ | ||
374 | timeout = 0; | ||
375 | if (!list_empty(&peer->timeout.link)) | ||
376 | timeout = (signed long) peer->timeout.timo_jif - | ||
377 | (signed long) jiffies; | ||
378 | |||
379 | seq_printf(m, "%5hu %08x %5d %5d %8ld %5Zu %7lu\n", | ||
380 | peer->trans->port, | ||
381 | ntohl(peer->addr.s_addr), | ||
382 | atomic_read(&peer->usage), | ||
383 | atomic_read(&peer->conn_count), | ||
384 | timeout, | ||
385 | peer->if_mtu, | ||
386 | (long) peer->rtt | ||
387 | ); | ||
388 | |||
389 | return 0; | ||
390 | } /* end rxrpc_proc_peers_show() */ | ||
391 | |||
392 | /*****************************************************************************/ | ||
393 | /* | ||
394 | * open "/proc/net/rxrpc/connections" which provides a summary of extant | ||
395 | * connections | ||
396 | */ | ||
397 | static int rxrpc_proc_conns_open(struct inode *inode, struct file *file) | ||
398 | { | ||
399 | struct seq_file *m; | ||
400 | int ret; | ||
401 | |||
402 | ret = seq_open(file, &rxrpc_proc_conns_ops); | ||
403 | if (ret < 0) | ||
404 | return ret; | ||
405 | |||
406 | m = file->private_data; | ||
407 | m->private = PDE(inode)->data; | ||
408 | |||
409 | return 0; | ||
410 | } /* end rxrpc_proc_conns_open() */ | ||
411 | |||
412 | /*****************************************************************************/ | ||
413 | /* | ||
414 | * set up the iterator to start reading from the conns list and return the | ||
415 | * first item | ||
416 | */ | ||
417 | static void *rxrpc_proc_conns_start(struct seq_file *m, loff_t *_pos) | ||
418 | { | ||
419 | struct list_head *_p; | ||
420 | loff_t pos = *_pos; | ||
421 | |||
422 | /* lock the list against modification */ | ||
423 | down_read(&rxrpc_conns_sem); | ||
424 | |||
425 | /* allow for the header line */ | ||
426 | if (!pos) | ||
427 | return SEQ_START_TOKEN; | ||
428 | pos--; | ||
429 | |||
430 | /* find the n'th element in the list */ | ||
431 | list_for_each(_p, &rxrpc_conns) | ||
432 | if (!pos--) | ||
433 | break; | ||
434 | |||
435 | return _p != &rxrpc_conns ? _p : NULL; | ||
436 | } /* end rxrpc_proc_conns_start() */ | ||
437 | |||
438 | /*****************************************************************************/ | ||
439 | /* | ||
440 | * move to next conn in conns list | ||
441 | */ | ||
442 | static void *rxrpc_proc_conns_next(struct seq_file *p, void *v, loff_t *pos) | ||
443 | { | ||
444 | struct list_head *_p; | ||
445 | |||
446 | (*pos)++; | ||
447 | |||
448 | _p = v; | ||
449 | _p = (v == SEQ_START_TOKEN) ? rxrpc_conns.next : _p->next; | ||
450 | |||
451 | return _p != &rxrpc_conns ? _p : NULL; | ||
452 | } /* end rxrpc_proc_conns_next() */ | ||
453 | |||
454 | /*****************************************************************************/ | ||
455 | /* | ||
456 | * clean up after reading from the conns list | ||
457 | */ | ||
458 | static void rxrpc_proc_conns_stop(struct seq_file *p, void *v) | ||
459 | { | ||
460 | up_read(&rxrpc_conns_sem); | ||
461 | |||
462 | } /* end rxrpc_proc_conns_stop() */ | ||
463 | |||
464 | /*****************************************************************************/ | ||
465 | /* | ||
466 | * display a header line followed by a load of conn lines | ||
467 | */ | ||
468 | static int rxrpc_proc_conns_show(struct seq_file *m, void *v) | ||
469 | { | ||
470 | struct rxrpc_connection *conn; | ||
471 | signed long timeout; | ||
472 | |||
473 | conn = list_entry(v, struct rxrpc_connection, proc_link); | ||
474 | |||
475 | /* display header on line 1 */ | ||
476 | if (v == SEQ_START_TOKEN) { | ||
477 | seq_puts(m, | ||
478 | "LOCAL REMOTE RPORT SRVC CONN END SERIALNO " | ||
479 | "CALLNO MTU TIMEOUT" | ||
480 | "\n"); | ||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | /* display one conn per line on subsequent lines */ | ||
485 | timeout = 0; | ||
486 | if (!list_empty(&conn->timeout.link)) | ||
487 | timeout = (signed long) conn->timeout.timo_jif - | ||
488 | (signed long) jiffies; | ||
489 | |||
490 | seq_printf(m, | ||
491 | "%5hu %08x %5hu %04hx %08x %-3.3s %08x %08x %5Zu %8ld\n", | ||
492 | conn->trans->port, | ||
493 | ntohl(conn->addr.sin_addr.s_addr), | ||
494 | ntohs(conn->addr.sin_port), | ||
495 | ntohs(conn->service_id), | ||
496 | ntohl(conn->conn_id), | ||
497 | conn->out_clientflag ? "CLT" : "SRV", | ||
498 | conn->serial_counter, | ||
499 | conn->call_counter, | ||
500 | conn->mtu_size, | ||
501 | timeout | ||
502 | ); | ||
503 | |||
504 | return 0; | ||
505 | } /* end rxrpc_proc_conns_show() */ | ||
506 | |||
507 | /*****************************************************************************/ | ||
508 | /* | ||
509 | * open "/proc/net/rxrpc/calls" which provides a summary of extant calls | ||
510 | */ | ||
511 | static int rxrpc_proc_calls_open(struct inode *inode, struct file *file) | ||
512 | { | ||
513 | struct seq_file *m; | ||
514 | int ret; | ||
515 | |||
516 | ret = seq_open(file, &rxrpc_proc_calls_ops); | ||
517 | if (ret < 0) | ||
518 | return ret; | ||
519 | |||
520 | m = file->private_data; | ||
521 | m->private = PDE(inode)->data; | ||
522 | |||
523 | return 0; | ||
524 | } /* end rxrpc_proc_calls_open() */ | ||
525 | |||
526 | /*****************************************************************************/ | ||
527 | /* | ||
528 | * set up the iterator to start reading from the calls list and return the | ||
529 | * first item | ||
530 | */ | ||
531 | static void *rxrpc_proc_calls_start(struct seq_file *m, loff_t *_pos) | ||
532 | { | ||
533 | struct list_head *_p; | ||
534 | loff_t pos = *_pos; | ||
535 | |||
536 | /* lock the list against modification */ | ||
537 | down_read(&rxrpc_calls_sem); | ||
538 | |||
539 | /* allow for the header line */ | ||
540 | if (!pos) | ||
541 | return SEQ_START_TOKEN; | ||
542 | pos--; | ||
543 | |||
544 | /* find the n'th element in the list */ | ||
545 | list_for_each(_p, &rxrpc_calls) | ||
546 | if (!pos--) | ||
547 | break; | ||
548 | |||
549 | return _p != &rxrpc_calls ? _p : NULL; | ||
550 | } /* end rxrpc_proc_calls_start() */ | ||
551 | |||
552 | /*****************************************************************************/ | ||
553 | /* | ||
554 | * move to next call in calls list | ||
555 | */ | ||
556 | static void *rxrpc_proc_calls_next(struct seq_file *p, void *v, loff_t *pos) | ||
557 | { | ||
558 | struct list_head *_p; | ||
559 | |||
560 | (*pos)++; | ||
561 | |||
562 | _p = v; | ||
563 | _p = (v == SEQ_START_TOKEN) ? rxrpc_calls.next : _p->next; | ||
564 | |||
565 | return _p != &rxrpc_calls ? _p : NULL; | ||
566 | } /* end rxrpc_proc_calls_next() */ | ||
567 | |||
568 | /*****************************************************************************/ | ||
569 | /* | ||
570 | * clean up after reading from the calls list | ||
571 | */ | ||
572 | static void rxrpc_proc_calls_stop(struct seq_file *p, void *v) | ||
573 | { | ||
574 | up_read(&rxrpc_calls_sem); | ||
575 | |||
576 | } /* end rxrpc_proc_calls_stop() */ | ||
577 | |||
578 | /*****************************************************************************/ | ||
579 | /* | ||
580 | * display a header line followed by a load of call lines | ||
581 | */ | ||
582 | static int rxrpc_proc_calls_show(struct seq_file *m, void *v) | ||
583 | { | ||
584 | struct rxrpc_call *call = list_entry(v, struct rxrpc_call, call_link); | ||
585 | |||
586 | /* display header on line 1 */ | ||
587 | if (v == SEQ_START_TOKEN) { | ||
588 | seq_puts(m, | ||
589 | "LOCAL REMOT SRVC CONN CALL DIR USE " | ||
590 | " L STATE OPCODE ABORT ERRNO\n" | ||
591 | ); | ||
592 | return 0; | ||
593 | } | ||
594 | |||
595 | /* display one call per line on subsequent lines */ | ||
596 | seq_printf(m, | ||
597 | "%5hu %5hu %04hx %08x %08x %s %3u%c" | ||
598 | " %c %-7.7s %6d %08x %5d\n", | ||
599 | call->conn->trans->port, | ||
600 | ntohs(call->conn->addr.sin_port), | ||
601 | ntohs(call->conn->service_id), | ||
602 | ntohl(call->conn->conn_id), | ||
603 | ntohl(call->call_id), | ||
604 | call->conn->service ? "SVC" : "CLT", | ||
605 | atomic_read(&call->usage), | ||
606 | waitqueue_active(&call->waitq) ? 'w' : ' ', | ||
607 | call->app_last_rcv ? 'Y' : '-', | ||
608 | (call->app_call_state!=RXRPC_CSTATE_ERROR ? | ||
609 | rxrpc_call_states7[call->app_call_state] : | ||
610 | rxrpc_call_error_states7[call->app_err_state]), | ||
611 | call->app_opcode, | ||
612 | call->app_abort_code, | ||
613 | call->app_errno | ||
614 | ); | ||
615 | |||
616 | return 0; | ||
617 | } /* end rxrpc_proc_calls_show() */ | ||