1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002 Cluster File Systems, Inc.
6 * This file is part of Portals
7 * http://sourceforge.net/projects/sandiaportals/
9 * Portals is free software; you can redistribute it and/or
10 * modify it under the terms of version 2 of the GNU General Public
11 * License as published by the Free Software Foundation.
13 * Portals is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Portals; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #define DEBUG_SUBSYSTEM S_LNET
25 #include <libcfs/libcfs.h>
26 #include <lnet/lib-lnet.h>
28 #if defined(__KERNEL__) && defined(LNET_ROUTER)
30 #include <linux/seq_file.h>
31 #include <linux/lustre_compat25.h>
33 /* this is really lnet_proc.c */
35 #define LNET_PROC_STATS "sys/lnet/stats"
36 #define LNET_PROC_ROUTES "sys/lnet/routes"
37 #define LNET_PROC_ROUTERS "sys/lnet/routers"
38 #define LNET_PROC_PEERS "sys/lnet/peers"
39 #define LNET_PROC_BUFFERS "sys/lnet/buffers"
40 #define LNET_PROC_NIS "sys/lnet/nis"
43 lnet_router_proc_stats_read (char *page, char **start, off_t off,
44 int count, int *eof, void *data)
46 lnet_counters_t *ctrs;
54 LIBCFS_ALLOC(ctrs, sizeof(*ctrs));
59 *ctrs = the_lnet.ln_counters;
63 "%u %u %u %u %u %u %u "LPU64" "LPU64" "LPU64" "LPU64"\n",
64 ctrs->msgs_alloc, ctrs->msgs_max,
66 ctrs->send_count, ctrs->recv_count,
67 ctrs->route_count, ctrs->drop_count,
68 ctrs->send_length, ctrs->recv_length,
69 ctrs->route_length, ctrs->drop_length);
71 LIBCFS_FREE(ctrs, sizeof(*ctrs));
76 lnet_router_proc_stats_write(struct file *file, const char *ubuffer,
77 unsigned long count, void *data)
80 memset(&the_lnet.ln_counters, 0, sizeof(the_lnet.ln_counters));
88 lnet_remotenet_t *lrsi_net;
89 lnet_route_t *lrsi_route;
91 } lnet_route_seq_iterator_t;
94 lnet_route_seq_seek (lnet_route_seq_iterator_t *lrsi, loff_t off)
102 lrsi->lrsi_net = NULL;
103 lrsi->lrsi_route = NULL;
110 if (lrsi->lrsi_net != NULL &&
111 lrsi->lrsi_version != the_lnet.ln_remote_nets_version) {
112 /* tables have changed */
117 if (lrsi->lrsi_net == NULL || lrsi->lrsi_off > off) {
118 /* search from start */
119 n = the_lnet.ln_remote_nets.next;
123 /* continue search */
124 n = &lrsi->lrsi_net->lrn_list;
125 r = &lrsi->lrsi_route->lr_list;
126 here = lrsi->lrsi_off;
129 lrsi->lrsi_version = the_lnet.ln_remote_nets_version;
130 lrsi->lrsi_off = off;
132 while (n != &the_lnet.ln_remote_nets) {
133 lnet_remotenet_t *rnet =
134 list_entry(n, lnet_remotenet_t, lrn_list);
137 r = rnet->lrn_routes.next;
139 while (r != &rnet->lrn_routes) {
141 list_entry(r, lnet_route_t,
145 lrsi->lrsi_net = rnet;
146 lrsi->lrsi_route = re;
159 lrsi->lrsi_net = NULL;
160 lrsi->lrsi_route = NULL;
168 lnet_route_seq_start (struct seq_file *s, loff_t *pos)
170 lnet_route_seq_iterator_t *lrsi;
173 LIBCFS_ALLOC(lrsi, sizeof(*lrsi));
177 lrsi->lrsi_net = NULL;
178 rc = lnet_route_seq_seek(lrsi, *pos);
182 LIBCFS_FREE(lrsi, sizeof(*lrsi));
187 lnet_route_seq_stop (struct seq_file *s, void *iter)
189 lnet_route_seq_iterator_t *lrsi = iter;
192 LIBCFS_FREE(lrsi, sizeof(*lrsi));
196 lnet_route_seq_next (struct seq_file *s, void *iter, loff_t *pos)
198 lnet_route_seq_iterator_t *lrsi = iter;
200 loff_t next = *pos + 1;
202 rc = lnet_route_seq_seek(lrsi, next);
204 LIBCFS_FREE(lrsi, sizeof(*lrsi));
213 lnet_route_seq_show (struct seq_file *s, void *iter)
215 lnet_route_seq_iterator_t *lrsi = iter;
221 if (lrsi->lrsi_off == 0) {
222 seq_printf(s, "Routing %s\n",
223 the_lnet.ln_routing ? "enabled" : "disabled");
224 seq_printf(s, "%-8s %4s %7s %s\n",
225 "net", "hops", "state", "router");
229 LASSERT (lrsi->lrsi_net != NULL);
230 LASSERT (lrsi->lrsi_route != NULL);
234 if (lrsi->lrsi_version != the_lnet.ln_remote_nets_version) {
239 net = lrsi->lrsi_net->lrn_net;
240 hops = lrsi->lrsi_net->lrn_hops;
241 nid = lrsi->lrsi_route->lr_gateway->lp_nid;
242 alive = lrsi->lrsi_route->lr_gateway->lp_alive;
246 seq_printf(s, "%-8s %4u %7s %s\n", libcfs_net2str(net), hops,
247 alive ? "up" : "down", libcfs_nid2str(nid));
251 static struct seq_operations lnet_routes_sops = {
252 .start = lnet_route_seq_start,
253 .stop = lnet_route_seq_stop,
254 .next = lnet_route_seq_next,
255 .show = lnet_route_seq_show,
259 lnet_route_seq_open(struct inode *inode, struct file *file)
261 struct proc_dir_entry *dp = PDE(inode);
265 rc = seq_open(file, &lnet_routes_sops);
267 sf = file->private_data;
268 sf->private = dp->data;
274 static struct file_operations lnet_routes_fops = {
275 .owner = THIS_MODULE,
276 .open = lnet_route_seq_open,
279 .release = seq_release,
283 __u64 lrtrsi_version;
284 lnet_peer_t *lrtrsi_router;
286 } lnet_router_seq_iterator_t;
289 lnet_router_seq_seek (lnet_router_seq_iterator_t *lrtrsi, loff_t off)
297 lrtrsi->lrtrsi_router = NULL;
298 lrtrsi->lrtrsi_off = 0;
304 lp = lrtrsi->lrtrsi_router;
307 lrtrsi->lrtrsi_version != the_lnet.ln_routers_version) {
308 /* tables have changed */
313 if (lp == NULL || lrtrsi->lrtrsi_off > off) {
314 /* search from start */
315 r = the_lnet.ln_routers.next;
318 /* continue search */
319 r = &lp->lp_rtr_list;
320 here = lrtrsi->lrtrsi_off;
323 lrtrsi->lrtrsi_version = the_lnet.ln_routers_version;
324 lrtrsi->lrtrsi_off = off;
326 while (r != &the_lnet.ln_routers) {
327 lnet_peer_t *rtr = list_entry(r,
332 lrtrsi->lrtrsi_router = rtr;
341 lrtrsi->lrtrsi_router = NULL;
349 lnet_router_seq_start (struct seq_file *s, loff_t *pos)
351 lnet_router_seq_iterator_t *lrtrsi;
354 LIBCFS_ALLOC(lrtrsi, sizeof(*lrtrsi));
358 lrtrsi->lrtrsi_router = NULL;
359 rc = lnet_router_seq_seek(lrtrsi, *pos);
363 LIBCFS_FREE(lrtrsi, sizeof(*lrtrsi));
368 lnet_router_seq_stop (struct seq_file *s, void *iter)
370 lnet_router_seq_iterator_t *lrtrsi = iter;
373 LIBCFS_FREE(lrtrsi, sizeof(*lrtrsi));
377 lnet_router_seq_next (struct seq_file *s, void *iter, loff_t *pos)
379 lnet_router_seq_iterator_t *lrtrsi = iter;
381 loff_t next = *pos + 1;
383 rc = lnet_router_seq_seek(lrtrsi, next);
385 LIBCFS_FREE(lrtrsi, sizeof(*lrtrsi));
394 lnet_router_seq_show (struct seq_file *s, void *iter)
396 lnet_router_seq_iterator_t *lrtrsi = iter;
405 if (lrtrsi->lrtrsi_off == 0) {
406 seq_printf(s, "%-4s %7s %9s %6s %12s %s\n",
407 "ref", "rtr_ref", "alive_cnt", "state", "last_ping", "router");
411 lp = lrtrsi->lrtrsi_router;
412 LASSERT (lp != NULL);
416 if (lrtrsi->lrtrsi_version != the_lnet.ln_routers_version) {
422 alive = lp->lp_alive;
423 alive_cnt = lp->lp_alive_count;
424 nrefs = lp->lp_refcount;
425 nrtrrefs = lp->lp_rtr_refcount;
426 last_ping = lp->lp_ping_timestamp;
431 "%-4d %7d %9d %6s %12lu %s\n", nrefs, nrtrrefs,
432 alive_cnt, alive ? "up" : "down",
433 last_ping, libcfs_nid2str(nid));
437 static struct seq_operations lnet_routers_sops = {
438 .start = lnet_router_seq_start,
439 .stop = lnet_router_seq_stop,
440 .next = lnet_router_seq_next,
441 .show = lnet_router_seq_show,
445 lnet_router_seq_open(struct inode *inode, struct file *file)
447 struct proc_dir_entry *dp = PDE(inode);
451 rc = seq_open(file, &lnet_routers_sops);
453 sf = file->private_data;
454 sf->private = dp->data;
460 static struct file_operations lnet_routers_fops = {
461 .owner = THIS_MODULE,
462 .open = lnet_router_seq_open,
465 .release = seq_release,
469 unsigned long long lpsi_version;
471 lnet_peer_t *lpsi_peer;
473 } lnet_peer_seq_iterator_t;
476 lnet_peer_seq_seek (lnet_peer_seq_iterator_t *lpsi, loff_t off)
485 lpsi->lpsi_peer = NULL;
492 if (lpsi->lpsi_peer != NULL &&
493 lpsi->lpsi_version != the_lnet.ln_peertable_version) {
494 /* tables have changed */
499 if (lpsi->lpsi_peer == NULL ||
500 lpsi->lpsi_off > off) {
501 /* search from start */
506 /* continue search */
507 idx = lpsi->lpsi_idx;
508 p = &lpsi->lpsi_peer->lp_hashlist;
509 here = lpsi->lpsi_off;
512 lpsi->lpsi_version = the_lnet.ln_peertable_version;
513 lpsi->lpsi_off = off;
515 while (idx < LNET_PEER_HASHSIZE) {
517 p = the_lnet.ln_peer_hash[idx].next;
519 while (p != &the_lnet.ln_peer_hash[idx]) {
520 lnet_peer_t *lp = list_entry(p, lnet_peer_t,
524 lpsi->lpsi_idx = idx;
525 lpsi->lpsi_peer = lp;
531 p = lp->lp_hashlist.next;
539 lpsi->lpsi_peer = NULL;
547 lnet_peer_seq_start (struct seq_file *s, loff_t *pos)
549 lnet_peer_seq_iterator_t *lpsi;
552 LIBCFS_ALLOC(lpsi, sizeof(*lpsi));
557 lpsi->lpsi_peer = NULL;
558 rc = lnet_peer_seq_seek(lpsi, *pos);
562 LIBCFS_FREE(lpsi, sizeof(*lpsi));
567 lnet_peer_seq_stop (struct seq_file *s, void *iter)
569 lnet_peer_seq_iterator_t *lpsi = iter;
572 LIBCFS_FREE(lpsi, sizeof(*lpsi));
576 lnet_peer_seq_next (struct seq_file *s, void *iter, loff_t *pos)
578 lnet_peer_seq_iterator_t *lpsi = iter;
580 loff_t next = *pos + 1;
582 rc = lnet_peer_seq_seek(lpsi, next);
584 LIBCFS_FREE(lpsi, sizeof(*lpsi));
593 lnet_peer_seq_show (struct seq_file *s, void *iter)
595 lnet_peer_seq_iterator_t *lpsi = iter;
608 if (lpsi->lpsi_off == 0) {
609 seq_printf(s, "%-24s %4s %5s %5s %5s %5s %5s %5s %s\n",
610 "nid", "refs", "state", "max",
611 "rtr", "min", "tx", "min", "queue");
615 LASSERT (lpsi->lpsi_peer != NULL);
619 if (lpsi->lpsi_version != the_lnet.ln_peertable_version) {
624 lp = lpsi->lpsi_peer;
627 maxcr = lp->lp_ni->ni_peertxcredits;
628 txcr = lp->lp_txcredits;
629 mintxcr = lp->lp_mintxcredits;
630 rtrcr = lp->lp_rtrcredits;
631 minrtrcr = lp->lp_minrtrcredits;
632 rtr = lnet_isrouter(lp);
633 alive = lp->lp_alive;
634 txqnob = lp->lp_txqnob;
635 nrefs = lp->lp_refcount;
639 seq_printf(s, "%-24s %4d %5s %5d %5d %5d %5d %5d %d\n",
640 libcfs_nid2str(nid), nrefs,
641 !rtr ? "~rtr" : (alive ? "up" : "down"),
642 maxcr, rtrcr, minrtrcr, txcr, mintxcr, txqnob);
646 static struct seq_operations lnet_peer_sops = {
647 .start = lnet_peer_seq_start,
648 .stop = lnet_peer_seq_stop,
649 .next = lnet_peer_seq_next,
650 .show = lnet_peer_seq_show,
654 lnet_peer_seq_open(struct inode *inode, struct file *file)
656 struct proc_dir_entry *dp = PDE(inode);
660 rc = seq_open(file, &lnet_peer_sops);
662 sf = file->private_data;
663 sf->private = dp->data;
669 static struct file_operations lnet_peer_fops = {
670 .owner = THIS_MODULE,
671 .open = lnet_peer_seq_open,
674 .release = seq_release,
680 } lnet_buffer_seq_iterator_t;
683 lnet_buffer_seq_seek (lnet_buffer_seq_iterator_t *lbsi, loff_t off)
697 if (lbsi->lbsi_idx < 0 ||
698 lbsi->lbsi_off > off) {
699 /* search from start */
703 /* continue search */
704 idx = lbsi->lbsi_idx;
705 here = lbsi->lbsi_off;
708 lbsi->lbsi_off = off;
710 while (idx < LNET_NRBPOOLS) {
712 lbsi->lbsi_idx = idx;
728 lnet_buffer_seq_start (struct seq_file *s, loff_t *pos)
730 lnet_buffer_seq_iterator_t *lbsi;
733 LIBCFS_ALLOC(lbsi, sizeof(*lbsi));
738 rc = lnet_buffer_seq_seek(lbsi, *pos);
742 LIBCFS_FREE(lbsi, sizeof(*lbsi));
747 lnet_buffer_seq_stop (struct seq_file *s, void *iter)
749 lnet_buffer_seq_iterator_t *lbsi = iter;
752 LIBCFS_FREE(lbsi, sizeof(*lbsi));
756 lnet_buffer_seq_next (struct seq_file *s, void *iter, loff_t *pos)
758 lnet_buffer_seq_iterator_t *lbsi = iter;
760 loff_t next = *pos + 1;
762 rc = lnet_buffer_seq_seek(lbsi, next);
764 LIBCFS_FREE(lbsi, sizeof(*lbsi));
773 lnet_buffer_seq_show (struct seq_file *s, void *iter)
775 lnet_buffer_seq_iterator_t *lbsi = iter;
776 lnet_rtrbufpool_t *rbp;
782 if (lbsi->lbsi_off == 0) {
783 seq_printf(s, "%5s %5s %7s %7s\n",
784 "pages", "count", "credits", "min");
788 LASSERT (lbsi->lbsi_idx >= 0 && lbsi->lbsi_idx < LNET_NRBPOOLS);
792 rbp = &the_lnet.ln_rtrpools[lbsi->lbsi_idx];
794 npages = rbp->rbp_npages;
795 nbuf = rbp->rbp_nbuffers;
796 cr = rbp->rbp_credits;
797 mincr = rbp->rbp_mincredits;
801 seq_printf(s, "%5d %5d %7d %7d\n",
802 npages, nbuf, cr, mincr);
806 static struct seq_operations lnet_buffer_sops = {
807 .start = lnet_buffer_seq_start,
808 .stop = lnet_buffer_seq_stop,
809 .next = lnet_buffer_seq_next,
810 .show = lnet_buffer_seq_show,
814 lnet_buffer_seq_open(struct inode *inode, struct file *file)
816 struct proc_dir_entry *dp = PDE(inode);
820 rc = seq_open(file, &lnet_buffer_sops);
822 sf = file->private_data;
823 sf->private = dp->data;
829 static struct file_operations lnet_buffers_fops = {
830 .owner = THIS_MODULE,
831 .open = lnet_buffer_seq_open,
834 .release = seq_release,
840 } lnet_ni_seq_iterator_t;
843 lnet_ni_seq_seek (lnet_ni_seq_iterator_t *lnsi, loff_t off)
850 lnsi->lnsi_ni = NULL;
857 if (lnsi->lnsi_ni == NULL ||
858 lnsi->lnsi_off > off) {
859 /* search from start */
863 /* continue search */
864 n = &lnsi->lnsi_ni->ni_list;
865 here = lnsi->lnsi_off;
868 lnsi->lnsi_off = off;
871 n = the_lnet.ln_nis.next;
873 while (n != &the_lnet.ln_nis) {
875 lnsi->lnsi_ni = list_entry(n, lnet_ni_t, ni_list);
883 lnsi->lnsi_ni = NULL;
891 lnet_ni_seq_start (struct seq_file *s, loff_t *pos)
893 lnet_ni_seq_iterator_t *lnsi;
896 LIBCFS_ALLOC(lnsi, sizeof(*lnsi));
900 lnsi->lnsi_ni = NULL;
901 rc = lnet_ni_seq_seek(lnsi, *pos);
905 LIBCFS_FREE(lnsi, sizeof(*lnsi));
910 lnet_ni_seq_stop (struct seq_file *s, void *iter)
912 lnet_ni_seq_iterator_t *lnsi = iter;
915 LIBCFS_FREE(lnsi, sizeof(*lnsi));
919 lnet_ni_seq_next (struct seq_file *s, void *iter, loff_t *pos)
921 lnet_ni_seq_iterator_t *lnsi = iter;
923 loff_t next = *pos + 1;
925 rc = lnet_ni_seq_seek(lnsi, next);
927 LIBCFS_FREE(lnsi, sizeof(*lnsi));
936 lnet_ni_seq_show (struct seq_file *s, void *iter)
938 lnet_ni_seq_iterator_t *lnsi = iter;
947 if (lnsi->lnsi_off == 0) {
948 seq_printf(s, "%-24s %4s %4s %5s %5s %5s\n",
949 "nid", "refs", "peer", "max", "tx", "min");
953 LASSERT (lnsi->lnsi_ni != NULL);
959 maxtxcr = ni->ni_maxtxcredits;
960 txcr = ni->ni_txcredits;
961 mintxcr = ni->ni_mintxcredits;
962 npeertxcr = ni->ni_peertxcredits;
964 nref = ni->ni_refcount;
968 seq_printf(s, "%-24s %4d %4d %5d %5d %5d\n",
969 libcfs_nid2str(nid), nref,
970 npeertxcr, maxtxcr, txcr, mintxcr);
974 static struct seq_operations lnet_ni_sops = {
975 .start = lnet_ni_seq_start,
976 .stop = lnet_ni_seq_stop,
977 .next = lnet_ni_seq_next,
978 .show = lnet_ni_seq_show,
982 lnet_ni_seq_open(struct inode *inode, struct file *file)
984 struct proc_dir_entry *dp = PDE(inode);
988 rc = seq_open(file, &lnet_ni_sops);
990 sf = file->private_data;
991 sf->private = dp->data;
997 static struct file_operations lnet_ni_fops = {
998 .owner = THIS_MODULE,
999 .open = lnet_ni_seq_open,
1001 .llseek = seq_lseek,
1002 .release = seq_release,
1006 lnet_proc_init(void)
1008 struct proc_dir_entry *pde;
1010 /* Initialize LNET_PROC_STATS */
1011 pde = create_proc_entry (LNET_PROC_STATS, 0644, NULL);
1013 CERROR("couldn't create proc entry %s\n", LNET_PROC_STATS);
1018 pde->read_proc = lnet_router_proc_stats_read;
1019 pde->write_proc = lnet_router_proc_stats_write;
1021 /* Initialize LNET_PROC_ROUTES */
1022 pde = create_proc_entry (LNET_PROC_ROUTES, 0444, NULL);
1024 CERROR("couldn't create proc entry %s\n", LNET_PROC_ROUTES);
1028 pde->proc_fops = &lnet_routes_fops;
1031 /* Initialize LNET_PROC_ROUTERS */
1032 pde = create_proc_entry (LNET_PROC_ROUTERS, 0444, NULL);
1034 CERROR("couldn't create proc entry %s\n", LNET_PROC_ROUTERS);
1038 pde->proc_fops = &lnet_routers_fops;
1041 /* Initialize LNET_PROC_PEERS */
1042 pde = create_proc_entry (LNET_PROC_PEERS, 0444, NULL);
1044 CERROR("couldn't create proc entry %s\n", LNET_PROC_PEERS);
1048 pde->proc_fops = &lnet_peer_fops;
1051 /* Initialize LNET_PROC_BUFFERS */
1052 pde = create_proc_entry (LNET_PROC_BUFFERS, 0444, NULL);
1054 CERROR("couldn't create proc entry %s\n", LNET_PROC_BUFFERS);
1058 pde->proc_fops = &lnet_buffers_fops;
1061 /* Initialize LNET_PROC_NIS */
1062 pde = create_proc_entry (LNET_PROC_NIS, 0444, NULL);
1064 CERROR("couldn't create proc entry %s\n", LNET_PROC_NIS);
1068 pde->proc_fops = &lnet_ni_fops;
1073 lnet_proc_fini(void)
1075 remove_proc_entry(LNET_PROC_STATS, 0);
1076 remove_proc_entry(LNET_PROC_ROUTES, 0);
1077 remove_proc_entry(LNET_PROC_ROUTERS, 0);
1078 remove_proc_entry(LNET_PROC_PEERS, 0);
1079 remove_proc_entry(LNET_PROC_BUFFERS, 0);
1080 remove_proc_entry(LNET_PROC_NIS, 0);
1086 lnet_proc_init(void)
1091 lnet_proc_fini(void)