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 = cfs_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 = cfs_list_entry(n, lnet_remotenet_t, lrn_list);
163 r = rnet->lrn_routes.next;
165 while (r != &rnet->lrn_routes) {
167 cfs_list_entry(r, lnet_route_t,
182 __u32 net = rnet->lrn_net;
183 unsigned int hops = route->lr_hops;
184 lnet_nid_t nid = route->lr_gateway->lp_nid;
185 int alive = route->lr_gateway->lp_alive;
187 s += snprintf(s, tmpstr + tmpsiz - s, "%-8s %4u %7s %s\n",
188 libcfs_net2str(net), hops,
189 alive ? "up" : "down", libcfs_nid2str(nid));
190 LASSERT (tmpstr + tmpsiz - s > 0);
196 len = s - tmpstr; /* how many bytes was written */
198 if (len > *lenp) { /* linux-supplied buffer is too small */
200 } else if (len > 0) { /* wrote something */
201 if (cfs_copy_to_user(buffer, tmpstr, len))
207 LIBCFS_FREE(tmpstr, tmpsiz);
215 int LL_PROC_PROTO(proc_lnet_routers)
220 const int tmpsiz = 256;
222 int *ver_p = (unsigned int *)(&filp->private_data);
224 DECLARE_LL_PROC_PPOS_DECL;
231 LIBCFS_ALLOC(tmpstr, tmpsiz);
235 s = tmpstr; /* points to current position in tmpstr[] */
238 s += snprintf(s, tmpstr + tmpsiz - s,
239 "%-4s %7s %9s %6s %12s %9s %8s %7s %s\n",
240 "ref", "rtr_ref", "alive_cnt", "state", "last_ping",
241 "ping_sent", "deadline", "down_ni", "router");
242 LASSERT (tmpstr + tmpsiz - s > 0);
245 *ver_p = (unsigned int)the_lnet.ln_routers_version;
249 lnet_peer_t *peer = NULL;
250 int skip = *ppos - 1;
254 if (*ver_p != (unsigned int)the_lnet.ln_routers_version) {
256 LIBCFS_FREE(tmpstr, tmpsiz);
260 r = the_lnet.ln_routers.next;
262 while (r != &the_lnet.ln_routers) {
263 lnet_peer_t *lp = cfs_list_entry(r, lnet_peer_t,
276 lnet_nid_t nid = peer->lp_nid;
277 cfs_time_t now = cfs_time_current();
278 cfs_time_t deadline = peer->lp_ping_deadline;
279 int nrefs = peer->lp_refcount;
280 int nrtrrefs = peer->lp_rtr_refcount;
281 int alive_cnt = peer->lp_alive_count;
282 int alive = peer->lp_alive;
283 int pingsent = !peer->lp_ping_notsent;
284 int last_ping = cfs_duration_sec(cfs_time_sub(now,
285 peer->lp_ping_timestamp));
286 int down_ni = lnet_router_down_ni(peer,
287 LNET_NIDNET(LNET_NID_ANY));
290 s += snprintf(s, tmpstr + tmpsiz - s,
291 "%-4d %7d %9d %6s %12d %9d %8s %7d %s\n",
292 nrefs, nrtrrefs, alive_cnt,
293 alive ? "up" : "down", last_ping,
294 pingsent, "NA", down_ni,
295 libcfs_nid2str(nid));
297 s += snprintf(s, tmpstr + tmpsiz - s,
298 "%-4d %7d %9d %6s %12d %9d %8lu %7d %s\n",
299 nrefs, nrtrrefs, alive_cnt,
300 alive ? "up" : "down", last_ping,
302 cfs_duration_sec(cfs_time_sub(deadline, now)),
303 down_ni, libcfs_nid2str(nid));
304 LASSERT (tmpstr + tmpsiz - s > 0);
310 len = s - tmpstr; /* how many bytes was written */
312 if (len > *lenp) { /* linux-supplied buffer is too small */
314 } else if (len > 0) { /* wrote something */
315 if (cfs_copy_to_user(buffer, tmpstr, len))
321 LIBCFS_FREE(tmpstr, tmpsiz);
330 * NB: we don't use the highest bit of *ppos because it's signed;
331 * next 9 bits is used to stash idx (assuming that
332 * LNET_PEER_HASHSIZE < 512)
334 #define LNET_LOFFT_BITS (sizeof(loff_t) * 8)
335 #define LNET_PHASH_BITS 9
336 #define LNET_PHASH_IDX_MASK (((1ULL << LNET_PHASH_BITS) - 1) << \
337 (LNET_LOFFT_BITS - LNET_PHASH_BITS - 1))
338 #define LNET_PHASH_NUM_MASK ((1ULL << \
339 (LNET_LOFFT_BITS - LNET_PHASH_BITS -1)) - 1)
340 #define LNET_PHASH_IDX_GET(pos) (int)(((pos) & LNET_PHASH_IDX_MASK) >> \
341 (LNET_LOFFT_BITS - LNET_PHASH_BITS -1))
342 #define LNET_PHASH_NUM_GET(pos) (int)((pos) & LNET_PHASH_NUM_MASK)
343 #define LNET_PHASH_POS_MAKE(idx, num) ((((loff_t)idx) << (LNET_LOFFT_BITS - \
344 LNET_PHASH_BITS -1)) | (num))
346 int LL_PROC_PROTO(proc_lnet_peers)
351 const int tmpsiz = 256;
353 int *ver_p = (unsigned int *)(&filp->private_data);
357 DECLARE_LL_PROC_PPOS_DECL;
359 idx = LNET_PHASH_IDX_GET(*ppos);
360 num = LNET_PHASH_NUM_GET(*ppos);
362 CLASSERT ((1 << LNET_PHASH_BITS) > LNET_PEER_HASHSIZE);
369 LIBCFS_ALLOC(tmpstr, tmpsiz);
373 s = tmpstr; /* points to current position in tmpstr[] */
376 s += snprintf(s, tmpstr + tmpsiz - s,
377 "%-24s %4s %5s %5s %5s %5s %5s %5s %s\n",
378 "nid", "refs", "state", "max",
379 "rtr", "min", "tx", "min", "queue");
380 LASSERT (tmpstr + tmpsiz - s > 0);
383 *ver_p = (unsigned int)the_lnet.ln_peertable_version;
388 cfs_list_t *p = NULL;
389 lnet_peer_t *peer = NULL;
394 if (*ver_p != (unsigned int)the_lnet.ln_peertable_version) {
396 LIBCFS_FREE(tmpstr, tmpsiz);
400 while (idx < LNET_PEER_HASHSIZE) {
402 p = the_lnet.ln_peer_hash[idx].next;
404 while (p != &the_lnet.ln_peer_hash[idx]) {
405 lnet_peer_t *lp = cfs_list_entry(p, lnet_peer_t,
410 /* minor optimiztion: start from idx+1
411 * on next iteration if we've just
412 * drained lp_hashlist */
413 if (lp->lp_hashlist.next ==
414 &the_lnet.ln_peer_hash[idx]) {
425 p = lp->lp_hashlist.next;
437 lnet_nid_t nid = peer->lp_nid;
438 int nrefs = peer->lp_refcount;
439 char *aliveness = "NA";
440 int maxcr = peer->lp_ni->ni_peertxcredits;
441 int txcr = peer->lp_txcredits;
442 int mintxcr = peer->lp_mintxcredits;
443 int rtrcr = peer->lp_rtrcredits;
444 int minrtrcr = peer->lp_minrtrcredits;
445 int txqnob = peer->lp_txqnob;
447 if (lnet_isrouter(peer) ||
448 lnet_peer_aliveness_enabled(peer))
449 aliveness = peer->lp_alive ? "up" : "down";
451 s += snprintf(s, tmpstr + tmpsiz - s,
452 "%-24s %4d %5s %5d %5d %5d %5d %5d %d\n",
453 libcfs_nid2str(nid), nrefs, aliveness,
454 maxcr, rtrcr, minrtrcr, txcr,
456 LASSERT (tmpstr + tmpsiz - s > 0);
462 len = s - tmpstr; /* how many bytes was written */
464 if (len > *lenp) { /* linux-supplied buffer is too small */
466 } else if (len > 0) { /* wrote something */
467 if (cfs_copy_to_user(buffer, tmpstr, len))
470 *ppos = LNET_PHASH_POS_MAKE(idx, num);
473 LIBCFS_FREE(tmpstr, tmpsiz);
481 static int __proc_lnet_buffers(void *data, int write,
482 loff_t pos, void *buffer, int nob)
489 const int tmpsiz = 64 * (LNET_NRBPOOLS + 1); /* (4 %d) * 4 */
494 LIBCFS_ALLOC(tmpstr, tmpsiz);
498 s = tmpstr; /* points to current position in tmpstr[] */
500 s += snprintf(s, tmpstr + tmpsiz - s,
502 "pages", "count", "credits", "min");
503 LASSERT (tmpstr + tmpsiz - s > 0);
507 for (idx = 0; idx < LNET_NRBPOOLS; idx++) {
508 lnet_rtrbufpool_t *rbp = &the_lnet.ln_rtrpools[idx];
510 int npages = rbp->rbp_npages;
511 int nbuf = rbp->rbp_nbuffers;
512 int cr = rbp->rbp_credits;
513 int mincr = rbp->rbp_mincredits;
515 s += snprintf(s, tmpstr + tmpsiz - s,
517 npages, nbuf, cr, mincr);
518 LASSERT (tmpstr + tmpsiz - s > 0);
525 if (pos >= min_t(int, len, strlen(tmpstr)))
528 rc = cfs_trace_copyout_string(buffer, nob,
531 LIBCFS_FREE(tmpstr, tmpsiz);
535 DECLARE_PROC_HANDLER(proc_lnet_buffers);
537 int LL_PROC_PROTO(proc_lnet_nis)
542 const int tmpsiz = 256;
545 DECLARE_LL_PROC_PPOS_DECL;
552 LIBCFS_ALLOC(tmpstr, tmpsiz);
556 s = tmpstr; /* points to current position in tmpstr[] */
559 s += snprintf(s, tmpstr + tmpsiz - s,
560 "%-24s %6s %5s %4s %4s %4s %5s %5s %5s\n",
561 "nid", "status", "alive", "refs", "peer",
562 "rtr", "max", "tx", "min");
563 LASSERT (tmpstr + tmpsiz - s > 0);
566 lnet_ni_t *ni = NULL;
567 int skip = *ppos - 1;
571 n = the_lnet.ln_nis.next;
573 while (n != &the_lnet.ln_nis) {
574 lnet_ni_t *a_ni = cfs_list_entry(n, lnet_ni_t, ni_list);
586 cfs_time_t now = cfs_time_current();
588 int maxtxcr = ni->ni_maxtxcredits;
589 int txcr = ni->ni_txcredits;
590 int mintxcr = ni->ni_mintxcredits;
591 int npeertxcr = ni->ni_peertxcredits;
592 int npeerrtrcr = ni->ni_peerrtrcredits;
593 lnet_nid_t nid = ni->ni_nid;
594 int nref = ni->ni_refcount;
597 if (the_lnet.ln_routing)
598 last_alive = cfs_duration_sec(cfs_time_sub(now,
600 if (ni->ni_lnd->lnd_type == LOLND) /* @lo forever alive */
603 LASSERT (ni->ni_status != NULL);
604 stat = (ni->ni_status->ns_status == LNET_NI_STATUS_UP) ?
607 s += snprintf(s, tmpstr + tmpsiz - s,
608 "%-24s %6s %5d %4d %4d %4d %5d %5d %5d\n",
609 libcfs_nid2str(nid), stat, last_alive, nref,
610 npeertxcr, npeerrtrcr, maxtxcr,
612 LASSERT (tmpstr + tmpsiz - s > 0);
618 len = s - tmpstr; /* how many bytes was written */
620 if (len > *lenp) { /* linux-supplied buffer is too small */
622 } else if (len > 0) { /* wrote something */
623 if (cfs_copy_to_user(buffer, tmpstr, len))
629 LIBCFS_FREE(tmpstr, tmpsiz);
637 static cfs_sysctl_table_t lnet_table[] = {
639 * NB No .strategy entries have been provided since sysctl(8) prefers
640 * to go via /proc for portability.
643 .ctl_name = PSDEV_LNET_STATS,
646 .proc_handler = &proc_lnet_stats,
649 .ctl_name = PSDEV_LNET_ROUTES,
650 .procname = "routes",
652 .proc_handler = &proc_lnet_routes,
655 .ctl_name = PSDEV_LNET_ROUTERS,
656 .procname = "routers",
658 .proc_handler = &proc_lnet_routers,
661 .ctl_name = PSDEV_LNET_PEERS,
664 .proc_handler = &proc_lnet_peers,
667 .ctl_name = PSDEV_LNET_PEERS,
668 .procname = "buffers",
670 .proc_handler = &proc_lnet_buffers,
673 .ctl_name = PSDEV_LNET_NIS,
676 .proc_handler = &proc_lnet_nis,
681 static cfs_sysctl_table_t top_table[] = {
683 .ctl_name = CTL_LNET,
699 if (lnet_table_header == NULL)
700 lnet_table_header = cfs_register_sysctl_table(top_table, 0);
708 if (lnet_table_header != NULL)
709 cfs_unregister_sysctl_table(lnet_table_header);
711 lnet_table_header = NULL;