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(now - peer->lp_ping_timestamp);
284 int down_ni = lnet_router_down_ni(peer, LNET_NIDNET(LNET_NID_ANY));
287 s += snprintf(s, tmpstr + tmpsiz - s,
288 "%-4d %7d %9d %6s %12d %9d %8s %7d %s\n",
289 nrefs, nrtrrefs, alive_cnt,
290 alive ? "up" : "down", last_ping,
291 pingsent, "NA", down_ni,
292 libcfs_nid2str(nid));
294 s += snprintf(s, tmpstr + tmpsiz - s,
295 "%-4d %7d %9d %6s %12d %9d %8lu %7d %s\n",
296 nrefs, nrtrrefs, alive_cnt,
297 alive ? "up" : "down", last_ping,
299 cfs_duration_sec(deadline - now),
300 down_ni, libcfs_nid2str(nid));
301 LASSERT (tmpstr + tmpsiz - s > 0);
307 len = s - tmpstr; /* how many bytes was written */
309 if (len > *lenp) { /* linux-supplied buffer is too small */
311 } else if (len > 0) { /* wrote something */
312 if (copy_to_user(buffer, tmpstr, len))
318 LIBCFS_FREE(tmpstr, tmpsiz);
327 * NB: we don't use the highest bit of *ppos because it's signed;
328 * next 9 bits is used to stash idx (assuming that
329 * LNET_PEER_HASHSIZE < 512)
331 #define LNET_LOFFT_BITS (sizeof(loff_t) * 8)
332 #define LNET_PHASH_BITS 9
333 #define LNET_PHASH_IDX_MASK (((1ULL << LNET_PHASH_BITS) - 1) << \
334 (LNET_LOFFT_BITS - LNET_PHASH_BITS - 1))
335 #define LNET_PHASH_NUM_MASK ((1ULL << \
336 (LNET_LOFFT_BITS - LNET_PHASH_BITS -1)) - 1)
337 #define LNET_PHASH_IDX_GET(pos) (int)(((pos) & LNET_PHASH_IDX_MASK) >> \
338 (LNET_LOFFT_BITS - LNET_PHASH_BITS -1))
339 #define LNET_PHASH_NUM_GET(pos) (int)((pos) & LNET_PHASH_NUM_MASK)
340 #define LNET_PHASH_POS_MAKE(idx, num) ((((loff_t)idx) << (LNET_LOFFT_BITS - \
341 LNET_PHASH_BITS -1)) | (num))
343 int LL_PROC_PROTO(proc_lnet_peers)
348 const int tmpsiz = 256;
350 int *ver_p = (unsigned int *)(&filp->private_data);
354 DECLARE_LL_PROC_PPOS_DECL;
356 idx = LNET_PHASH_IDX_GET(*ppos);
357 num = LNET_PHASH_NUM_GET(*ppos);
359 CLASSERT ((1 << LNET_PHASH_BITS) > LNET_PEER_HASHSIZE);
366 LIBCFS_ALLOC(tmpstr, tmpsiz);
370 s = tmpstr; /* points to current position in tmpstr[] */
373 s += snprintf(s, tmpstr + tmpsiz - s,
374 "%-24s %4s %5s %5s %5s %5s %5s %5s %s\n",
375 "nid", "refs", "state", "max",
376 "rtr", "min", "tx", "min", "queue");
377 LASSERT (tmpstr + tmpsiz - s > 0);
380 *ver_p = (unsigned int)the_lnet.ln_peertable_version;
385 struct list_head *p = NULL;
386 lnet_peer_t *peer = NULL;
391 if (*ver_p != (unsigned int)the_lnet.ln_peertable_version) {
393 LIBCFS_FREE(tmpstr, tmpsiz);
397 while (idx < LNET_PEER_HASHSIZE) {
399 p = the_lnet.ln_peer_hash[idx].next;
401 while (p != &the_lnet.ln_peer_hash[idx]) {
402 lnet_peer_t *lp = list_entry(p, lnet_peer_t,
407 /* minor optimiztion: start from idx+1
408 * on next iteration if we've just
409 * drained lp_hashlist */
410 if (lp->lp_hashlist.next ==
411 &the_lnet.ln_peer_hash[idx]) {
421 p = lp->lp_hashlist.next;
433 lnet_nid_t nid = peer->lp_nid;
434 int nrefs = peer->lp_refcount;
435 char *aliveness = "NA";
436 int maxcr = peer->lp_ni->ni_peertxcredits;
437 int txcr = peer->lp_txcredits;
438 int mintxcr = peer->lp_mintxcredits;
439 int rtrcr = peer->lp_rtrcredits;
440 int minrtrcr = peer->lp_minrtrcredits;
441 int txqnob = peer->lp_txqnob;
443 if (lnet_isrouter(peer) ||
444 peer->lp_ni->ni_peertimeout > 0)
445 aliveness = peer->lp_alive ? "up" : "down";
447 s += snprintf(s, tmpstr + tmpsiz - s,
448 "%-24s %4d %5s %5d %5d %5d %5d %5d %d\n",
449 libcfs_nid2str(nid), nrefs, aliveness,
450 maxcr, rtrcr, minrtrcr, txcr,
452 LASSERT (tmpstr + tmpsiz - s > 0);
458 len = s - tmpstr; /* how many bytes was written */
460 if (len > *lenp) { /* linux-supplied buffer is too small */
462 } else if (len > 0) { /* wrote something */
463 if (copy_to_user(buffer, tmpstr, len))
466 *ppos = LNET_PHASH_POS_MAKE(idx, num);
469 LIBCFS_FREE(tmpstr, tmpsiz);
477 static int __proc_lnet_buffers(void *data, int write,
478 loff_t pos, void *buffer, int nob)
485 const int tmpsiz = 64 * (LNET_NRBPOOLS + 1); /* (4 %d) * 4 */
490 LIBCFS_ALLOC(tmpstr, tmpsiz);
494 s = tmpstr; /* points to current position in tmpstr[] */
496 s += snprintf(s, tmpstr + tmpsiz - s,
498 "pages", "count", "credits", "min");
499 LASSERT (tmpstr + tmpsiz - s > 0);
503 for (idx = 0; idx < LNET_NRBPOOLS; idx++) {
504 lnet_rtrbufpool_t *rbp = &the_lnet.ln_rtrpools[idx];
506 int npages = rbp->rbp_npages;
507 int nbuf = rbp->rbp_nbuffers;
508 int cr = rbp->rbp_credits;
509 int mincr = rbp->rbp_mincredits;
511 s += snprintf(s, tmpstr + tmpsiz - s,
513 npages, nbuf, cr, mincr);
514 LASSERT (tmpstr + tmpsiz - s > 0);
521 if (pos >= min_t(int, len, strlen(tmpstr)))
524 rc = trace_copyout_string(buffer, nob,
527 LIBCFS_FREE(tmpstr, tmpsiz);
531 DECLARE_PROC_HANDLER(proc_lnet_buffers);
533 int LL_PROC_PROTO(proc_lnet_nis)
538 const int tmpsiz = 256;
541 DECLARE_LL_PROC_PPOS_DECL;
548 LIBCFS_ALLOC(tmpstr, tmpsiz);
552 s = tmpstr; /* points to current position in tmpstr[] */
555 s += snprintf(s, tmpstr + tmpsiz - s,
556 "%-24s %6s %5s %4s %4s %4s %5s %5s %5s\n",
557 "nid", "status", "alive", "refs", "peer",
558 "rtr", "max", "tx", "min");
559 LASSERT (tmpstr + tmpsiz - s > 0);
562 lnet_ni_t *ni = NULL;
563 int skip = *ppos - 1;
567 n = the_lnet.ln_nis.next;
569 while (n != &the_lnet.ln_nis) {
570 lnet_ni_t *a_ni = list_entry(n, lnet_ni_t, ni_list);
582 cfs_time_t now = cfs_time_current();
583 int maxtxcr = ni->ni_maxtxcredits;
584 int txcr = ni->ni_txcredits;
585 int mintxcr = ni->ni_mintxcredits;
586 int npeertxcr = ni->ni_peertxcredits;
587 int npeerrtrcr = ni->ni_peerrtrcredits;
588 lnet_nid_t nid = ni->ni_nid;
589 int nref = ni->ni_refcount;
593 last_alive = (the_lnet.ln_routing) ?
594 cfs_duration_sec(now - ni->ni_last_alive) : -1;
595 if (ni->ni_lnd->lnd_type == LOLND) /* @lo forever alive */
598 LASSERT (ni->ni_status != NULL);
599 stat = (ni->ni_status->ns_status == LNET_NI_STATUS_UP) ?
602 s += snprintf(s, tmpstr + tmpsiz - s,
603 "%-24s %6s %5d %4d %4d %4d %5d %5d %5d\n",
604 libcfs_nid2str(nid), stat, last_alive, nref,
605 npeertxcr, npeerrtrcr, maxtxcr,
607 LASSERT (tmpstr + tmpsiz - s > 0);
613 len = s - tmpstr; /* how many bytes was written */
615 if (len > *lenp) { /* linux-supplied buffer is too small */
617 } else if (len > 0) { /* wrote something */
618 if (copy_to_user(buffer, tmpstr, len))
624 LIBCFS_FREE(tmpstr, tmpsiz);
632 static cfs_sysctl_table_t lnet_table[] = {
634 * NB No .strategy entries have been provided since sysctl(8) prefers
635 * to go via /proc for portability.
638 .ctl_name = PSDEV_LNET_STATS,
641 .proc_handler = &proc_lnet_stats,
644 .ctl_name = PSDEV_LNET_ROUTES,
645 .procname = "routes",
647 .proc_handler = &proc_lnet_routes,
650 .ctl_name = PSDEV_LNET_ROUTERS,
651 .procname = "routers",
653 .proc_handler = &proc_lnet_routers,
656 .ctl_name = PSDEV_LNET_PEERS,
659 .proc_handler = &proc_lnet_peers,
662 .ctl_name = PSDEV_LNET_PEERS,
663 .procname = "buffers",
665 .proc_handler = &proc_lnet_buffers,
668 .ctl_name = PSDEV_LNET_NIS,
671 .proc_handler = &proc_lnet_nis,
676 static cfs_sysctl_table_t top_table[] = {
678 .ctl_name = CTL_LNET,
694 if (lnet_table_header == NULL)
695 lnet_table_header = cfs_register_sysctl_table(top_table, 0);
703 if (lnet_table_header != NULL)
704 cfs_unregister_sysctl_table(lnet_table_header);
706 lnet_table_header = NULL;