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 /* this is really lnet_proc.c */
32 static cfs_sysctl_table_header_t *lnet_table_header = NULL;
34 #ifndef HAVE_SYSCTL_UNNUMBERED
35 #define CTL_LNET (0x100)
37 PSDEV_LNET_STATS = 100,
45 #define CTL_LNET CTL_UNNUMBERED
46 #define PSDEV_LNET_STATS CTL_UNNUMBERED
47 #define PSDEV_LNET_ROUTES CTL_UNNUMBERED
48 #define PSDEV_LNET_ROUTERS CTL_UNNUMBERED
49 #define PSDEV_LNET_PEERS CTL_UNNUMBERED
50 #define PSDEV_LNET_BUFFERS CTL_UNNUMBERED
51 #define PSDEV_LNET_NIS CTL_UNNUMBERED
54 static int __proc_lnet_stats(void *data, int write,
55 loff_t pos, void *buffer, int nob)
58 lnet_counters_t *ctrs;
61 const int tmpsiz = 256; /* 7 %u and 4 LPU64 */
65 memset(&the_lnet.ln_counters, 0, sizeof(the_lnet.ln_counters));
72 LIBCFS_ALLOC(ctrs, sizeof(*ctrs));
76 LIBCFS_ALLOC(tmpstr, tmpsiz);
78 LIBCFS_FREE(ctrs, sizeof(*ctrs));
83 *ctrs = the_lnet.ln_counters;
86 len = snprintf(tmpstr, tmpsiz,
87 "%u %u %u %u %u %u %u "LPU64" "LPU64" "
89 ctrs->msgs_alloc, ctrs->msgs_max,
91 ctrs->send_count, ctrs->recv_count,
92 ctrs->route_count, ctrs->drop_count,
93 ctrs->send_length, ctrs->recv_length,
94 ctrs->route_length, ctrs->drop_length);
96 if (pos >= min_t(int, len, strlen(tmpstr)))
99 rc = trace_copyout_string(buffer, nob,
102 LIBCFS_FREE(tmpstr, tmpsiz);
103 LIBCFS_FREE(ctrs, sizeof(*ctrs));
107 DECLARE_PROC_HANDLER(proc_lnet_stats);
109 int LL_PROC_PROTO(proc_lnet_routes)
114 const int tmpsiz = 256;
116 int *ver_p = (unsigned int *)(&filp->private_data);
118 DECLARE_LL_PROC_PPOS_DECL;
125 LIBCFS_ALLOC(tmpstr, tmpsiz);
129 s = tmpstr; /* points to current position in tmpstr[] */
132 s += snprintf(s, tmpstr + tmpsiz - s, "Routing %s\n",
133 the_lnet.ln_routing ? "enabled" : "disabled");
134 LASSERT (tmpstr + tmpsiz - s > 0);
136 s += snprintf(s, tmpstr + tmpsiz - s, "%-8s %4s %7s %s\n",
137 "net", "hops", "state", "router");
138 LASSERT (tmpstr + tmpsiz - s > 0);
141 *ver_p = (unsigned int)the_lnet.ln_remote_nets_version;
146 lnet_route_t *route = NULL;
147 lnet_remotenet_t *rnet = NULL;
148 int skip = *ppos - 1;
152 if (*ver_p != (unsigned int)the_lnet.ln_remote_nets_version) {
154 LIBCFS_FREE(tmpstr, tmpsiz);
158 n = the_lnet.ln_remote_nets.next;
160 while (n != &the_lnet.ln_remote_nets && route == NULL) {
161 rnet = list_entry(n, lnet_remotenet_t, lrn_list);
163 r = rnet->lrn_routes.next;
165 while (r != &rnet->lrn_routes) {
166 lnet_route_t *re = list_entry(r, lnet_route_t,
181 __u32 net = rnet->lrn_net;
182 unsigned int hops = route->lr_hops;
183 lnet_nid_t nid = route->lr_gateway->lp_nid;
184 int alive = route->lr_gateway->lp_alive;
186 s += snprintf(s, tmpstr + tmpsiz - s, "%-8s %4u %7s %s\n",
187 libcfs_net2str(net), hops,
188 alive ? "up" : "down", libcfs_nid2str(nid));
189 LASSERT (tmpstr + tmpsiz - s > 0);
195 len = s - tmpstr; /* how many bytes was written */
197 if (len > *lenp) { /* linux-supplied buffer is too small */
199 } else if (len > 0) { /* wrote something */
200 if (copy_to_user(buffer, tmpstr, len))
206 LIBCFS_FREE(tmpstr, tmpsiz);
214 int LL_PROC_PROTO(proc_lnet_routers)
219 const int tmpsiz = 256;
221 int *ver_p = (unsigned int *)(&filp->private_data);
223 DECLARE_LL_PROC_PPOS_DECL;
230 LIBCFS_ALLOC(tmpstr, tmpsiz);
234 s = tmpstr; /* points to current position in tmpstr[] */
237 s += snprintf(s, tmpstr + tmpsiz - s,
238 "%-4s %7s %9s %6s %12s %9s %8s %7s %s\n",
239 "ref", "rtr_ref", "alive_cnt", "state", "last_ping",
240 "ping_sent", "deadline", "down_ni", "router");
241 LASSERT (tmpstr + tmpsiz - s > 0);
244 *ver_p = (unsigned int)the_lnet.ln_routers_version;
248 lnet_peer_t *peer = NULL;
249 int skip = *ppos - 1;
253 if (*ver_p != (unsigned int)the_lnet.ln_routers_version) {
255 LIBCFS_FREE(tmpstr, tmpsiz);
259 r = the_lnet.ln_routers.next;
261 while (r != &the_lnet.ln_routers) {
262 lnet_peer_t *lp = list_entry(r, lnet_peer_t,
275 lnet_nid_t nid = peer->lp_nid;
276 cfs_time_t now = cfs_time_current();
277 cfs_time_t deadline = peer->lp_ping_deadline;
278 int nrefs = peer->lp_refcount;
279 int nrtrrefs = peer->lp_rtr_refcount;
280 int alive_cnt = peer->lp_alive_count;
281 int alive = peer->lp_alive;
282 int pingsent = !peer->lp_ping_notsent;
283 int last_ping = cfs_duration_sec(cfs_time_sub(now,
284 peer->lp_ping_timestamp));
285 int down_ni = lnet_router_down_ni(peer,
286 LNET_NIDNET(LNET_NID_ANY));
289 s += snprintf(s, tmpstr + tmpsiz - s,
290 "%-4d %7d %9d %6s %12d %9d %8s %7d %s\n",
291 nrefs, nrtrrefs, alive_cnt,
292 alive ? "up" : "down", last_ping,
293 pingsent, "NA", down_ni,
294 libcfs_nid2str(nid));
296 s += snprintf(s, tmpstr + tmpsiz - s,
297 "%-4d %7d %9d %6s %12d %9d %8lu %7d %s\n",
298 nrefs, nrtrrefs, alive_cnt,
299 alive ? "up" : "down", last_ping,
301 cfs_duration_sec(cfs_time_sub(deadline, now)),
302 down_ni, libcfs_nid2str(nid));
303 LASSERT (tmpstr + tmpsiz - s > 0);
309 len = s - tmpstr; /* how many bytes was written */
311 if (len > *lenp) { /* linux-supplied buffer is too small */
313 } else if (len > 0) { /* wrote something */
314 if (copy_to_user(buffer, tmpstr, len))
320 LIBCFS_FREE(tmpstr, tmpsiz);
329 * NB: we don't use the highest bit of *ppos because it's signed;
330 * next 9 bits is used to stash idx (assuming that
331 * LNET_PEER_HASHSIZE < 512)
333 #define LNET_LOFFT_BITS (sizeof(loff_t) * 8)
334 #define LNET_PHASH_BITS 9
335 #define LNET_PHASH_IDX_MASK (((1ULL << LNET_PHASH_BITS) - 1) << \
336 (LNET_LOFFT_BITS - LNET_PHASH_BITS - 1))
337 #define LNET_PHASH_NUM_MASK ((1ULL << \
338 (LNET_LOFFT_BITS - LNET_PHASH_BITS -1)) - 1)
339 #define LNET_PHASH_IDX_GET(pos) (int)(((pos) & LNET_PHASH_IDX_MASK) >> \
340 (LNET_LOFFT_BITS - LNET_PHASH_BITS -1))
341 #define LNET_PHASH_NUM_GET(pos) (int)((pos) & LNET_PHASH_NUM_MASK)
342 #define LNET_PHASH_POS_MAKE(idx, num) ((((loff_t)idx) << (LNET_LOFFT_BITS - \
343 LNET_PHASH_BITS -1)) | (num))
345 int LL_PROC_PROTO(proc_lnet_peers)
350 const int tmpsiz = 256;
352 int *ver_p = (unsigned int *)(&filp->private_data);
356 DECLARE_LL_PROC_PPOS_DECL;
358 idx = LNET_PHASH_IDX_GET(*ppos);
359 num = LNET_PHASH_NUM_GET(*ppos);
361 CLASSERT ((1 << LNET_PHASH_BITS) > LNET_PEER_HASHSIZE);
368 LIBCFS_ALLOC(tmpstr, tmpsiz);
372 s = tmpstr; /* points to current position in tmpstr[] */
375 s += snprintf(s, tmpstr + tmpsiz - s,
376 "%-24s %4s %5s %5s %5s %5s %5s %5s %s\n",
377 "nid", "refs", "state", "max",
378 "rtr", "min", "tx", "min", "queue");
379 LASSERT (tmpstr + tmpsiz - s > 0);
382 *ver_p = (unsigned int)the_lnet.ln_peertable_version;
387 struct list_head *p = NULL;
388 lnet_peer_t *peer = NULL;
393 if (*ver_p != (unsigned int)the_lnet.ln_peertable_version) {
395 LIBCFS_FREE(tmpstr, tmpsiz);
399 while (idx < LNET_PEER_HASHSIZE) {
401 p = the_lnet.ln_peer_hash[idx].next;
403 while (p != &the_lnet.ln_peer_hash[idx]) {
404 lnet_peer_t *lp = list_entry(p, lnet_peer_t,
409 /* minor optimiztion: start from idx+1
410 * on next iteration if we've just
411 * drained lp_hashlist */
412 if (lp->lp_hashlist.next ==
413 &the_lnet.ln_peer_hash[idx]) {
424 p = lp->lp_hashlist.next;
436 lnet_nid_t nid = peer->lp_nid;
437 int nrefs = peer->lp_refcount;
438 char *aliveness = "NA";
439 int maxcr = peer->lp_ni->ni_peertxcredits;
440 int txcr = peer->lp_txcredits;
441 int mintxcr = peer->lp_mintxcredits;
442 int rtrcr = peer->lp_rtrcredits;
443 int minrtrcr = peer->lp_minrtrcredits;
444 int txqnob = peer->lp_txqnob;
446 if (lnet_isrouter(peer) ||
447 peer->lp_ni->ni_peertimeout > 0)
448 aliveness = peer->lp_alive ? "up" : "down";
450 s += snprintf(s, tmpstr + tmpsiz - s,
451 "%-24s %4d %5s %5d %5d %5d %5d %5d %d\n",
452 libcfs_nid2str(nid), nrefs, aliveness,
453 maxcr, rtrcr, minrtrcr, txcr,
455 LASSERT (tmpstr + tmpsiz - s > 0);
461 len = s - tmpstr; /* how many bytes was written */
463 if (len > *lenp) { /* linux-supplied buffer is too small */
465 } else if (len > 0) { /* wrote something */
466 if (copy_to_user(buffer, tmpstr, len))
469 *ppos = LNET_PHASH_POS_MAKE(idx, num);
472 LIBCFS_FREE(tmpstr, tmpsiz);
480 static int __proc_lnet_buffers(void *data, int write,
481 loff_t pos, void *buffer, int nob)
488 const int tmpsiz = 64 * (LNET_NRBPOOLS + 1); /* (4 %d) * 4 */
493 LIBCFS_ALLOC(tmpstr, tmpsiz);
497 s = tmpstr; /* points to current position in tmpstr[] */
499 s += snprintf(s, tmpstr + tmpsiz - s,
501 "pages", "count", "credits", "min");
502 LASSERT (tmpstr + tmpsiz - s > 0);
506 for (idx = 0; idx < LNET_NRBPOOLS; idx++) {
507 lnet_rtrbufpool_t *rbp = &the_lnet.ln_rtrpools[idx];
509 int npages = rbp->rbp_npages;
510 int nbuf = rbp->rbp_nbuffers;
511 int cr = rbp->rbp_credits;
512 int mincr = rbp->rbp_mincredits;
514 s += snprintf(s, tmpstr + tmpsiz - s,
516 npages, nbuf, cr, mincr);
517 LASSERT (tmpstr + tmpsiz - s > 0);
524 if (pos >= min_t(int, len, strlen(tmpstr)))
527 rc = trace_copyout_string(buffer, nob,
530 LIBCFS_FREE(tmpstr, tmpsiz);
534 DECLARE_PROC_HANDLER(proc_lnet_buffers);
536 int LL_PROC_PROTO(proc_lnet_nis)
541 const int tmpsiz = 256;
544 DECLARE_LL_PROC_PPOS_DECL;
551 LIBCFS_ALLOC(tmpstr, tmpsiz);
555 s = tmpstr; /* points to current position in tmpstr[] */
558 s += snprintf(s, tmpstr + tmpsiz - s,
559 "%-24s %6s %5s %4s %4s %4s %5s %5s %5s\n",
560 "nid", "status", "alive", "refs", "peer",
561 "rtr", "max", "tx", "min");
562 LASSERT (tmpstr + tmpsiz - s > 0);
565 lnet_ni_t *ni = NULL;
566 int skip = *ppos - 1;
570 n = the_lnet.ln_nis.next;
572 while (n != &the_lnet.ln_nis) {
573 lnet_ni_t *a_ni = list_entry(n, lnet_ni_t, ni_list);
585 cfs_time_t now = cfs_time_current();
587 int maxtxcr = ni->ni_maxtxcredits;
588 int txcr = ni->ni_txcredits;
589 int mintxcr = ni->ni_mintxcredits;
590 int npeertxcr = ni->ni_peertxcredits;
591 int npeerrtrcr = ni->ni_peerrtrcredits;
592 lnet_nid_t nid = ni->ni_nid;
593 int nref = ni->ni_refcount;
596 if (the_lnet.ln_routing)
597 last_alive = cfs_duration_sec(cfs_time_sub(now,
599 if (ni->ni_lnd->lnd_type == LOLND) /* @lo forever alive */
602 LASSERT (ni->ni_status != NULL);
603 stat = (ni->ni_status->ns_status == LNET_NI_STATUS_UP) ?
606 s += snprintf(s, tmpstr + tmpsiz - s,
607 "%-24s %6s %5d %4d %4d %4d %5d %5d %5d\n",
608 libcfs_nid2str(nid), stat, last_alive, nref,
609 npeertxcr, npeerrtrcr, maxtxcr,
611 LASSERT (tmpstr + tmpsiz - s > 0);
617 len = s - tmpstr; /* how many bytes was written */
619 if (len > *lenp) { /* linux-supplied buffer is too small */
621 } else if (len > 0) { /* wrote something */
622 if (copy_to_user(buffer, tmpstr, len))
628 LIBCFS_FREE(tmpstr, tmpsiz);
636 static cfs_sysctl_table_t lnet_table[] = {
638 * NB No .strategy entries have been provided since sysctl(8) prefers
639 * to go via /proc for portability.
642 .ctl_name = PSDEV_LNET_STATS,
645 .proc_handler = &proc_lnet_stats,
648 .ctl_name = PSDEV_LNET_ROUTES,
649 .procname = "routes",
651 .proc_handler = &proc_lnet_routes,
654 .ctl_name = PSDEV_LNET_ROUTERS,
655 .procname = "routers",
657 .proc_handler = &proc_lnet_routers,
660 .ctl_name = PSDEV_LNET_PEERS,
663 .proc_handler = &proc_lnet_peers,
666 .ctl_name = PSDEV_LNET_PEERS,
667 .procname = "buffers",
669 .proc_handler = &proc_lnet_buffers,
672 .ctl_name = PSDEV_LNET_NIS,
675 .proc_handler = &proc_lnet_nis,
680 static cfs_sysctl_table_t top_table[] = {
682 .ctl_name = CTL_LNET,
698 if (lnet_table_header == NULL)
699 lnet_table_header = cfs_register_sysctl_table(top_table, 0);
707 if (lnet_table_header != NULL)
708 cfs_unregister_sysctl_table(lnet_table_header);
710 lnet_table_header = NULL;