1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
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>
32 /* this is really lnet_proc.c */
34 #define LNET_PROC_STATS "sys/lnet/stats"
35 #define LNET_PROC_ROUTES "sys/lnet/routes"
36 #define LNET_PROC_ROUTERS "sys/lnet/routers"
37 #define LNET_PROC_PEERS "sys/lnet/peers"
38 #define LNET_PROC_BUFFERS "sys/lnet/buffers"
39 #define LNET_PROC_NIS "sys/lnet/nis"
42 lnet_router_proc_stats_read (char *page, char **start, off_t off,
43 int count, int *eof, void *data)
45 lnet_counters_t *ctrs;
53 LIBCFS_ALLOC(ctrs, sizeof(*ctrs));
58 *ctrs = the_lnet.ln_counters;
62 "%u %u %u %u %u %u %u "LPU64" "LPU64" "LPU64" "LPU64"\n",
63 ctrs->msgs_alloc, ctrs->msgs_max,
65 ctrs->send_count, ctrs->recv_count,
66 ctrs->route_count, ctrs->drop_count,
67 ctrs->send_length, ctrs->recv_length,
68 ctrs->route_length, ctrs->drop_length);
70 LIBCFS_FREE(ctrs, sizeof(*ctrs));
75 lnet_router_proc_stats_write(struct file *file, const char *ubuffer,
76 unsigned long count, void *data)
79 memset(&the_lnet.ln_counters, 0, sizeof(the_lnet.ln_counters));
87 lnet_remotenet_t *lrsi_net;
88 lnet_route_t *lrsi_route;
90 } lnet_route_seq_iterator_t;
93 lnet_route_seq_seek (lnet_route_seq_iterator_t *lrsi, loff_t off)
101 lrsi->lrsi_net = NULL;
102 lrsi->lrsi_route = NULL;
109 if (lrsi->lrsi_net != NULL &&
110 lrsi->lrsi_version != the_lnet.ln_remote_nets_version) {
111 /* tables have changed */
116 if (lrsi->lrsi_net == NULL || lrsi->lrsi_off > off) {
117 /* search from start */
118 n = the_lnet.ln_remote_nets.next;
122 /* continue search */
123 n = &lrsi->lrsi_net->lrn_list;
124 r = &lrsi->lrsi_route->lr_list;
125 here = lrsi->lrsi_off;
128 lrsi->lrsi_version = the_lnet.ln_remote_nets_version;
129 lrsi->lrsi_off = off;
131 while (n != &the_lnet.ln_remote_nets) {
132 lnet_remotenet_t *rnet =
133 list_entry(n, lnet_remotenet_t, lrn_list);
136 r = rnet->lrn_routes.next;
138 while (r != &rnet->lrn_routes) {
140 list_entry(r, lnet_route_t,
144 lrsi->lrsi_net = rnet;
145 lrsi->lrsi_route = re;
158 lrsi->lrsi_net = NULL;
159 lrsi->lrsi_route = NULL;
167 lnet_route_seq_start (struct seq_file *s, loff_t *pos)
169 lnet_route_seq_iterator_t *lrsi;
172 LIBCFS_ALLOC(lrsi, sizeof(*lrsi));
176 lrsi->lrsi_net = NULL;
177 rc = lnet_route_seq_seek(lrsi, *pos);
181 LIBCFS_FREE(lrsi, sizeof(*lrsi));
186 lnet_route_seq_stop (struct seq_file *s, void *iter)
188 lnet_route_seq_iterator_t *lrsi = iter;
191 LIBCFS_FREE(lrsi, sizeof(*lrsi));
195 lnet_route_seq_next (struct seq_file *s, void *iter, loff_t *pos)
197 lnet_route_seq_iterator_t *lrsi = iter;
199 loff_t next = *pos + 1;
201 rc = lnet_route_seq_seek(lrsi, next);
203 LIBCFS_FREE(lrsi, sizeof(*lrsi));
212 lnet_route_seq_show (struct seq_file *s, void *iter)
214 lnet_route_seq_iterator_t *lrsi = iter;
220 if (lrsi->lrsi_off == 0) {
221 seq_printf(s, "Routing %s\n",
222 the_lnet.ln_routing ? "enabled" : "disabled");
223 seq_printf(s, "%-8s %4s %7s %s\n",
224 "net", "hops", "state", "router");
228 LASSERT (lrsi->lrsi_net != NULL);
229 LASSERT (lrsi->lrsi_route != NULL);
233 if (lrsi->lrsi_version != the_lnet.ln_remote_nets_version) {
238 net = lrsi->lrsi_net->lrn_net;
239 hops = lrsi->lrsi_net->lrn_hops;
240 nid = lrsi->lrsi_route->lr_gateway->lp_nid;
241 alive = lrsi->lrsi_route->lr_gateway->lp_alive;
245 seq_printf(s, "%-8s %4u %7s %s\n", libcfs_net2str(net), hops,
246 alive ? "up" : "down", libcfs_nid2str(nid));
250 static struct seq_operations lnet_routes_sops = {
251 .start = lnet_route_seq_start,
252 .stop = lnet_route_seq_stop,
253 .next = lnet_route_seq_next,
254 .show = lnet_route_seq_show,
258 lnet_route_seq_open(struct inode *inode, struct file *file)
260 struct proc_dir_entry *dp = PDE(inode);
264 rc = seq_open(file, &lnet_routes_sops);
266 sf = file->private_data;
267 sf->private = dp->data;
273 static struct file_operations lnet_routes_fops = {
274 .owner = THIS_MODULE,
275 .open = lnet_route_seq_open,
278 .release = seq_release,
282 __u64 lrtrsi_version;
283 lnet_peer_t *lrtrsi_router;
285 } lnet_router_seq_iterator_t;
288 lnet_router_seq_seek (lnet_router_seq_iterator_t *lrtrsi, loff_t off)
296 lrtrsi->lrtrsi_router = NULL;
297 lrtrsi->lrtrsi_off = 0;
303 lp = lrtrsi->lrtrsi_router;
306 lrtrsi->lrtrsi_version != the_lnet.ln_routers_version) {
307 /* tables have changed */
312 if (lp == NULL || lrtrsi->lrtrsi_off > off) {
313 /* search from start */
314 r = the_lnet.ln_routers.next;
317 /* continue search */
318 r = &lp->lp_rtr_list;
319 here = lrtrsi->lrtrsi_off;
322 lrtrsi->lrtrsi_version = the_lnet.ln_routers_version;
323 lrtrsi->lrtrsi_off = off;
325 while (r != &the_lnet.ln_routers) {
326 lnet_peer_t *rtr = list_entry(r,
331 lrtrsi->lrtrsi_router = rtr;
340 lrtrsi->lrtrsi_router = NULL;
348 lnet_router_seq_start (struct seq_file *s, loff_t *pos)
350 lnet_router_seq_iterator_t *lrtrsi;
353 LIBCFS_ALLOC(lrtrsi, sizeof(*lrtrsi));
357 lrtrsi->lrtrsi_router = NULL;
358 rc = lnet_router_seq_seek(lrtrsi, *pos);
362 LIBCFS_FREE(lrtrsi, sizeof(*lrtrsi));
367 lnet_router_seq_stop (struct seq_file *s, void *iter)
369 lnet_router_seq_iterator_t *lrtrsi = iter;
372 LIBCFS_FREE(lrtrsi, sizeof(*lrtrsi));
376 lnet_router_seq_next (struct seq_file *s, void *iter, loff_t *pos)
378 lnet_router_seq_iterator_t *lrtrsi = iter;
380 loff_t next = *pos + 1;
382 rc = lnet_router_seq_seek(lrtrsi, next);
384 LIBCFS_FREE(lrtrsi, sizeof(*lrtrsi));
393 lnet_router_seq_show (struct seq_file *s, void *iter)
395 lnet_router_seq_iterator_t *lrtrsi = iter;
404 if (lrtrsi->lrtrsi_off == 0) {
405 seq_printf(s, "%-4s %7s %9s %6s %12s %s\n",
406 "ref", "rtr_ref", "alive_cnt", "state", "last_ping", "router");
410 lp = lrtrsi->lrtrsi_router;
411 LASSERT (lp != NULL);
415 if (lrtrsi->lrtrsi_version != the_lnet.ln_routers_version) {
421 alive = lp->lp_alive;
422 alive_cnt = lp->lp_alive_count;
423 nrefs = lp->lp_refcount;
424 nrtrrefs = lp->lp_rtr_refcount;
425 last_ping = lp->lp_ping_timestamp;
430 "%-4d %7d %9d %6s %12lu %s\n", nrefs, nrtrrefs,
431 alive_cnt, alive ? "up" : "down",
432 last_ping, libcfs_nid2str(nid));
436 static struct seq_operations lnet_routers_sops = {
437 .start = lnet_router_seq_start,
438 .stop = lnet_router_seq_stop,
439 .next = lnet_router_seq_next,
440 .show = lnet_router_seq_show,
444 lnet_router_seq_open(struct inode *inode, struct file *file)
446 struct proc_dir_entry *dp = PDE(inode);
450 rc = seq_open(file, &lnet_routers_sops);
452 sf = file->private_data;
453 sf->private = dp->data;
459 static struct file_operations lnet_routers_fops = {
460 .owner = THIS_MODULE,
461 .open = lnet_router_seq_open,
464 .release = seq_release,
468 unsigned long long lpsi_version;
470 lnet_peer_t *lpsi_peer;
472 } lnet_peer_seq_iterator_t;
475 lnet_peer_seq_seek (lnet_peer_seq_iterator_t *lpsi, loff_t off)
484 lpsi->lpsi_peer = NULL;
491 if (lpsi->lpsi_peer != NULL &&
492 lpsi->lpsi_version != the_lnet.ln_peertable_version) {
493 /* tables have changed */
498 if (lpsi->lpsi_peer == NULL ||
499 lpsi->lpsi_off > off) {
500 /* search from start */
505 /* continue search */
506 idx = lpsi->lpsi_idx;
507 p = &lpsi->lpsi_peer->lp_hashlist;
508 here = lpsi->lpsi_off;
511 lpsi->lpsi_version = the_lnet.ln_peertable_version;
512 lpsi->lpsi_off = off;
514 while (idx < LNET_PEER_HASHSIZE) {
516 p = the_lnet.ln_peer_hash[idx].next;
518 while (p != &the_lnet.ln_peer_hash[idx]) {
519 lnet_peer_t *lp = list_entry(p, lnet_peer_t,
523 lpsi->lpsi_idx = idx;
524 lpsi->lpsi_peer = lp;
530 p = lp->lp_hashlist.next;
538 lpsi->lpsi_peer = NULL;
546 lnet_peer_seq_start (struct seq_file *s, loff_t *pos)
548 lnet_peer_seq_iterator_t *lpsi;
551 LIBCFS_ALLOC(lpsi, sizeof(*lpsi));
556 lpsi->lpsi_peer = NULL;
557 rc = lnet_peer_seq_seek(lpsi, *pos);
561 LIBCFS_FREE(lpsi, sizeof(*lpsi));
566 lnet_peer_seq_stop (struct seq_file *s, void *iter)
568 lnet_peer_seq_iterator_t *lpsi = iter;
571 LIBCFS_FREE(lpsi, sizeof(*lpsi));
575 lnet_peer_seq_next (struct seq_file *s, void *iter, loff_t *pos)
577 lnet_peer_seq_iterator_t *lpsi = iter;
579 loff_t next = *pos + 1;
581 rc = lnet_peer_seq_seek(lpsi, next);
583 LIBCFS_FREE(lpsi, sizeof(*lpsi));
592 lnet_peer_seq_show (struct seq_file *s, void *iter)
594 lnet_peer_seq_iterator_t *lpsi = iter;
607 if (lpsi->lpsi_off == 0) {
608 seq_printf(s, "%-24s %4s %5s %5s %5s %5s %5s %5s %s\n",
609 "nid", "refs", "state", "max",
610 "rtr", "min", "tx", "min", "queue");
614 LASSERT (lpsi->lpsi_peer != NULL);
618 if (lpsi->lpsi_version != the_lnet.ln_peertable_version) {
623 lp = lpsi->lpsi_peer;
626 maxcr = lp->lp_ni->ni_peertxcredits;
627 txcr = lp->lp_txcredits;
628 mintxcr = lp->lp_mintxcredits;
629 rtrcr = lp->lp_rtrcredits;
630 minrtrcr = lp->lp_minrtrcredits;
631 rtr = lnet_isrouter(lp);
632 alive = lp->lp_alive;
633 txqnob = lp->lp_txqnob;
634 nrefs = lp->lp_refcount;
638 seq_printf(s, "%-24s %4d %5s %5d %5d %5d %5d %5d %d\n",
639 libcfs_nid2str(nid), nrefs,
640 !rtr ? "~rtr" : (alive ? "up" : "down"),
641 maxcr, rtrcr, minrtrcr, txcr, mintxcr, txqnob);
645 static struct seq_operations lnet_peer_sops = {
646 .start = lnet_peer_seq_start,
647 .stop = lnet_peer_seq_stop,
648 .next = lnet_peer_seq_next,
649 .show = lnet_peer_seq_show,
653 lnet_peer_seq_open(struct inode *inode, struct file *file)
655 struct proc_dir_entry *dp = PDE(inode);
659 rc = seq_open(file, &lnet_peer_sops);
661 sf = file->private_data;
662 sf->private = dp->data;
668 static struct file_operations lnet_peer_fops = {
669 .owner = THIS_MODULE,
670 .open = lnet_peer_seq_open,
673 .release = seq_release,
679 } lnet_buffer_seq_iterator_t;
682 lnet_buffer_seq_seek (lnet_buffer_seq_iterator_t *lbsi, loff_t off)
696 if (lbsi->lbsi_idx < 0 ||
697 lbsi->lbsi_off > off) {
698 /* search from start */
702 /* continue search */
703 idx = lbsi->lbsi_idx;
704 here = lbsi->lbsi_off;
707 lbsi->lbsi_off = off;
709 while (idx < LNET_NRBPOOLS) {
711 lbsi->lbsi_idx = idx;
727 lnet_buffer_seq_start (struct seq_file *s, loff_t *pos)
729 lnet_buffer_seq_iterator_t *lbsi;
732 LIBCFS_ALLOC(lbsi, sizeof(*lbsi));
737 rc = lnet_buffer_seq_seek(lbsi, *pos);
741 LIBCFS_FREE(lbsi, sizeof(*lbsi));
746 lnet_buffer_seq_stop (struct seq_file *s, void *iter)
748 lnet_buffer_seq_iterator_t *lbsi = iter;
751 LIBCFS_FREE(lbsi, sizeof(*lbsi));
755 lnet_buffer_seq_next (struct seq_file *s, void *iter, loff_t *pos)
757 lnet_buffer_seq_iterator_t *lbsi = iter;
759 loff_t next = *pos + 1;
761 rc = lnet_buffer_seq_seek(lbsi, next);
763 LIBCFS_FREE(lbsi, sizeof(*lbsi));
772 lnet_buffer_seq_show (struct seq_file *s, void *iter)
774 lnet_buffer_seq_iterator_t *lbsi = iter;
775 lnet_rtrbufpool_t *rbp;
781 if (lbsi->lbsi_off == 0) {
782 seq_printf(s, "%5s %5s %7s %7s\n",
783 "pages", "count", "credits", "min");
787 LASSERT (lbsi->lbsi_idx >= 0 && lbsi->lbsi_idx < LNET_NRBPOOLS);
791 rbp = &the_lnet.ln_rtrpools[lbsi->lbsi_idx];
793 npages = rbp->rbp_npages;
794 nbuf = rbp->rbp_nbuffers;
795 cr = rbp->rbp_credits;
796 mincr = rbp->rbp_mincredits;
800 seq_printf(s, "%5d %5d %7d %7d\n",
801 npages, nbuf, cr, mincr);
805 static struct seq_operations lnet_buffer_sops = {
806 .start = lnet_buffer_seq_start,
807 .stop = lnet_buffer_seq_stop,
808 .next = lnet_buffer_seq_next,
809 .show = lnet_buffer_seq_show,
813 lnet_buffer_seq_open(struct inode *inode, struct file *file)
815 struct proc_dir_entry *dp = PDE(inode);
819 rc = seq_open(file, &lnet_buffer_sops);
821 sf = file->private_data;
822 sf->private = dp->data;
828 static struct file_operations lnet_buffers_fops = {
829 .owner = THIS_MODULE,
830 .open = lnet_buffer_seq_open,
833 .release = seq_release,
839 } lnet_ni_seq_iterator_t;
842 lnet_ni_seq_seek (lnet_ni_seq_iterator_t *lnsi, loff_t off)
849 lnsi->lnsi_ni = NULL;
856 if (lnsi->lnsi_ni == NULL ||
857 lnsi->lnsi_off > off) {
858 /* search from start */
862 /* continue search */
863 n = &lnsi->lnsi_ni->ni_list;
864 here = lnsi->lnsi_off;
867 lnsi->lnsi_off = off;
870 n = the_lnet.ln_nis.next;
872 while (n != &the_lnet.ln_nis) {
874 lnsi->lnsi_ni = list_entry(n, lnet_ni_t, ni_list);
882 lnsi->lnsi_ni = NULL;
890 lnet_ni_seq_start (struct seq_file *s, loff_t *pos)
892 lnet_ni_seq_iterator_t *lnsi;
895 LIBCFS_ALLOC(lnsi, sizeof(*lnsi));
899 lnsi->lnsi_ni = NULL;
900 rc = lnet_ni_seq_seek(lnsi, *pos);
904 LIBCFS_FREE(lnsi, sizeof(*lnsi));
909 lnet_ni_seq_stop (struct seq_file *s, void *iter)
911 lnet_ni_seq_iterator_t *lnsi = iter;
914 LIBCFS_FREE(lnsi, sizeof(*lnsi));
918 lnet_ni_seq_next (struct seq_file *s, void *iter, loff_t *pos)
920 lnet_ni_seq_iterator_t *lnsi = iter;
922 loff_t next = *pos + 1;
924 rc = lnet_ni_seq_seek(lnsi, next);
926 LIBCFS_FREE(lnsi, sizeof(*lnsi));
935 lnet_ni_seq_show (struct seq_file *s, void *iter)
937 lnet_ni_seq_iterator_t *lnsi = iter;
946 if (lnsi->lnsi_off == 0) {
947 seq_printf(s, "%-24s %4s %4s %5s %5s %5s\n",
948 "nid", "refs", "peer", "max", "tx", "min");
952 LASSERT (lnsi->lnsi_ni != NULL);
958 maxtxcr = ni->ni_maxtxcredits;
959 txcr = ni->ni_txcredits;
960 mintxcr = ni->ni_mintxcredits;
961 npeertxcr = ni->ni_peertxcredits;
963 nref = ni->ni_refcount;
967 seq_printf(s, "%-24s %4d %4d %5d %5d %5d\n",
968 libcfs_nid2str(nid), nref,
969 npeertxcr, maxtxcr, txcr, mintxcr);
973 static struct seq_operations lnet_ni_sops = {
974 .start = lnet_ni_seq_start,
975 .stop = lnet_ni_seq_stop,
976 .next = lnet_ni_seq_next,
977 .show = lnet_ni_seq_show,
981 lnet_ni_seq_open(struct inode *inode, struct file *file)
983 struct proc_dir_entry *dp = PDE(inode);
987 rc = seq_open(file, &lnet_ni_sops);
989 sf = file->private_data;
990 sf->private = dp->data;
996 static struct file_operations lnet_ni_fops = {
997 .owner = THIS_MODULE,
998 .open = lnet_ni_seq_open,
1000 .llseek = seq_lseek,
1001 .release = seq_release,
1005 lnet_proc_init(void)
1007 struct proc_dir_entry *pde;
1009 /* Initialize LNET_PROC_STATS */
1010 pde = create_proc_entry (LNET_PROC_STATS, 0644, NULL);
1012 CERROR("couldn't create proc entry %s\n", LNET_PROC_STATS);
1017 pde->read_proc = lnet_router_proc_stats_read;
1018 pde->write_proc = lnet_router_proc_stats_write;
1020 /* Initialize LNET_PROC_ROUTES */
1021 pde = create_proc_entry (LNET_PROC_ROUTES, 0444, NULL);
1023 CERROR("couldn't create proc entry %s\n", LNET_PROC_ROUTES);
1027 pde->proc_fops = &lnet_routes_fops;
1030 /* Initialize LNET_PROC_ROUTERS */
1031 pde = create_proc_entry (LNET_PROC_ROUTERS, 0444, NULL);
1033 CERROR("couldn't create proc entry %s\n", LNET_PROC_ROUTERS);
1037 pde->proc_fops = &lnet_routers_fops;
1040 /* Initialize LNET_PROC_PEERS */
1041 pde = create_proc_entry (LNET_PROC_PEERS, 0444, NULL);
1043 CERROR("couldn't create proc entry %s\n", LNET_PROC_PEERS);
1047 pde->proc_fops = &lnet_peer_fops;
1050 /* Initialize LNET_PROC_BUFFERS */
1051 pde = create_proc_entry (LNET_PROC_BUFFERS, 0444, NULL);
1053 CERROR("couldn't create proc entry %s\n", LNET_PROC_BUFFERS);
1057 pde->proc_fops = &lnet_buffers_fops;
1060 /* Initialize LNET_PROC_NIS */
1061 pde = create_proc_entry (LNET_PROC_NIS, 0444, NULL);
1063 CERROR("couldn't create proc entry %s\n", LNET_PROC_NIS);
1067 pde->proc_fops = &lnet_ni_fops;
1072 lnet_proc_fini(void)
1074 remove_proc_entry(LNET_PROC_STATS, 0);
1075 remove_proc_entry(LNET_PROC_ROUTES, 0);
1076 remove_proc_entry(LNET_PROC_ROUTERS, 0);
1077 remove_proc_entry(LNET_PROC_PEERS, 0);
1078 remove_proc_entry(LNET_PROC_BUFFERS, 0);
1079 remove_proc_entry(LNET_PROC_NIS, 0);
1085 lnet_proc_init(void)
1090 lnet_proc_fini(void)