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 = rnet->lrn_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 %s\n",
239 "ref", "rtr_ref", "alive_cnt", "state",
240 "last_ping", "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 int nrefs = peer->lp_refcount;
276 int nrtrrefs = peer->lp_rtr_refcount;
277 int alive_cnt = peer->lp_alive_count;
278 int alive = peer->lp_alive;
279 time_t last_ping = peer->lp_ping_timestamp;
280 lnet_nid_t nid = peer->lp_nid;
282 s += snprintf(s, tmpstr + tmpsiz - s,
283 "%-4d %7d %9d %6s %12lu %s\n",
285 alive_cnt, alive ? "up" : "down",
286 last_ping, libcfs_nid2str(nid));
287 LASSERT (tmpstr + tmpsiz - s > 0);
293 len = s - tmpstr; /* how many bytes was written */
295 if (len > *lenp) { /* linux-supplied buffer is too small */
297 } else if (len > 0) { /* wrote something */
298 if (copy_to_user(buffer, tmpstr, len))
304 LIBCFS_FREE(tmpstr, tmpsiz);
313 * NB: we don't use the highest bit of *ppos because it's signed;
314 * next 9 bits is used to stash idx (assuming that
315 * LNET_PEER_HASHSIZE < 512)
317 #define LNET_LOFFT_BITS (sizeof(loff_t) * 8)
318 #define LNET_PHASH_BITS 9
319 #define LNET_PHASH_IDX_MASK (((1ULL << LNET_PHASH_BITS) - 1) << \
320 (LNET_LOFFT_BITS - LNET_PHASH_BITS - 1))
321 #define LNET_PHASH_NUM_MASK ((1ULL << \
322 (LNET_LOFFT_BITS - LNET_PHASH_BITS -1)) - 1)
323 #define LNET_PHASH_IDX_GET(pos) (int)(((pos) & LNET_PHASH_IDX_MASK) >> \
324 (LNET_LOFFT_BITS - LNET_PHASH_BITS -1))
325 #define LNET_PHASH_NUM_GET(pos) (int)((pos) & LNET_PHASH_NUM_MASK)
326 #define LNET_PHASH_POS_MAKE(idx, num) ((((loff_t)idx) << (LNET_LOFFT_BITS - \
327 LNET_PHASH_BITS -1)) | (num))
329 int LL_PROC_PROTO(proc_lnet_peers)
334 const int tmpsiz = 256;
336 int *ver_p = (unsigned int *)(&filp->private_data);
340 DECLARE_LL_PROC_PPOS_DECL;
342 idx = LNET_PHASH_IDX_GET(*ppos);
343 num = LNET_PHASH_NUM_GET(*ppos);
345 CLASSERT ((1 << LNET_PHASH_BITS) > LNET_PEER_HASHSIZE);
352 LIBCFS_ALLOC(tmpstr, tmpsiz);
356 s = tmpstr; /* points to current position in tmpstr[] */
359 s += snprintf(s, tmpstr + tmpsiz - s,
360 "%-24s %4s %5s %5s %5s %5s %5s %5s %s\n",
361 "nid", "refs", "state", "max",
362 "rtr", "min", "tx", "min", "queue");
363 LASSERT (tmpstr + tmpsiz - s > 0);
366 *ver_p = (unsigned int)the_lnet.ln_peertable_version;
371 struct list_head *p = NULL;
372 lnet_peer_t *peer = NULL;
377 if (*ver_p != (unsigned int)the_lnet.ln_peertable_version) {
379 LIBCFS_FREE(tmpstr, tmpsiz);
383 while (idx < LNET_PEER_HASHSIZE) {
385 p = the_lnet.ln_peer_hash[idx].next;
387 while (p != &the_lnet.ln_peer_hash[idx]) {
388 lnet_peer_t *lp = list_entry(p, lnet_peer_t,
393 /* minor optimiztion: start from idx+1
394 * on next iteration if we've just
395 * drained lp_hashlist */
396 if (lp->lp_hashlist.next ==
397 &the_lnet.ln_peer_hash[idx]) {
407 p = lp->lp_hashlist.next;
419 lnet_nid_t nid = peer->lp_nid;
420 int nrefs = peer->lp_refcount;
421 char *aliveness = "NA";
422 int maxcr = peer->lp_ni->ni_peertxcredits;
423 int txcr = peer->lp_txcredits;
424 int mintxcr = peer->lp_mintxcredits;
425 int rtrcr = peer->lp_rtrcredits;
426 int minrtrcr = peer->lp_minrtrcredits;
427 int txqnob = peer->lp_txqnob;
429 if (lnet_isrouter(peer) ||
430 peer->lp_ni->ni_peertimeout > 0)
431 aliveness = peer->lp_alive ? "up" : "down";
433 s += snprintf(s, tmpstr + tmpsiz - s,
434 "%-24s %4d %5s %5d %5d %5d %5d %5d %d\n",
435 libcfs_nid2str(nid), nrefs, aliveness,
436 maxcr, rtrcr, minrtrcr, txcr,
438 LASSERT (tmpstr + tmpsiz - s > 0);
444 len = s - tmpstr; /* how many bytes was written */
446 if (len > *lenp) { /* linux-supplied buffer is too small */
448 } else if (len > 0) { /* wrote something */
449 if (copy_to_user(buffer, tmpstr, len))
452 *ppos = LNET_PHASH_POS_MAKE(idx, num);
455 LIBCFS_FREE(tmpstr, tmpsiz);
463 static int __proc_lnet_buffers(void *data, int write,
464 loff_t pos, void *buffer, int nob)
471 const int tmpsiz = 64 * (LNET_NRBPOOLS + 1); /* (4 %d) * 4 */
476 LIBCFS_ALLOC(tmpstr, tmpsiz);
480 s = tmpstr; /* points to current position in tmpstr[] */
482 s += snprintf(s, tmpstr + tmpsiz - s,
484 "pages", "count", "credits", "min");
485 LASSERT (tmpstr + tmpsiz - s > 0);
489 for (idx = 0; idx < LNET_NRBPOOLS; idx++) {
490 lnet_rtrbufpool_t *rbp = &the_lnet.ln_rtrpools[idx];
492 int npages = rbp->rbp_npages;
493 int nbuf = rbp->rbp_nbuffers;
494 int cr = rbp->rbp_credits;
495 int mincr = rbp->rbp_mincredits;
497 s += snprintf(s, tmpstr + tmpsiz - s,
499 npages, nbuf, cr, mincr);
500 LASSERT (tmpstr + tmpsiz - s > 0);
507 if (pos >= min_t(int, len, strlen(tmpstr)))
510 rc = trace_copyout_string(buffer, nob,
513 LIBCFS_FREE(tmpstr, tmpsiz);
517 DECLARE_PROC_HANDLER(proc_lnet_buffers);
519 int LL_PROC_PROTO(proc_lnet_nis)
524 const int tmpsiz = 256;
527 DECLARE_LL_PROC_PPOS_DECL;
534 LIBCFS_ALLOC(tmpstr, tmpsiz);
538 s = tmpstr; /* points to current position in tmpstr[] */
541 s += snprintf(s, tmpstr + tmpsiz - s,
542 "%-24s %4s %4s %4s %5s %5s %5s\n",
543 "nid", "refs", "peer", "rtr", "max",
545 LASSERT (tmpstr + tmpsiz - s > 0);
548 lnet_ni_t *ni = NULL;
549 int skip = *ppos - 1;
553 n = the_lnet.ln_nis.next;
555 while (n != &the_lnet.ln_nis) {
556 lnet_ni_t *a_ni = list_entry(n, lnet_ni_t, ni_list);
568 int maxtxcr = ni->ni_maxtxcredits;
569 int txcr = ni->ni_txcredits;
570 int mintxcr = ni->ni_mintxcredits;
571 int npeertxcr = ni->ni_peertxcredits;
572 int npeerrtrcr = ni->ni_peerrtrcredits;
573 lnet_nid_t nid = ni->ni_nid;
574 int nref = ni->ni_refcount;
576 s += snprintf(s, tmpstr + tmpsiz - s,
577 "%-24s %4d %4d %4d %5d %5d %5d\n",
578 libcfs_nid2str(nid), nref,
579 npeertxcr, npeerrtrcr, maxtxcr,
581 LASSERT (tmpstr + tmpsiz - s > 0);
587 len = s - tmpstr; /* how many bytes was written */
589 if (len > *lenp) { /* linux-supplied buffer is too small */
591 } else if (len > 0) { /* wrote something */
592 if (copy_to_user(buffer, tmpstr, len))
598 LIBCFS_FREE(tmpstr, tmpsiz);
606 static cfs_sysctl_table_t lnet_table[] = {
608 * NB No .strategy entries have been provided since sysctl(8) prefers
609 * to go via /proc for portability.
612 .ctl_name = PSDEV_LNET_STATS,
615 .proc_handler = &proc_lnet_stats,
618 .ctl_name = PSDEV_LNET_ROUTES,
619 .procname = "routes",
621 .proc_handler = &proc_lnet_routes,
624 .ctl_name = PSDEV_LNET_ROUTERS,
625 .procname = "routers",
627 .proc_handler = &proc_lnet_routers,
630 .ctl_name = PSDEV_LNET_PEERS,
633 .proc_handler = &proc_lnet_peers,
636 .ctl_name = PSDEV_LNET_PEERS,
637 .procname = "buffers",
639 .proc_handler = &proc_lnet_buffers,
642 .ctl_name = PSDEV_LNET_NIS,
645 .proc_handler = &proc_lnet_nis,
650 static cfs_sysctl_table_t top_table[] = {
652 .ctl_name = CTL_LNET,
668 if (lnet_table_header == NULL)
669 lnet_table_header = cfs_register_sysctl_table(top_table, 0);
677 if (lnet_table_header != NULL)
678 cfs_unregister_sysctl_table(lnet_table_header);
680 lnet_table_header = NULL;