Merge remote-tracking branch 'regulator/topic/tps65910' into regulator-next
[deliverable/linux.git] / drivers / staging / lustre / lnet / lnet / router_proc.c
1 /*
2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3 *
4 * Copyright (c) 2011, 2012, Intel Corporation.
5 *
6 * This file is part of Portals
7 * http://sourceforge.net/projects/sandiaportals/
8 *
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.
12 *
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.
17 *
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.
21 *
22 */
23
24 #define DEBUG_SUBSYSTEM S_LNET
25 #include <linux/libcfs/libcfs.h>
26 #include <linux/lnet/lib-lnet.h>
27
28 #if defined(LNET_ROUTER)
29
30 /* This is really lnet_proc.c. You might need to update sanity test 215
31 * if any file format is changed. */
32
33 static ctl_table_header_t *lnet_table_header = NULL;
34
35 #define CTL_LNET (0x100)
36 enum {
37 PSDEV_LNET_STATS = 100,
38 PSDEV_LNET_ROUTES,
39 PSDEV_LNET_ROUTERS,
40 PSDEV_LNET_PEERS,
41 PSDEV_LNET_BUFFERS,
42 PSDEV_LNET_NIS,
43 PSDEV_LNET_PTL_ROTOR,
44 };
45
46 #define LNET_LOFFT_BITS (sizeof(loff_t) * 8)
47 /*
48 * NB: max allowed LNET_CPT_BITS is 8 on 64-bit system and 2 on 32-bit system
49 */
50 #define LNET_PROC_CPT_BITS (LNET_CPT_BITS + 1)
51 /* change version, 16 bits or 8 bits */
52 #define LNET_PROC_VER_BITS MAX(((MIN(LNET_LOFFT_BITS, 64)) / 4), 8)
53
54 #define LNET_PROC_HASH_BITS LNET_PEER_HASH_BITS
55 /*
56 * bits for peer hash offset
57 * NB: we don't use the highest bit of *ppos because it's signed
58 */
59 #define LNET_PROC_HOFF_BITS (LNET_LOFFT_BITS - \
60 LNET_PROC_CPT_BITS - \
61 LNET_PROC_VER_BITS - \
62 LNET_PROC_HASH_BITS - 1)
63 /* bits for hash index + position */
64 #define LNET_PROC_HPOS_BITS (LNET_PROC_HASH_BITS + LNET_PROC_HOFF_BITS)
65 /* bits for peer hash table + hash version */
66 #define LNET_PROC_VPOS_BITS (LNET_PROC_HPOS_BITS + LNET_PROC_VER_BITS)
67
68 #define LNET_PROC_CPT_MASK ((1ULL << LNET_PROC_CPT_BITS) - 1)
69 #define LNET_PROC_VER_MASK ((1ULL << LNET_PROC_VER_BITS) - 1)
70 #define LNET_PROC_HASH_MASK ((1ULL << LNET_PROC_HASH_BITS) - 1)
71 #define LNET_PROC_HOFF_MASK ((1ULL << LNET_PROC_HOFF_BITS) - 1)
72
73 #define LNET_PROC_CPT_GET(pos) \
74 (int)(((pos) >> LNET_PROC_VPOS_BITS) & LNET_PROC_CPT_MASK)
75
76 #define LNET_PROC_VER_GET(pos) \
77 (int)(((pos) >> LNET_PROC_HPOS_BITS) & LNET_PROC_VER_MASK)
78
79 #define LNET_PROC_HASH_GET(pos) \
80 (int)(((pos) >> LNET_PROC_HOFF_BITS) & LNET_PROC_HASH_MASK)
81
82 #define LNET_PROC_HOFF_GET(pos) \
83 (int)((pos) & LNET_PROC_HOFF_MASK)
84
85 #define LNET_PROC_POS_MAKE(cpt, ver, hash, off) \
86 (((((loff_t)(cpt)) & LNET_PROC_CPT_MASK) << LNET_PROC_VPOS_BITS) | \
87 ((((loff_t)(ver)) & LNET_PROC_VER_MASK) << LNET_PROC_HPOS_BITS) | \
88 ((((loff_t)(hash)) & LNET_PROC_HASH_MASK) << LNET_PROC_HOFF_BITS) | \
89 ((off) & LNET_PROC_HOFF_MASK))
90
91 #define LNET_PROC_VERSION(v) ((unsigned int)((v) & LNET_PROC_VER_MASK))
92
93 static int __proc_lnet_stats(void *data, int write,
94 loff_t pos, void *buffer, int nob)
95 {
96 int rc;
97 lnet_counters_t *ctrs;
98 int len;
99 char *tmpstr;
100 const int tmpsiz = 256; /* 7 %u and 4 LPU64 */
101
102 if (write) {
103 lnet_counters_reset();
104 return 0;
105 }
106
107 /* read */
108
109 LIBCFS_ALLOC(ctrs, sizeof(*ctrs));
110 if (ctrs == NULL)
111 return -ENOMEM;
112
113 LIBCFS_ALLOC(tmpstr, tmpsiz);
114 if (tmpstr == NULL) {
115 LIBCFS_FREE(ctrs, sizeof(*ctrs));
116 return -ENOMEM;
117 }
118
119 lnet_counters_get(ctrs);
120
121 len = snprintf(tmpstr, tmpsiz,
122 "%u %u %u %u %u %u %u "LPU64" "LPU64" "
123 LPU64" "LPU64,
124 ctrs->msgs_alloc, ctrs->msgs_max,
125 ctrs->errors,
126 ctrs->send_count, ctrs->recv_count,
127 ctrs->route_count, ctrs->drop_count,
128 ctrs->send_length, ctrs->recv_length,
129 ctrs->route_length, ctrs->drop_length);
130
131 if (pos >= min_t(int, len, strlen(tmpstr)))
132 rc = 0;
133 else
134 rc = cfs_trace_copyout_string(buffer, nob,
135 tmpstr + pos, "\n");
136
137 LIBCFS_FREE(tmpstr, tmpsiz);
138 LIBCFS_FREE(ctrs, sizeof(*ctrs));
139 return rc;
140 }
141
142 DECLARE_PROC_HANDLER(proc_lnet_stats);
143
144 int LL_PROC_PROTO(proc_lnet_routes)
145 {
146 const int tmpsiz = 256;
147 char *tmpstr;
148 char *s;
149 int rc = 0;
150 int len;
151 int ver;
152 int off;
153
154 DECLARE_LL_PROC_PPOS_DECL;
155
156 CLASSERT(sizeof(loff_t) >= 4);
157
158 off = LNET_PROC_HOFF_GET(*ppos);
159 ver = LNET_PROC_VER_GET(*ppos);
160
161 LASSERT (!write);
162
163 if (*lenp == 0)
164 return 0;
165
166 LIBCFS_ALLOC(tmpstr, tmpsiz);
167 if (tmpstr == NULL)
168 return -ENOMEM;
169
170 s = tmpstr; /* points to current position in tmpstr[] */
171
172 if (*ppos == 0) {
173 s += snprintf(s, tmpstr + tmpsiz - s, "Routing %s\n",
174 the_lnet.ln_routing ? "enabled" : "disabled");
175 LASSERT (tmpstr + tmpsiz - s > 0);
176
177 s += snprintf(s, tmpstr + tmpsiz - s, "%-8s %4s %7s %s\n",
178 "net", "hops", "state", "router");
179 LASSERT (tmpstr + tmpsiz - s > 0);
180
181 lnet_net_lock(0);
182 ver = (unsigned int)the_lnet.ln_remote_nets_version;
183 lnet_net_unlock(0);
184 *ppos = LNET_PROC_POS_MAKE(0, ver, 0, off);
185 } else {
186 struct list_head *n;
187 struct list_head *r;
188 lnet_route_t *route = NULL;
189 lnet_remotenet_t *rnet = NULL;
190 int skip = off - 1;
191 struct list_head *rn_list;
192 int i;
193
194 lnet_net_lock(0);
195
196 if (ver != LNET_PROC_VERSION(the_lnet.ln_remote_nets_version)) {
197 lnet_net_unlock(0);
198 LIBCFS_FREE(tmpstr, tmpsiz);
199 return -ESTALE;
200 }
201
202 for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE && route == NULL;
203 i++) {
204 rn_list = &the_lnet.ln_remote_nets_hash[i];
205
206 n = rn_list->next;
207
208 while (n != rn_list && route == NULL) {
209 rnet = list_entry(n, lnet_remotenet_t,
210 lrn_list);
211
212 r = rnet->lrn_routes.next;
213
214 while (r != &rnet->lrn_routes) {
215 lnet_route_t *re =
216 list_entry(r, lnet_route_t,
217 lr_list);
218 if (skip == 0) {
219 route = re;
220 break;
221 }
222
223 skip--;
224 r = r->next;
225 }
226
227 n = n->next;
228 }
229 }
230
231 if (route != NULL) {
232 __u32 net = rnet->lrn_net;
233 unsigned int hops = route->lr_hops;
234 lnet_nid_t nid = route->lr_gateway->lp_nid;
235 int alive = route->lr_gateway->lp_alive;
236
237 s += snprintf(s, tmpstr + tmpsiz - s,
238 "%-8s %4u %7s %s\n",
239 libcfs_net2str(net), hops,
240 alive ? "up" : "down",
241 libcfs_nid2str(nid));
242 LASSERT(tmpstr + tmpsiz - s > 0);
243 }
244
245 lnet_net_unlock(0);
246 }
247
248 len = s - tmpstr; /* how many bytes was written */
249
250 if (len > *lenp) { /* linux-supplied buffer is too small */
251 rc = -EINVAL;
252 } else if (len > 0) { /* wrote something */
253 if (copy_to_user(buffer, tmpstr, len))
254 rc = -EFAULT;
255 else {
256 off += 1;
257 *ppos = LNET_PROC_POS_MAKE(0, ver, 0, off);
258 }
259 }
260
261 LIBCFS_FREE(tmpstr, tmpsiz);
262
263 if (rc == 0)
264 *lenp = len;
265
266 return rc;
267 }
268
269 int LL_PROC_PROTO(proc_lnet_routers)
270 {
271 int rc = 0;
272 char *tmpstr;
273 char *s;
274 const int tmpsiz = 256;
275 int len;
276 int ver;
277 int off;
278
279 DECLARE_LL_PROC_PPOS_DECL;
280
281 off = LNET_PROC_HOFF_GET(*ppos);
282 ver = LNET_PROC_VER_GET(*ppos);
283
284 LASSERT (!write);
285
286 if (*lenp == 0)
287 return 0;
288
289 LIBCFS_ALLOC(tmpstr, tmpsiz);
290 if (tmpstr == NULL)
291 return -ENOMEM;
292
293 s = tmpstr; /* points to current position in tmpstr[] */
294
295 if (*ppos == 0) {
296 s += snprintf(s, tmpstr + tmpsiz - s,
297 "%-4s %7s %9s %6s %12s %9s %8s %7s %s\n",
298 "ref", "rtr_ref", "alive_cnt", "state",
299 "last_ping", "ping_sent", "deadline",
300 "down_ni", "router");
301 LASSERT(tmpstr + tmpsiz - s > 0);
302
303 lnet_net_lock(0);
304 ver = (unsigned int)the_lnet.ln_routers_version;
305 lnet_net_unlock(0);
306 *ppos = LNET_PROC_POS_MAKE(0, ver, 0, off);
307 } else {
308 struct list_head *r;
309 struct lnet_peer *peer = NULL;
310 int skip = off - 1;
311
312 lnet_net_lock(0);
313
314 if (ver != LNET_PROC_VERSION(the_lnet.ln_routers_version)) {
315 lnet_net_unlock(0);
316
317 LIBCFS_FREE(tmpstr, tmpsiz);
318 return -ESTALE;
319 }
320
321 r = the_lnet.ln_routers.next;
322
323 while (r != &the_lnet.ln_routers) {
324 lnet_peer_t *lp = list_entry(r, lnet_peer_t,
325 lp_rtr_list);
326
327 if (skip == 0) {
328 peer = lp;
329 break;
330 }
331
332 skip--;
333 r = r->next;
334 }
335
336 if (peer != NULL) {
337 lnet_nid_t nid = peer->lp_nid;
338 cfs_time_t now = cfs_time_current();
339 cfs_time_t deadline = peer->lp_ping_deadline;
340 int nrefs = peer->lp_refcount;
341 int nrtrrefs = peer->lp_rtr_refcount;
342 int alive_cnt = peer->lp_alive_count;
343 int alive = peer->lp_alive;
344 int pingsent = !peer->lp_ping_notsent;
345 int last_ping = cfs_duration_sec(cfs_time_sub(now,
346 peer->lp_ping_timestamp));
347 int down_ni = 0;
348 lnet_route_t *rtr;
349
350 if ((peer->lp_ping_feats &
351 LNET_PING_FEAT_NI_STATUS) != 0) {
352 list_for_each_entry(rtr, &peer->lp_routes,
353 lr_gwlist) {
354 /* downis on any route should be the
355 * number of downis on the gateway */
356 if (rtr->lr_downis != 0) {
357 down_ni = rtr->lr_downis;
358 break;
359 }
360 }
361 }
362
363 if (deadline == 0)
364 s += snprintf(s, tmpstr + tmpsiz - s,
365 "%-4d %7d %9d %6s %12d %9d %8s %7d %s\n",
366 nrefs, nrtrrefs, alive_cnt,
367 alive ? "up" : "down", last_ping,
368 pingsent, "NA", down_ni,
369 libcfs_nid2str(nid));
370 else
371 s += snprintf(s, tmpstr + tmpsiz - s,
372 "%-4d %7d %9d %6s %12d %9d %8lu %7d %s\n",
373 nrefs, nrtrrefs, alive_cnt,
374 alive ? "up" : "down", last_ping,
375 pingsent,
376 cfs_duration_sec(cfs_time_sub(deadline, now)),
377 down_ni, libcfs_nid2str(nid));
378 LASSERT (tmpstr + tmpsiz - s > 0);
379 }
380
381 lnet_net_unlock(0);
382 }
383
384 len = s - tmpstr; /* how many bytes was written */
385
386 if (len > *lenp) { /* linux-supplied buffer is too small */
387 rc = -EINVAL;
388 } else if (len > 0) { /* wrote something */
389 if (copy_to_user(buffer, tmpstr, len))
390 rc = -EFAULT;
391 else {
392 off += 1;
393 *ppos = LNET_PROC_POS_MAKE(0, ver, 0, off);
394 }
395 }
396
397 LIBCFS_FREE(tmpstr, tmpsiz);
398
399 if (rc == 0)
400 *lenp = len;
401
402 return rc;
403 }
404
405 int LL_PROC_PROTO(proc_lnet_peers)
406 {
407 const int tmpsiz = 256;
408 struct lnet_peer_table *ptable;
409 char *tmpstr;
410 char *s;
411 int cpt = LNET_PROC_CPT_GET(*ppos);
412 int ver = LNET_PROC_VER_GET(*ppos);
413 int hash = LNET_PROC_HASH_GET(*ppos);
414 int hoff = LNET_PROC_HOFF_GET(*ppos);
415 int rc = 0;
416 int len;
417
418 CLASSERT(LNET_PROC_HASH_BITS >= LNET_PEER_HASH_BITS);
419 LASSERT(!write);
420
421 if (*lenp == 0)
422 return 0;
423
424 if (cpt >= LNET_CPT_NUMBER) {
425 *lenp = 0;
426 return 0;
427 }
428
429 LIBCFS_ALLOC(tmpstr, tmpsiz);
430 if (tmpstr == NULL)
431 return -ENOMEM;
432
433 s = tmpstr; /* points to current position in tmpstr[] */
434
435 if (*ppos == 0) {
436 s += snprintf(s, tmpstr + tmpsiz - s,
437 "%-24s %4s %5s %5s %5s %5s %5s %5s %5s %s\n",
438 "nid", "refs", "state", "last", "max",
439 "rtr", "min", "tx", "min", "queue");
440 LASSERT (tmpstr + tmpsiz - s > 0);
441
442 hoff++;
443 } else {
444 struct lnet_peer *peer;
445 struct list_head *p;
446 int skip;
447 again:
448 p = NULL;
449 peer = NULL;
450 skip = hoff - 1;
451
452 lnet_net_lock(cpt);
453 ptable = the_lnet.ln_peer_tables[cpt];
454 if (hoff == 1)
455 ver = LNET_PROC_VERSION(ptable->pt_version);
456
457 if (ver != LNET_PROC_VERSION(ptable->pt_version)) {
458 lnet_net_unlock(cpt);
459 LIBCFS_FREE(tmpstr, tmpsiz);
460 return -ESTALE;
461 }
462
463 while (hash < LNET_PEER_HASH_SIZE) {
464 if (p == NULL)
465 p = ptable->pt_hash[hash].next;
466
467 while (p != &ptable->pt_hash[hash]) {
468 lnet_peer_t *lp = list_entry(p, lnet_peer_t,
469 lp_hashlist);
470 if (skip == 0) {
471 peer = lp;
472
473 /* minor optimization: start from idx+1
474 * on next iteration if we've just
475 * drained lp_hashlist */
476 if (lp->lp_hashlist.next ==
477 &ptable->pt_hash[hash]) {
478 hoff = 1;
479 hash++;
480 } else {
481 hoff++;
482 }
483
484 break;
485 }
486
487 skip--;
488 p = lp->lp_hashlist.next;
489 }
490
491 if (peer != NULL)
492 break;
493
494 p = NULL;
495 hoff = 1;
496 hash++;
497 }
498
499 if (peer != NULL) {
500 lnet_nid_t nid = peer->lp_nid;
501 int nrefs = peer->lp_refcount;
502 int lastalive = -1;
503 char *aliveness = "NA";
504 int maxcr = peer->lp_ni->ni_peertxcredits;
505 int txcr = peer->lp_txcredits;
506 int mintxcr = peer->lp_mintxcredits;
507 int rtrcr = peer->lp_rtrcredits;
508 int minrtrcr = peer->lp_minrtrcredits;
509 int txqnob = peer->lp_txqnob;
510
511 if (lnet_isrouter(peer) ||
512 lnet_peer_aliveness_enabled(peer))
513 aliveness = peer->lp_alive ? "up" : "down";
514
515 if (lnet_peer_aliveness_enabled(peer)) {
516 cfs_time_t now = cfs_time_current();
517 cfs_duration_t delta;
518
519 delta = cfs_time_sub(now, peer->lp_last_alive);
520 lastalive = cfs_duration_sec(delta);
521
522 /* No need to mess up peers contents with
523 * arbitrarily long integers - it suffices to
524 * know that lastalive is more than 10000s old
525 */
526 if (lastalive >= 10000)
527 lastalive = 9999;
528 }
529
530 lnet_net_unlock(cpt);
531
532 s += snprintf(s, tmpstr + tmpsiz - s,
533 "%-24s %4d %5s %5d %5d %5d %5d %5d %5d %d\n",
534 libcfs_nid2str(nid), nrefs, aliveness,
535 lastalive, maxcr, rtrcr, minrtrcr, txcr,
536 mintxcr, txqnob);
537 LASSERT (tmpstr + tmpsiz - s > 0);
538
539 } else { /* peer is NULL */
540 lnet_net_unlock(cpt);
541 }
542
543 if (hash == LNET_PEER_HASH_SIZE) {
544 cpt++;
545 hash = 0;
546 hoff = 1;
547 if (peer == NULL && cpt < LNET_CPT_NUMBER)
548 goto again;
549 }
550 }
551
552 len = s - tmpstr; /* how many bytes was written */
553
554 if (len > *lenp) { /* linux-supplied buffer is too small */
555 rc = -EINVAL;
556 } else if (len > 0) { /* wrote something */
557 if (copy_to_user(buffer, tmpstr, len))
558 rc = -EFAULT;
559 else
560 *ppos = LNET_PROC_POS_MAKE(cpt, ver, hash, hoff);
561 }
562
563 LIBCFS_FREE(tmpstr, tmpsiz);
564
565 if (rc == 0)
566 *lenp = len;
567
568 return rc;
569 }
570
571 static int __proc_lnet_buffers(void *data, int write,
572 loff_t pos, void *buffer, int nob)
573 {
574 char *s;
575 char *tmpstr;
576 int tmpsiz;
577 int idx;
578 int len;
579 int rc;
580 int i;
581
582 LASSERT(!write);
583
584 /* (4 %d) * 4 * LNET_CPT_NUMBER */
585 tmpsiz = 64 * (LNET_NRBPOOLS + 1) * LNET_CPT_NUMBER;
586 LIBCFS_ALLOC(tmpstr, tmpsiz);
587 if (tmpstr == NULL)
588 return -ENOMEM;
589
590 s = tmpstr; /* points to current position in tmpstr[] */
591
592 s += snprintf(s, tmpstr + tmpsiz - s,
593 "%5s %5s %7s %7s\n",
594 "pages", "count", "credits", "min");
595 LASSERT (tmpstr + tmpsiz - s > 0);
596
597 if (the_lnet.ln_rtrpools == NULL)
598 goto out; /* I'm not a router */
599
600 for (idx = 0; idx < LNET_NRBPOOLS; idx++) {
601 lnet_rtrbufpool_t *rbp;
602
603 lnet_net_lock(LNET_LOCK_EX);
604 cfs_percpt_for_each(rbp, i, the_lnet.ln_rtrpools) {
605 s += snprintf(s, tmpstr + tmpsiz - s,
606 "%5d %5d %7d %7d\n",
607 rbp[idx].rbp_npages,
608 rbp[idx].rbp_nbuffers,
609 rbp[idx].rbp_credits,
610 rbp[idx].rbp_mincredits);
611 LASSERT(tmpstr + tmpsiz - s > 0);
612 }
613 lnet_net_unlock(LNET_LOCK_EX);
614 }
615
616 out:
617 len = s - tmpstr;
618
619 if (pos >= min_t(int, len, strlen(tmpstr)))
620 rc = 0;
621 else
622 rc = cfs_trace_copyout_string(buffer, nob,
623 tmpstr + pos, NULL);
624
625 LIBCFS_FREE(tmpstr, tmpsiz);
626 return rc;
627 }
628
629 DECLARE_PROC_HANDLER(proc_lnet_buffers);
630
631 int LL_PROC_PROTO(proc_lnet_nis)
632 {
633 int tmpsiz = 128 * LNET_CPT_NUMBER;
634 int rc = 0;
635 char *tmpstr;
636 char *s;
637 int len;
638
639 DECLARE_LL_PROC_PPOS_DECL;
640
641 LASSERT (!write);
642
643 if (*lenp == 0)
644 return 0;
645
646 LIBCFS_ALLOC(tmpstr, tmpsiz);
647 if (tmpstr == NULL)
648 return -ENOMEM;
649
650 s = tmpstr; /* points to current position in tmpstr[] */
651
652 if (*ppos == 0) {
653 s += snprintf(s, tmpstr + tmpsiz - s,
654 "%-24s %6s %5s %4s %4s %4s %5s %5s %5s\n",
655 "nid", "status", "alive", "refs", "peer",
656 "rtr", "max", "tx", "min");
657 LASSERT (tmpstr + tmpsiz - s > 0);
658 } else {
659 struct list_head *n;
660 lnet_ni_t *ni = NULL;
661 int skip = *ppos - 1;
662
663 lnet_net_lock(0);
664
665 n = the_lnet.ln_nis.next;
666
667 while (n != &the_lnet.ln_nis) {
668 lnet_ni_t *a_ni = list_entry(n, lnet_ni_t, ni_list);
669
670 if (skip == 0) {
671 ni = a_ni;
672 break;
673 }
674
675 skip--;
676 n = n->next;
677 }
678
679 if (ni != NULL) {
680 struct lnet_tx_queue *tq;
681 char *stat;
682 long now = cfs_time_current_sec();
683 int last_alive = -1;
684 int i;
685 int j;
686
687 if (the_lnet.ln_routing)
688 last_alive = now - ni->ni_last_alive;
689
690 /* @lo forever alive */
691 if (ni->ni_lnd->lnd_type == LOLND)
692 last_alive = 0;
693
694 lnet_ni_lock(ni);
695 LASSERT(ni->ni_status != NULL);
696 stat = (ni->ni_status->ns_status ==
697 LNET_NI_STATUS_UP) ? "up" : "down";
698 lnet_ni_unlock(ni);
699
700 /* we actually output credits information for
701 * TX queue of each partition */
702 cfs_percpt_for_each(tq, i, ni->ni_tx_queues) {
703 for (j = 0; ni->ni_cpts != NULL &&
704 j < ni->ni_ncpts; j++) {
705 if (i == ni->ni_cpts[j])
706 break;
707 }
708
709 if (j == ni->ni_ncpts)
710 continue;
711
712 if (i != 0)
713 lnet_net_lock(i);
714
715 s += snprintf(s, tmpstr + tmpsiz - s,
716 "%-24s %6s %5d %4d %4d %4d %5d %5d %5d\n",
717 libcfs_nid2str(ni->ni_nid), stat,
718 last_alive, *ni->ni_refs[i],
719 ni->ni_peertxcredits,
720 ni->ni_peerrtrcredits,
721 tq->tq_credits_max,
722 tq->tq_credits, tq->tq_credits_min);
723 if (i != 0)
724 lnet_net_unlock(i);
725 }
726 LASSERT(tmpstr + tmpsiz - s > 0);
727 }
728
729 lnet_net_unlock(0);
730 }
731
732 len = s - tmpstr; /* how many bytes was written */
733
734 if (len > *lenp) { /* linux-supplied buffer is too small */
735 rc = -EINVAL;
736 } else if (len > 0) { /* wrote something */
737 if (copy_to_user(buffer, tmpstr, len))
738 rc = -EFAULT;
739 else
740 *ppos += 1;
741 }
742
743 LIBCFS_FREE(tmpstr, tmpsiz);
744
745 if (rc == 0)
746 *lenp = len;
747
748 return rc;
749 }
750
751 struct lnet_portal_rotors {
752 int pr_value;
753 const char *pr_name;
754 const char *pr_desc;
755 };
756
757 static struct lnet_portal_rotors portal_rotors[] = {
758 {
759 .pr_value = LNET_PTL_ROTOR_OFF,
760 .pr_name = "OFF",
761 .pr_desc = "Turn off message rotor for wildcard portals"
762 },
763 {
764 .pr_value = LNET_PTL_ROTOR_ON,
765 .pr_name = "ON",
766 .pr_desc = "round-robin dispatch all PUT messages for "
767 "wildcard portals"
768 },
769 {
770 .pr_value = LNET_PTL_ROTOR_RR_RT,
771 .pr_name = "RR_RT",
772 .pr_desc = "round-robin dispatch routed PUT message for "
773 "wildcard portals"
774 },
775 {
776 .pr_value = LNET_PTL_ROTOR_HASH_RT,
777 .pr_name = "HASH_RT",
778 .pr_desc = "dispatch routed PUT message by hashing source "
779 "NID for wildcard portals"
780 },
781 {
782 .pr_value = -1,
783 .pr_name = NULL,
784 .pr_desc = NULL
785 },
786 };
787
788 extern int portal_rotor;
789
790 static int __proc_lnet_portal_rotor(void *data, int write,
791 loff_t pos, void *buffer, int nob)
792 {
793 const int buf_len = 128;
794 char *buf;
795 char *tmp;
796 int rc;
797 int i;
798
799 LIBCFS_ALLOC(buf, buf_len);
800 if (buf == NULL)
801 return -ENOMEM;
802
803 if (!write) {
804 lnet_res_lock(0);
805
806 for (i = 0; portal_rotors[i].pr_value >= 0; i++) {
807 if (portal_rotors[i].pr_value == portal_rotor)
808 break;
809 }
810
811 LASSERT(portal_rotors[i].pr_value == portal_rotor);
812 lnet_res_unlock(0);
813
814 rc = snprintf(buf, buf_len,
815 "{\n\tportals: all\n"
816 "\trotor: %s\n\tdescription: %s\n}",
817 portal_rotors[i].pr_name,
818 portal_rotors[i].pr_desc);
819
820 if (pos >= min_t(int, rc, buf_len)) {
821 rc = 0;
822 } else {
823 rc = cfs_trace_copyout_string(buffer, nob,
824 buf + pos, "\n");
825 }
826 goto out;
827 }
828
829 rc = cfs_trace_copyin_string(buf, buf_len, buffer, nob);
830 if (rc < 0)
831 goto out;
832
833 tmp = cfs_trimwhite(buf);
834
835 rc = -EINVAL;
836 lnet_res_lock(0);
837 for (i = 0; portal_rotors[i].pr_name != NULL; i++) {
838 if (cfs_strncasecmp(portal_rotors[i].pr_name, tmp,
839 strlen(portal_rotors[i].pr_name)) == 0) {
840 portal_rotor = portal_rotors[i].pr_value;
841 rc = 0;
842 break;
843 }
844 }
845 lnet_res_unlock(0);
846 out:
847 LIBCFS_FREE(buf, buf_len);
848 return rc;
849 }
850 DECLARE_PROC_HANDLER(proc_lnet_portal_rotor);
851
852 static ctl_table_t lnet_table[] = {
853 /*
854 * NB No .strategy entries have been provided since sysctl(8) prefers
855 * to go via /proc for portability.
856 */
857 {
858 INIT_CTL_NAME(PSDEV_LNET_STATS)
859 .procname = "stats",
860 .mode = 0644,
861 .proc_handler = &proc_lnet_stats,
862 },
863 {
864 INIT_CTL_NAME(PSDEV_LNET_ROUTES)
865 .procname = "routes",
866 .mode = 0444,
867 .proc_handler = &proc_lnet_routes,
868 },
869 {
870 INIT_CTL_NAME(PSDEV_LNET_ROUTERS)
871 .procname = "routers",
872 .mode = 0444,
873 .proc_handler = &proc_lnet_routers,
874 },
875 {
876 INIT_CTL_NAME(PSDEV_LNET_PEERS)
877 .procname = "peers",
878 .mode = 0444,
879 .proc_handler = &proc_lnet_peers,
880 },
881 {
882 INIT_CTL_NAME(PSDEV_LNET_PEERS)
883 .procname = "buffers",
884 .mode = 0444,
885 .proc_handler = &proc_lnet_buffers,
886 },
887 {
888 INIT_CTL_NAME(PSDEV_LNET_NIS)
889 .procname = "nis",
890 .mode = 0444,
891 .proc_handler = &proc_lnet_nis,
892 },
893 {
894 INIT_CTL_NAME(PSDEV_LNET_PTL_ROTOR)
895 .procname = "portal_rotor",
896 .mode = 0644,
897 .proc_handler = &proc_lnet_portal_rotor,
898 },
899 {
900 INIT_CTL_NAME(0)
901 }
902 };
903
904 static ctl_table_t top_table[] = {
905 {
906 INIT_CTL_NAME(CTL_LNET)
907 .procname = "lnet",
908 .mode = 0555,
909 .data = NULL,
910 .maxlen = 0,
911 .child = lnet_table,
912 },
913 {
914 INIT_CTL_NAME(0)
915 }
916 };
917
918 void
919 lnet_proc_init(void)
920 {
921 #ifdef CONFIG_SYSCTL
922 if (lnet_table_header == NULL)
923 lnet_table_header = register_sysctl_table(top_table);
924 #endif
925 }
926
927 void
928 lnet_proc_fini(void)
929 {
930 #ifdef CONFIG_SYSCTL
931 if (lnet_table_header != NULL)
932 unregister_sysctl_table(lnet_table_header);
933
934 lnet_table_header = NULL;
935 #endif
936 }
937
938 #else
939
940 void
941 lnet_proc_init(void)
942 {
943 }
944
945 void
946 lnet_proc_fini(void)
947 {
948 }
949
950 #endif
This page took 0.050364 seconds and 5 git commands to generate.