Whamcloud - gitweb
- fixed typo in a comment.
[fs/lustre-release.git] / lnet / lnet / router_proc.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2002 Cluster File Systems, Inc.
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 <libcfs/libcfs.h>
26 #include <lnet/lib-lnet.h>
27
28 #if defined(__KERNEL__) && defined(LNET_ROUTER)
29
30 #include <linux/seq_file.h>
31 #include <linux/lustre_compat25.h>
32
33 /* this is really lnet_proc.c */
34
35 #define LNET_PROC_STATS   "sys/lnet/stats"
36 #define LNET_PROC_ROUTES  "sys/lnet/routes"
37 #define LNET_PROC_ROUTERS "sys/lnet/routers"
38 #define LNET_PROC_PEERS   "sys/lnet/peers"
39 #define LNET_PROC_BUFFERS "sys/lnet/buffers"
40 #define LNET_PROC_NIS     "sys/lnet/nis"
41
42 static int
43 lnet_router_proc_stats_read (char *page, char **start, off_t off,
44                              int count, int *eof, void *data)
45 {
46         lnet_counters_t *ctrs;
47         int              rc;
48
49         *start = page;
50         *eof = 1;
51         if (off != 0)
52                 return 0;
53
54         LIBCFS_ALLOC(ctrs, sizeof(*ctrs));
55         if (ctrs == NULL)
56                 return -ENOMEM;
57
58         LNET_LOCK();
59         *ctrs = the_lnet.ln_counters;
60         LNET_UNLOCK();
61
62         rc = sprintf(page,
63                      "%u %u %u %u %u %u %u "LPU64" "LPU64" "LPU64" "LPU64"\n",
64                      ctrs->msgs_alloc, ctrs->msgs_max,
65                      ctrs->errors,
66                      ctrs->send_count, ctrs->recv_count,
67                      ctrs->route_count, ctrs->drop_count,
68                      ctrs->send_length, ctrs->recv_length,
69                      ctrs->route_length, ctrs->drop_length);
70
71         LIBCFS_FREE(ctrs, sizeof(*ctrs));
72         return rc;
73 }
74
75 static int
76 lnet_router_proc_stats_write(struct file *file, const char *ubuffer,
77                      unsigned long count, void *data)
78 {
79         LNET_LOCK();
80         memset(&the_lnet.ln_counters, 0, sizeof(the_lnet.ln_counters));
81         LNET_UNLOCK();
82
83         return (count);
84 }
85
86 typedef struct {
87         __u64                lrsi_version;
88         lnet_remotenet_t    *lrsi_net;
89         lnet_route_t        *lrsi_route;
90         loff_t               lrsi_off;
91 } lnet_route_seq_iterator_t;
92
93 int
94 lnet_route_seq_seek (lnet_route_seq_iterator_t *lrsi, loff_t off)
95 {
96         struct list_head  *n;
97         struct list_head  *r;
98         int                rc;
99         loff_t             here;
100
101         if (off == 0) {
102                 lrsi->lrsi_net = NULL;
103                 lrsi->lrsi_route = NULL;
104                 lrsi->lrsi_off = 0;
105                 return 0;
106         }
107
108         LNET_LOCK();
109
110         if (lrsi->lrsi_net != NULL &&
111             lrsi->lrsi_version != the_lnet.ln_remote_nets_version) {
112                 /* tables have changed */
113                 rc = -ESTALE;
114                 goto out;
115         }
116
117         if (lrsi->lrsi_net == NULL || lrsi->lrsi_off > off) {
118                 /* search from start */
119                 n = the_lnet.ln_remote_nets.next;
120                 r = NULL;
121                 here = 1;
122         } else {
123                 /* continue search */
124                 n = &lrsi->lrsi_net->lrn_list;
125                 r = &lrsi->lrsi_route->lr_list;
126                 here = lrsi->lrsi_off;
127         }
128
129         lrsi->lrsi_version = the_lnet.ln_remote_nets_version;
130         lrsi->lrsi_off        = off;
131
132         while (n != &the_lnet.ln_remote_nets) {
133                 lnet_remotenet_t *rnet =
134                         list_entry(n, lnet_remotenet_t, lrn_list);
135
136                 if (r == NULL)
137                         r = rnet->lrn_routes.next;
138
139                 while (r != &rnet->lrn_routes) {
140                         lnet_route_t *re =
141                                 list_entry(r, lnet_route_t,
142                                            lr_list);
143
144                         if (here == off) {
145                                 lrsi->lrsi_net = rnet;
146                                 lrsi->lrsi_route = re;
147                                 rc = 0;
148                                 goto out;
149                         }
150
151                         r = r->next;
152                         here++;
153                 }
154
155                 r = NULL;
156                 n = n->next;
157         }
158
159         lrsi->lrsi_net   = NULL;
160         lrsi->lrsi_route = NULL;
161         rc             = -ENOENT;
162  out:
163         LNET_UNLOCK();
164         return rc;
165 }
166
167 static void *
168 lnet_route_seq_start (struct seq_file *s, loff_t *pos)
169 {
170         lnet_route_seq_iterator_t *lrsi;
171         int                        rc;
172
173         LIBCFS_ALLOC(lrsi, sizeof(*lrsi));
174         if (lrsi == NULL)
175                 return NULL;
176
177         lrsi->lrsi_net = NULL;
178         rc = lnet_route_seq_seek(lrsi, *pos);
179         if (rc == 0)
180                 return lrsi;
181
182         LIBCFS_FREE(lrsi, sizeof(*lrsi));
183         return NULL;
184 }
185
186 static void
187 lnet_route_seq_stop (struct seq_file *s, void *iter)
188 {
189         lnet_route_seq_iterator_t  *lrsi = iter;
190
191         if (lrsi != NULL)
192                 LIBCFS_FREE(lrsi, sizeof(*lrsi));
193 }
194
195 static void *
196 lnet_route_seq_next (struct seq_file *s, void *iter, loff_t *pos)
197 {
198         lnet_route_seq_iterator_t *lrsi = iter;
199         int                        rc;
200         loff_t                     next = *pos + 1;
201
202         rc = lnet_route_seq_seek(lrsi, next);
203         if (rc != 0) {
204                 LIBCFS_FREE(lrsi, sizeof(*lrsi));
205                 return NULL;
206         }
207
208         *pos = next;
209         return lrsi;
210 }
211
212 static int
213 lnet_route_seq_show (struct seq_file *s, void *iter)
214 {
215         lnet_route_seq_iterator_t *lrsi = iter;
216         __u32                      net;
217         unsigned int               hops;
218         lnet_nid_t                 nid;
219         int                        alive;
220
221         if (lrsi->lrsi_off == 0) {
222                 seq_printf(s, "Routing %s\n",
223                            the_lnet.ln_routing ? "enabled" : "disabled");
224                 seq_printf(s, "%-8s %4s %7s %s\n",
225                            "net", "hops", "state", "router");
226                 return 0;
227         }
228
229         LASSERT (lrsi->lrsi_net != NULL);
230         LASSERT (lrsi->lrsi_route != NULL);
231
232         LNET_LOCK();
233
234         if (lrsi->lrsi_version != the_lnet.ln_remote_nets_version) {
235                 LNET_UNLOCK();
236                 return -ESTALE;
237         }
238
239         net   = lrsi->lrsi_net->lrn_net;
240         hops  = lrsi->lrsi_net->lrn_hops;
241         nid   = lrsi->lrsi_route->lr_gateway->lp_nid;
242         alive = lrsi->lrsi_route->lr_gateway->lp_alive;
243
244         LNET_UNLOCK();
245
246         seq_printf(s, "%-8s %4u %7s %s\n", libcfs_net2str(net), hops,
247                    alive ? "up" : "down", libcfs_nid2str(nid));
248         return 0;
249 }
250
251 static struct seq_operations lnet_routes_sops = {
252         .start = lnet_route_seq_start,
253         .stop  = lnet_route_seq_stop,
254         .next  = lnet_route_seq_next,
255         .show  = lnet_route_seq_show,
256 };
257
258 static int
259 lnet_route_seq_open(struct inode *inode, struct file *file)
260 {
261         struct proc_dir_entry *dp = PDE(inode);
262         struct seq_file       *sf;
263         int                    rc;
264
265         rc = seq_open(file, &lnet_routes_sops);
266         if (rc == 0) {
267                 sf = file->private_data;
268                 sf->private = dp->data;
269         }
270
271         return rc;
272 }
273
274 static struct file_operations lnet_routes_fops = {
275         .owner   = THIS_MODULE,
276         .open    = lnet_route_seq_open,
277         .read    = seq_read,
278         .llseek  = seq_lseek,
279         .release = seq_release,
280 };
281
282 typedef struct {
283         __u64                lrtrsi_version;
284         lnet_peer_t          *lrtrsi_router;
285         loff_t               lrtrsi_off;
286 } lnet_router_seq_iterator_t;
287
288 int
289 lnet_router_seq_seek (lnet_router_seq_iterator_t *lrtrsi, loff_t off)
290 {
291         struct list_head  *r;
292         lnet_peer_t       *lp;
293         int                rc;
294         loff_t             here;
295
296         if (off == 0) {
297                 lrtrsi->lrtrsi_router = NULL;
298                 lrtrsi->lrtrsi_off = 0;
299                 return 0;
300         }
301
302         LNET_LOCK();
303
304         lp = lrtrsi->lrtrsi_router;
305
306         if (lp != NULL &&
307             lrtrsi->lrtrsi_version != the_lnet.ln_routers_version) {
308                 /* tables have changed */
309                 rc = -ESTALE;
310                 goto out;
311         }
312
313         if (lp == NULL || lrtrsi->lrtrsi_off > off) {
314                 /* search from start */
315                 r = the_lnet.ln_routers.next;
316                 here = 1;
317         } else {
318                 /* continue search */
319                 r = &lp->lp_rtr_list;
320                 here = lrtrsi->lrtrsi_off;
321         }
322
323         lrtrsi->lrtrsi_version = the_lnet.ln_routers_version;
324         lrtrsi->lrtrsi_off        = off;
325
326         while (r != &the_lnet.ln_routers) {
327                 lnet_peer_t *rtr = list_entry(r, 
328                                               lnet_peer_t,
329                                               lp_rtr_list);
330
331                 if (here == off) {
332                         lrtrsi->lrtrsi_router = rtr;
333                         rc = 0;
334                         goto out;
335                 }
336
337                 r = r->next;
338                 here++;
339         }
340
341         lrtrsi->lrtrsi_router = NULL;
342         rc             = -ENOENT;
343  out:
344         LNET_UNLOCK();
345         return rc;
346 }
347
348 static void *
349 lnet_router_seq_start (struct seq_file *s, loff_t *pos)
350 {
351         lnet_router_seq_iterator_t *lrtrsi;
352         int                        rc;
353
354         LIBCFS_ALLOC(lrtrsi, sizeof(*lrtrsi));
355         if (lrtrsi == NULL)
356                 return NULL;
357
358         lrtrsi->lrtrsi_router = NULL;
359         rc = lnet_router_seq_seek(lrtrsi, *pos);
360         if (rc == 0)
361                 return lrtrsi;
362
363         LIBCFS_FREE(lrtrsi, sizeof(*lrtrsi));
364         return NULL;
365 }
366
367 static void
368 lnet_router_seq_stop (struct seq_file *s, void *iter)
369 {
370         lnet_router_seq_iterator_t  *lrtrsi = iter;
371
372         if (lrtrsi != NULL)
373                 LIBCFS_FREE(lrtrsi, sizeof(*lrtrsi));
374 }
375
376 static void *
377 lnet_router_seq_next (struct seq_file *s, void *iter, loff_t *pos)
378 {
379         lnet_router_seq_iterator_t *lrtrsi = iter;
380         int                        rc;
381         loff_t                     next = *pos + 1;
382
383         rc = lnet_router_seq_seek(lrtrsi, next);
384         if (rc != 0) {
385                 LIBCFS_FREE(lrtrsi, sizeof(*lrtrsi));
386                 return NULL;
387         }
388
389         *pos = next;
390         return lrtrsi;
391 }
392
393 static int
394 lnet_router_seq_show (struct seq_file *s, void *iter)
395 {
396         lnet_router_seq_iterator_t *lrtrsi = iter;
397         lnet_peer_t *lp;
398         lnet_nid_t  nid;
399         int         alive;
400         int         nrefs;
401         int         nrtrrefs;
402
403         if (lrtrsi->lrtrsi_off == 0) {
404                 seq_printf(s, "%-4s %7s %9s %6s %12s %s\n",
405                            "ref", "rtr_ref", "alive_cnt", "state", "last_ping", "router");
406                 return 0;
407         }
408
409         lp = lrtrsi->lrtrsi_router;
410         LASSERT (lp != NULL);
411
412         LNET_LOCK();
413
414         if (lrtrsi->lrtrsi_version != the_lnet.ln_routers_version) {
415                 LNET_UNLOCK();
416                 return -ESTALE;
417         }
418
419         nrefs = lp->lp_refcount;
420         nrtrrefs = lp->lp_rtr_refcount;
421         nid   = lp->lp_nid;
422         alive = lp->lp_alive;
423
424         LNET_UNLOCK();
425
426         seq_printf(s, 
427                    "%-4d %7d %9d %6s %12lu %s\n", 
428                    nrefs, nrtrrefs,
429                    lp->lp_alive_count,
430                    alive ? "up" : "down", 
431                    lp->lp_ping_timestamp,
432                    libcfs_nid2str(nid));
433         return 0;
434 }
435
436 static struct seq_operations lnet_routers_sops = {
437         .start = lnet_router_seq_start,
438         .stop  = lnet_router_seq_stop,
439         .next  = lnet_router_seq_next,
440         .show  = lnet_router_seq_show,
441 };
442
443 static int
444 lnet_router_seq_open(struct inode *inode, struct file *file)
445 {
446         struct proc_dir_entry *dp = PDE(inode);
447         struct seq_file       *sf;
448         int                    rc;
449
450         rc = seq_open(file, &lnet_routers_sops);
451         if (rc == 0) {
452                 sf = file->private_data;
453                 sf->private = dp->data;
454         }
455
456         return rc;
457 }
458
459 static struct file_operations lnet_routers_fops = {
460         .owner   = THIS_MODULE,
461         .open    = lnet_router_seq_open,
462         .read    = seq_read,
463         .llseek  = seq_lseek,
464         .release = seq_release,
465 };
466
467 typedef struct {
468         unsigned long long   lpsi_version;
469         int                  lpsi_idx;
470         lnet_peer_t         *lpsi_peer;
471         loff_t               lpsi_off;
472 } lnet_peer_seq_iterator_t;
473
474 int
475 lnet_peer_seq_seek (lnet_peer_seq_iterator_t *lpsi, loff_t off)
476 {
477         int                idx;
478         struct list_head  *p;
479         loff_t             here;
480         int                rc;
481
482         if (off == 0) {
483                 lpsi->lpsi_idx = 0;
484                 lpsi->lpsi_peer = NULL;
485                 lpsi->lpsi_off = 0;
486                 return 0;
487         }
488
489         LNET_LOCK();
490
491         if (lpsi->lpsi_peer != NULL &&
492             lpsi->lpsi_version != the_lnet.ln_peertable_version) {
493                 /* tables have changed */
494                 rc = -ESTALE;
495                 goto out;
496         }
497
498         if (lpsi->lpsi_peer == NULL ||
499             lpsi->lpsi_off > off) {
500                 /* search from start */
501                 idx = 0;
502                 p = NULL;
503                 here = 1;
504         } else {
505                 /* continue search */
506                 idx = lpsi->lpsi_idx;
507                 p = &lpsi->lpsi_peer->lp_hashlist;
508                 here = lpsi->lpsi_off;
509         }
510
511         lpsi->lpsi_version = the_lnet.ln_peertable_version;
512         lpsi->lpsi_off     = off;
513
514         while (idx < LNET_PEER_HASHSIZE) {
515                 if (p == NULL)
516                         p = the_lnet.ln_peer_hash[idx].next;
517
518                 while (p != &the_lnet.ln_peer_hash[idx]) {
519                         lnet_peer_t *lp = list_entry(p, lnet_peer_t,
520                                                      lp_hashlist);
521
522                         if (here == off) {
523                                 lpsi->lpsi_idx = idx;
524                                 lpsi->lpsi_peer = lp;
525                                 rc = 0;
526                                 goto out;
527                         }
528
529                         here++;
530                         p = lp->lp_hashlist.next;
531                 }
532
533                 p = NULL;
534                 idx++;
535         }
536
537         lpsi->lpsi_idx  = 0;
538         lpsi->lpsi_peer = NULL;
539         rc              = -ENOENT;
540  out:
541         LNET_UNLOCK();
542         return rc;
543 }
544
545 static void *
546 lnet_peer_seq_start (struct seq_file *s, loff_t *pos)
547 {
548         lnet_peer_seq_iterator_t *lpsi;
549         int                        rc;
550
551         LIBCFS_ALLOC(lpsi, sizeof(*lpsi));
552         if (lpsi == NULL)
553                 return NULL;
554
555         lpsi->lpsi_idx = 0;
556         lpsi->lpsi_peer = NULL;
557         rc = lnet_peer_seq_seek(lpsi, *pos);
558         if (rc == 0)
559                 return lpsi;
560
561         LIBCFS_FREE(lpsi, sizeof(*lpsi));
562         return NULL;
563 }
564
565 static void
566 lnet_peer_seq_stop (struct seq_file *s, void *iter)
567 {
568         lnet_peer_seq_iterator_t  *lpsi = iter;
569
570         if (lpsi != NULL)
571                 LIBCFS_FREE(lpsi, sizeof(*lpsi));
572 }
573
574 static void *
575 lnet_peer_seq_next (struct seq_file *s, void *iter, loff_t *pos)
576 {
577         lnet_peer_seq_iterator_t *lpsi = iter;
578         int                       rc;
579         loff_t                    next = *pos + 1;
580
581         rc = lnet_peer_seq_seek(lpsi, next);
582         if (rc != 0) {
583                 LIBCFS_FREE(lpsi, sizeof(*lpsi));
584                 return NULL;
585         }
586
587         *pos = next;
588         return lpsi;
589 }
590
591 static int
592 lnet_peer_seq_show (struct seq_file *s, void *iter)
593 {
594         lnet_peer_seq_iterator_t *lpsi = iter;
595         lnet_peer_t              *lp;
596         lnet_nid_t                nid;
597         int                       maxcr;
598         int                       mintxcr;
599         int                       txcr;
600         int                       minrtrcr;
601         int                       rtrcr;
602         int                       alive;
603         int                       rtr;
604         int                       txqnob;
605         int                       nrefs;
606
607         if (lpsi->lpsi_off == 0) {
608                 seq_printf(s, "%-24s %4s %5s %5s %5s %5s %5s %5s %s\n",
609                            "nid", "refs", "state", "max",
610                            "rtr", "min", "tx", "min", "queue");
611                 return 0;
612         }
613
614         LASSERT (lpsi->lpsi_peer != NULL);
615
616         LNET_LOCK();
617
618         if (lpsi->lpsi_version != the_lnet.ln_peertable_version) {
619                 LNET_UNLOCK();
620                 return -ESTALE;
621         }
622
623         lp = lpsi->lpsi_peer;
624
625         nid      = lp->lp_nid;
626         maxcr    = lp->lp_ni->ni_peertxcredits;
627         txcr     = lp->lp_txcredits;
628         mintxcr  = lp->lp_mintxcredits;
629         rtrcr    = lp->lp_rtrcredits;
630         minrtrcr = lp->lp_minrtrcredits;
631         rtr      = lnet_isrouter(lp);
632         alive    = lp->lp_alive;
633         txqnob   = lp->lp_txqnob;
634         nrefs    = lp->lp_refcount;
635
636         LNET_UNLOCK();
637
638         seq_printf(s, "%-24s %4d %5s %5d %5d %5d %5d %5d %d\n",
639                    libcfs_nid2str(nid), nrefs, 
640                    !rtr ? "~rtr" : (lp->lp_alive ? "up" : "down"),
641                    maxcr, rtrcr, minrtrcr, txcr, mintxcr, txqnob);
642         return 0;
643 }
644
645 static struct seq_operations lnet_peer_sops = {
646         .start = lnet_peer_seq_start,
647         .stop  = lnet_peer_seq_stop,
648         .next  = lnet_peer_seq_next,
649         .show  = lnet_peer_seq_show,
650 };
651
652 static int
653 lnet_peer_seq_open(struct inode *inode, struct file *file)
654 {
655         struct proc_dir_entry *dp = PDE(inode);
656         struct seq_file       *sf;
657         int                    rc;
658
659         rc = seq_open(file, &lnet_peer_sops);
660         if (rc == 0) {
661                 sf = file->private_data;
662                 sf->private = dp->data;
663         }
664
665         return rc;
666 }
667
668 static struct file_operations lnet_peer_fops = {
669         .owner   = THIS_MODULE,
670         .open    = lnet_peer_seq_open,
671         .read    = seq_read,
672         .llseek  = seq_lseek,
673         .release = seq_release,
674 };
675
676 typedef struct {
677         int                  lbsi_idx;
678         loff_t               lbsi_off;
679 } lnet_buffer_seq_iterator_t;
680
681 int
682 lnet_buffer_seq_seek (lnet_buffer_seq_iterator_t *lbsi, loff_t off)
683 {
684         int                idx;
685         loff_t             here;
686         int                rc;
687
688         if (off == 0) {
689                 lbsi->lbsi_idx = -1;
690                 lbsi->lbsi_off = 0;
691                 return 0;
692         }
693
694         LNET_LOCK();
695
696         if (lbsi->lbsi_idx < 0 ||
697             lbsi->lbsi_off > off) {
698                 /* search from start */
699                 idx = 0;
700                 here = 1;
701         } else {
702                 /* continue search */
703                 idx = lbsi->lbsi_idx;
704                 here = lbsi->lbsi_off;
705         }
706
707         lbsi->lbsi_off     = off;
708
709         while (idx < LNET_NRBPOOLS) {
710                 if (here == off) {
711                         lbsi->lbsi_idx = idx;
712                         rc = 0;
713                         goto out;
714                 }
715                 here++;
716                 idx++;
717         }
718
719         lbsi->lbsi_idx  = -1;
720         rc              = -ENOENT;
721  out:
722         LNET_UNLOCK();
723         return rc;
724 }
725
726 static void *
727 lnet_buffer_seq_start (struct seq_file *s, loff_t *pos)
728 {
729         lnet_buffer_seq_iterator_t *lbsi;
730         int                        rc;
731
732         LIBCFS_ALLOC(lbsi, sizeof(*lbsi));
733         if (lbsi == NULL)
734                 return NULL;
735
736         lbsi->lbsi_idx = -1;
737         rc = lnet_buffer_seq_seek(lbsi, *pos);
738         if (rc == 0)
739                 return lbsi;
740
741         LIBCFS_FREE(lbsi, sizeof(*lbsi));
742         return NULL;
743 }
744
745 static void
746 lnet_buffer_seq_stop (struct seq_file *s, void *iter)
747 {
748         lnet_buffer_seq_iterator_t  *lbsi = iter;
749
750         if (lbsi != NULL)
751                 LIBCFS_FREE(lbsi, sizeof(*lbsi));
752 }
753
754 static void *
755 lnet_buffer_seq_next (struct seq_file *s, void *iter, loff_t *pos)
756 {
757         lnet_buffer_seq_iterator_t *lbsi = iter;
758         int                         rc;
759         loff_t                      next = *pos + 1;
760
761         rc = lnet_buffer_seq_seek(lbsi, next);
762         if (rc != 0) {
763                 LIBCFS_FREE(lbsi, sizeof(*lbsi));
764                 return NULL;
765         }
766
767         *pos = next;
768         return lbsi;
769 }
770
771 static int
772 lnet_buffer_seq_show (struct seq_file *s, void *iter)
773 {
774         lnet_buffer_seq_iterator_t *lbsi = iter;
775         lnet_rtrbufpool_t          *rbp;
776         int                         npages;
777         int                         nbuf;
778         int                         cr;
779         int                         mincr;
780
781         if (lbsi->lbsi_off == 0) {
782                 seq_printf(s, "%5s %5s %7s %7s\n",
783                            "pages", "count", "credits", "min");
784                 return 0;
785         }
786
787         LASSERT (lbsi->lbsi_idx >= 0 && lbsi->lbsi_idx < LNET_NRBPOOLS);
788
789         LNET_LOCK();
790
791         rbp = &the_lnet.ln_rtrpools[lbsi->lbsi_idx];
792
793         npages = rbp->rbp_npages;
794         nbuf   = rbp->rbp_nbuffers;
795         cr     = rbp->rbp_credits;
796         mincr  = rbp->rbp_mincredits;
797
798         LNET_UNLOCK();
799
800         seq_printf(s, "%5d %5d %7d %7d\n",
801                    npages, nbuf, cr, mincr);
802         return 0;
803 }
804
805 static struct seq_operations lnet_buffer_sops = {
806         .start = lnet_buffer_seq_start,
807         .stop  = lnet_buffer_seq_stop,
808         .next  = lnet_buffer_seq_next,
809         .show  = lnet_buffer_seq_show,
810 };
811
812 static int
813 lnet_buffer_seq_open(struct inode *inode, struct file *file)
814 {
815         struct proc_dir_entry *dp = PDE(inode);
816         struct seq_file       *sf;
817         int                    rc;
818
819         rc = seq_open(file, &lnet_buffer_sops);
820         if (rc == 0) {
821                 sf = file->private_data;
822                 sf->private = dp->data;
823         }
824
825         return rc;
826 }
827
828 static struct file_operations lnet_buffers_fops = {
829         .owner   = THIS_MODULE,
830         .open    = lnet_buffer_seq_open,
831         .read    = seq_read,
832         .llseek  = seq_lseek,
833         .release = seq_release,
834 };
835
836 typedef struct {
837         lnet_ni_t           *lnsi_ni;
838         loff_t               lnsi_off;
839 } lnet_ni_seq_iterator_t;
840
841 int
842 lnet_ni_seq_seek (lnet_ni_seq_iterator_t *lnsi, loff_t off)
843 {
844         struct list_head  *n;
845         loff_t             here;
846         int                rc;
847
848         if (off == 0) {
849                 lnsi->lnsi_ni = NULL;
850                 lnsi->lnsi_off = 0;
851                 return 0;
852         }
853
854         LNET_LOCK();
855
856         if (lnsi->lnsi_ni == NULL ||
857             lnsi->lnsi_off > off) {
858                 /* search from start */
859                 n = NULL;
860                 here = 1;
861         } else {
862                 /* continue search */
863                 n = &lnsi->lnsi_ni->ni_list;
864                 here = lnsi->lnsi_off;
865         }
866
867         lnsi->lnsi_off = off;
868
869         if (n == NULL)
870                 n = the_lnet.ln_nis.next;
871
872         while (n != &the_lnet.ln_nis) {
873                 if (here == off) {
874                         lnsi->lnsi_ni = list_entry(n, lnet_ni_t, ni_list);
875                         rc = 0;
876                         goto out;
877                 }
878                 here++;
879                 n = n->next;
880         }
881
882         lnsi->lnsi_ni  = NULL;
883         rc             = -ENOENT;
884  out:
885         LNET_UNLOCK();
886         return rc;
887 }
888
889 static void *
890 lnet_ni_seq_start (struct seq_file *s, loff_t *pos)
891 {
892         lnet_ni_seq_iterator_t *lnsi;
893         int                     rc;
894
895         LIBCFS_ALLOC(lnsi, sizeof(*lnsi));
896         if (lnsi == NULL)
897                 return NULL;
898
899         lnsi->lnsi_ni = NULL;
900         rc = lnet_ni_seq_seek(lnsi, *pos);
901         if (rc == 0)
902                 return lnsi;
903
904         LIBCFS_FREE(lnsi, sizeof(*lnsi));
905         return NULL;
906 }
907
908 static void
909 lnet_ni_seq_stop (struct seq_file *s, void *iter)
910 {
911         lnet_ni_seq_iterator_t  *lnsi = iter;
912
913         if (lnsi != NULL)
914                 LIBCFS_FREE(lnsi, sizeof(*lnsi));
915 }
916
917 static void *
918 lnet_ni_seq_next (struct seq_file *s, void *iter, loff_t *pos)
919 {
920         lnet_ni_seq_iterator_t *lnsi = iter;
921         int                     rc;
922         loff_t                  next = *pos + 1;
923
924         rc = lnet_ni_seq_seek(lnsi, next);
925         if (rc != 0) {
926                 LIBCFS_FREE(lnsi, sizeof(*lnsi));
927                 return NULL;
928         }
929
930         *pos = next;
931         return lnsi;
932 }
933
934 static int
935 lnet_ni_seq_show (struct seq_file *s, void *iter)
936 {
937         lnet_ni_seq_iterator_t *lnsi = iter;
938         lnet_ni_t              *ni;
939         int                     maxtxcr;
940         int                     txcr;
941         int                     mintxcr;
942         int                     npeertxcr;
943         lnet_nid_t              nid;
944         int                     nref;
945
946         if (lnsi->lnsi_off == 0) {
947                 seq_printf(s, "%-24s %4s %4s %5s %5s %5s\n",
948                            "nid", "refs", "peer", "max", "tx", "min");
949                 return 0;
950         }
951
952         LASSERT (lnsi->lnsi_ni != NULL);
953
954         LNET_LOCK();
955
956         ni = lnsi->lnsi_ni;
957
958         maxtxcr   = ni->ni_maxtxcredits;
959         txcr      = ni->ni_txcredits;
960         mintxcr   = ni->ni_mintxcredits;
961         npeertxcr = ni->ni_peertxcredits;
962         nid       = ni->ni_nid;
963         nref      = ni->ni_refcount;
964
965         LNET_UNLOCK();
966
967         seq_printf(s, "%-24s %4d %4d %5d %5d %5d\n",
968                    libcfs_nid2str(nid), nref,
969                    npeertxcr, maxtxcr, txcr, mintxcr);
970         return 0;
971 }
972
973 static struct seq_operations lnet_ni_sops = {
974         .start = lnet_ni_seq_start,
975         .stop  = lnet_ni_seq_stop,
976         .next  = lnet_ni_seq_next,
977         .show  = lnet_ni_seq_show,
978 };
979
980 static int
981 lnet_ni_seq_open(struct inode *inode, struct file *file)
982 {
983         struct proc_dir_entry *dp = PDE(inode);
984         struct seq_file       *sf;
985         int                    rc;
986
987         rc = seq_open(file, &lnet_ni_sops);
988         if (rc == 0) {
989                 sf = file->private_data;
990                 sf->private = dp->data;
991         }
992
993         return rc;
994 }
995
996 static struct file_operations lnet_ni_fops = {
997         .owner   = THIS_MODULE,
998         .open    = lnet_ni_seq_open,
999         .read    = seq_read,
1000         .llseek  = seq_lseek,
1001         .release = seq_release,
1002 };
1003
1004 void
1005 lnet_proc_init(void)
1006 {
1007         struct proc_dir_entry *pde;
1008
1009         /* Initialize LNET_PROC_STATS */
1010         pde = create_proc_entry (LNET_PROC_STATS, 0644, NULL);
1011         if (pde == NULL) {
1012                 CERROR("couldn't create proc entry %s\n", LNET_PROC_STATS);
1013                 return;
1014         }
1015
1016         pde->data = NULL;
1017         pde->read_proc = lnet_router_proc_stats_read;
1018         pde->write_proc = lnet_router_proc_stats_write;
1019
1020         /* Initialize LNET_PROC_ROUTES */
1021         pde = create_proc_entry (LNET_PROC_ROUTES, 0444, NULL);
1022         if (pde == NULL) {
1023                 CERROR("couldn't create proc entry %s\n", LNET_PROC_ROUTES);
1024                 return;
1025         }
1026
1027         pde->proc_fops = &lnet_routes_fops;
1028         pde->data = NULL;
1029
1030         /* Initialize LNET_PROC_ROUTERS */
1031         pde = create_proc_entry (LNET_PROC_ROUTERS, 0444, NULL);
1032         if (pde == NULL) {
1033                 CERROR("couldn't create proc entry %s\n", LNET_PROC_ROUTERS);
1034                 return;
1035         }
1036
1037         pde->proc_fops = &lnet_routers_fops;
1038         pde->data = NULL;
1039
1040         /* Initialize LNET_PROC_PEERS */
1041         pde = create_proc_entry (LNET_PROC_PEERS, 0444, NULL);
1042         if (pde == NULL) {
1043                 CERROR("couldn't create proc entry %s\n", LNET_PROC_PEERS);
1044                 return;
1045         }
1046
1047         pde->proc_fops = &lnet_peer_fops;
1048         pde->data = NULL;
1049
1050         /* Initialize LNET_PROC_BUFFERS */
1051         pde = create_proc_entry (LNET_PROC_BUFFERS, 0444, NULL);
1052         if (pde == NULL) {
1053                 CERROR("couldn't create proc entry %s\n", LNET_PROC_BUFFERS);
1054                 return;
1055         }
1056
1057         pde->proc_fops = &lnet_buffers_fops;
1058         pde->data = NULL;
1059
1060         /* Initialize LNET_PROC_NIS */
1061         pde = create_proc_entry (LNET_PROC_NIS, 0444, NULL);
1062         if (pde == NULL) {
1063                 CERROR("couldn't create proc entry %s\n", LNET_PROC_NIS);
1064                 return;
1065         }
1066
1067         pde->proc_fops = &lnet_ni_fops;
1068         pde->data = NULL;
1069 }
1070
1071 void
1072 lnet_proc_fini(void)
1073 {
1074         remove_proc_entry(LNET_PROC_STATS, 0);
1075         remove_proc_entry(LNET_PROC_ROUTES, 0);
1076         remove_proc_entry(LNET_PROC_ROUTERS, 0);
1077         remove_proc_entry(LNET_PROC_PEERS, 0);
1078         remove_proc_entry(LNET_PROC_BUFFERS, 0);
1079         remove_proc_entry(LNET_PROC_NIS, 0);
1080 }
1081
1082 #else
1083
1084 void
1085 lnet_proc_init(void)
1086 {
1087 }
1088
1089 void
1090 lnet_proc_fini(void)
1091 {
1092 }
1093
1094 #endif