proc.c 16 KB

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