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