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