Whamcloud - gitweb
Landing b_hd_newconfig on HEAD
[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                       txqnob;
604         int                       nrefs;
605
606         if (lpsi->lpsi_off == 0) {
607                 seq_printf(s, "%-24s %4s %5s %5s %5s %5s %5s %5s %s\n",
608                            "nid", "refs", "state", "max",
609                            "rtr", "min", "tx", "min", "queue");
610                 return 0;
611         }
612
613         LASSERT (lpsi->lpsi_peer != NULL);
614
615         LNET_LOCK();
616
617         if (lpsi->lpsi_version != the_lnet.ln_peertable_version) {
618                 LNET_UNLOCK();
619                 return -ESTALE;
620         }
621
622         lp = lpsi->lpsi_peer;
623
624         nid      = lp->lp_nid;
625         maxcr    = lp->lp_ni->ni_peertxcredits;
626         txcr     = lp->lp_txcredits;
627         mintxcr  = lp->lp_mintxcredits;
628         rtrcr    = lp->lp_rtrcredits;
629         minrtrcr = lp->lp_minrtrcredits;
630         alive    = lp->lp_alive;
631         txqnob   = lp->lp_txqnob;
632         nrefs    = lp->lp_refcount;
633
634         LNET_UNLOCK();
635
636         seq_printf(s, "%-24s %4d %5s %5d %5d %5d %5d %5d %d\n",
637                    libcfs_nid2str(nid), nrefs, alive ? "up" : "down",
638                    maxcr, rtrcr, minrtrcr, txcr, mintxcr, txqnob);
639         return 0;
640 }
641
642 static struct seq_operations lnet_peer_sops = {
643         .start = lnet_peer_seq_start,
644         .stop  = lnet_peer_seq_stop,
645         .next  = lnet_peer_seq_next,
646         .show  = lnet_peer_seq_show,
647 };
648
649 static int
650 lnet_peer_seq_open(struct inode *inode, struct file *file)
651 {
652         struct proc_dir_entry *dp = PDE(inode);
653         struct seq_file       *sf;
654         int                    rc;
655
656         rc = seq_open(file, &lnet_peer_sops);
657         if (rc == 0) {
658                 sf = file->private_data;
659                 sf->private = dp->data;
660         }
661
662         return rc;
663 }
664
665 static struct file_operations lnet_peer_fops = {
666         .owner   = THIS_MODULE,
667         .open    = lnet_peer_seq_open,
668         .read    = seq_read,
669         .llseek  = seq_lseek,
670         .release = seq_release,
671 };
672
673 typedef struct {
674         int                  lbsi_idx;
675         loff_t               lbsi_off;
676 } lnet_buffer_seq_iterator_t;
677
678 int
679 lnet_buffer_seq_seek (lnet_buffer_seq_iterator_t *lbsi, loff_t off)
680 {
681         int                idx;
682         loff_t             here;
683         int                rc;
684
685         if (off == 0) {
686                 lbsi->lbsi_idx = -1;
687                 lbsi->lbsi_off = 0;
688                 return 0;
689         }
690
691         LNET_LOCK();
692
693         if (lbsi->lbsi_idx < 0 ||
694             lbsi->lbsi_off > off) {
695                 /* search from start */
696                 idx = 0;
697                 here = 1;
698         } else {
699                 /* continue search */
700                 idx = lbsi->lbsi_idx;
701                 here = lbsi->lbsi_off;
702         }
703
704         lbsi->lbsi_off     = off;
705
706         while (idx < LNET_NRBPOOLS) {
707                 if (here == off) {
708                         lbsi->lbsi_idx = idx;
709                         rc = 0;
710                         goto out;
711                 }
712                 here++;
713                 idx++;
714         }
715
716         lbsi->lbsi_idx  = -1;
717         rc              = -ENOENT;
718  out:
719         LNET_UNLOCK();
720         return rc;
721 }
722
723 static void *
724 lnet_buffer_seq_start (struct seq_file *s, loff_t *pos)
725 {
726         lnet_buffer_seq_iterator_t *lbsi;
727         int                        rc;
728
729         LIBCFS_ALLOC(lbsi, sizeof(*lbsi));
730         if (lbsi == NULL)
731                 return NULL;
732
733         lbsi->lbsi_idx = -1;
734         rc = lnet_buffer_seq_seek(lbsi, *pos);
735         if (rc == 0)
736                 return lbsi;
737
738         LIBCFS_FREE(lbsi, sizeof(*lbsi));
739         return NULL;
740 }
741
742 static void
743 lnet_buffer_seq_stop (struct seq_file *s, void *iter)
744 {
745         lnet_buffer_seq_iterator_t  *lbsi = iter;
746
747         if (lbsi != NULL)
748                 LIBCFS_FREE(lbsi, sizeof(*lbsi));
749 }
750
751 static void *
752 lnet_buffer_seq_next (struct seq_file *s, void *iter, loff_t *pos)
753 {
754         lnet_buffer_seq_iterator_t *lbsi = iter;
755         int                         rc;
756         loff_t                      next = *pos + 1;
757
758         rc = lnet_buffer_seq_seek(lbsi, next);
759         if (rc != 0) {
760                 LIBCFS_FREE(lbsi, sizeof(*lbsi));
761                 return NULL;
762         }
763
764         *pos = next;
765         return lbsi;
766 }
767
768 static int
769 lnet_buffer_seq_show (struct seq_file *s, void *iter)
770 {
771         lnet_buffer_seq_iterator_t *lbsi = iter;
772         lnet_rtrbufpool_t          *rbp;
773         int                         npages;
774         int                         nbuf;
775         int                         cr;
776         int                         mincr;
777
778         if (lbsi->lbsi_off == 0) {
779                 seq_printf(s, "%5s %5s %7s %7s\n",
780                            "pages", "count", "credits", "min");
781                 return 0;
782         }
783
784         LASSERT (lbsi->lbsi_idx >= 0 && lbsi->lbsi_idx < LNET_NRBPOOLS);
785
786         LNET_LOCK();
787
788         rbp = &the_lnet.ln_rtrpools[lbsi->lbsi_idx];
789
790         npages = rbp->rbp_npages;
791         nbuf   = rbp->rbp_nbuffers;
792         cr     = rbp->rbp_credits;
793         mincr  = rbp->rbp_mincredits;
794
795         LNET_UNLOCK();
796
797         seq_printf(s, "%5d %5d %7d %7d\n",
798                    npages, nbuf, cr, mincr);
799         return 0;
800 }
801
802 static struct seq_operations lnet_buffer_sops = {
803         .start = lnet_buffer_seq_start,
804         .stop  = lnet_buffer_seq_stop,
805         .next  = lnet_buffer_seq_next,
806         .show  = lnet_buffer_seq_show,
807 };
808
809 static int
810 lnet_buffer_seq_open(struct inode *inode, struct file *file)
811 {
812         struct proc_dir_entry *dp = PDE(inode);
813         struct seq_file       *sf;
814         int                    rc;
815
816         rc = seq_open(file, &lnet_buffer_sops);
817         if (rc == 0) {
818                 sf = file->private_data;
819                 sf->private = dp->data;
820         }
821
822         return rc;
823 }
824
825 static struct file_operations lnet_buffers_fops = {
826         .owner   = THIS_MODULE,
827         .open    = lnet_buffer_seq_open,
828         .read    = seq_read,
829         .llseek  = seq_lseek,
830         .release = seq_release,
831 };
832
833 typedef struct {
834         lnet_ni_t           *lnsi_ni;
835         loff_t               lnsi_off;
836 } lnet_ni_seq_iterator_t;
837
838 int
839 lnet_ni_seq_seek (lnet_ni_seq_iterator_t *lnsi, loff_t off)
840 {
841         struct list_head  *n;
842         loff_t             here;
843         int                rc;
844
845         if (off == 0) {
846                 lnsi->lnsi_ni = NULL;
847                 lnsi->lnsi_off = 0;
848                 return 0;
849         }
850
851         LNET_LOCK();
852
853         if (lnsi->lnsi_ni == NULL ||
854             lnsi->lnsi_off > off) {
855                 /* search from start */
856                 n = NULL;
857                 here = 1;
858         } else {
859                 /* continue search */
860                 n = &lnsi->lnsi_ni->ni_list;
861                 here = lnsi->lnsi_off;
862         }
863
864         lnsi->lnsi_off = off;
865
866         if (n == NULL)
867                 n = the_lnet.ln_nis.next;
868
869         while (n != &the_lnet.ln_nis) {
870                 if (here == off) {
871                         lnsi->lnsi_ni = list_entry(n, lnet_ni_t, ni_list);
872                         rc = 0;
873                         goto out;
874                 }
875                 here++;
876                 n = n->next;
877         }
878
879         lnsi->lnsi_ni  = NULL;
880         rc             = -ENOENT;
881  out:
882         LNET_UNLOCK();
883         return rc;
884 }
885
886 static void *
887 lnet_ni_seq_start (struct seq_file *s, loff_t *pos)
888 {
889         lnet_ni_seq_iterator_t *lnsi;
890         int                     rc;
891
892         LIBCFS_ALLOC(lnsi, sizeof(*lnsi));
893         if (lnsi == NULL)
894                 return NULL;
895
896         lnsi->lnsi_ni = NULL;
897         rc = lnet_ni_seq_seek(lnsi, *pos);
898         if (rc == 0)
899                 return lnsi;
900
901         LIBCFS_FREE(lnsi, sizeof(*lnsi));
902         return NULL;
903 }
904
905 static void
906 lnet_ni_seq_stop (struct seq_file *s, void *iter)
907 {
908         lnet_ni_seq_iterator_t  *lnsi = iter;
909
910         if (lnsi != NULL)
911                 LIBCFS_FREE(lnsi, sizeof(*lnsi));
912 }
913
914 static void *
915 lnet_ni_seq_next (struct seq_file *s, void *iter, loff_t *pos)
916 {
917         lnet_ni_seq_iterator_t *lnsi = iter;
918         int                     rc;
919         loff_t                  next = *pos + 1;
920
921         rc = lnet_ni_seq_seek(lnsi, next);
922         if (rc != 0) {
923                 LIBCFS_FREE(lnsi, sizeof(*lnsi));
924                 return NULL;
925         }
926
927         *pos = next;
928         return lnsi;
929 }
930
931 static int
932 lnet_ni_seq_show (struct seq_file *s, void *iter)
933 {
934         lnet_ni_seq_iterator_t *lnsi = iter;
935         lnet_ni_t              *ni;
936         int                     maxtxcr;
937         int                     txcr;
938         int                     mintxcr;
939         int                     npeertxcr;
940         lnet_nid_t              nid;
941         int                     nref;
942
943         if (lnsi->lnsi_off == 0) {
944                 seq_printf(s, "%-24s %4s %4s %5s %5s %5s\n",
945                            "nid", "refs", "peer", "max", "tx", "min");
946                 return 0;
947         }
948
949         LASSERT (lnsi->lnsi_ni != NULL);
950
951         LNET_LOCK();
952
953         ni = lnsi->lnsi_ni;
954
955         maxtxcr   = ni->ni_maxtxcredits;
956         txcr      = ni->ni_txcredits;
957         mintxcr   = ni->ni_mintxcredits;
958         npeertxcr = ni->ni_peertxcredits;
959         nid       = ni->ni_nid;
960         nref      = ni->ni_refcount;
961
962         LNET_UNLOCK();
963
964         seq_printf(s, "%-24s %4d %4d %5d %5d %5d\n",
965                    libcfs_nid2str(nid), nref,
966                    npeertxcr, maxtxcr, txcr, mintxcr);
967         return 0;
968 }
969
970 static struct seq_operations lnet_ni_sops = {
971         .start = lnet_ni_seq_start,
972         .stop  = lnet_ni_seq_stop,
973         .next  = lnet_ni_seq_next,
974         .show  = lnet_ni_seq_show,
975 };
976
977 static int
978 lnet_ni_seq_open(struct inode *inode, struct file *file)
979 {
980         struct proc_dir_entry *dp = PDE(inode);
981         struct seq_file       *sf;
982         int                    rc;
983
984         rc = seq_open(file, &lnet_ni_sops);
985         if (rc == 0) {
986                 sf = file->private_data;
987                 sf->private = dp->data;
988         }
989
990         return rc;
991 }
992
993 static struct file_operations lnet_ni_fops = {
994         .owner   = THIS_MODULE,
995         .open    = lnet_ni_seq_open,
996         .read    = seq_read,
997         .llseek  = seq_lseek,
998         .release = seq_release,
999 };
1000
1001 void
1002 lnet_proc_init(void)
1003 {
1004         struct proc_dir_entry *stats;
1005         struct proc_dir_entry *routes;
1006         struct proc_dir_entry *routers;
1007         struct proc_dir_entry *peers;
1008
1009         /* Initialize LNET_PROC_STATS */
1010         stats = create_proc_entry (LNET_PROC_STATS, 0644, NULL);
1011         if (stats == NULL) {
1012                 CERROR("couldn't create proc entry %s\n", LNET_PROC_STATS);
1013                 return;
1014         }
1015
1016         stats->data = NULL;
1017         stats->read_proc = lnet_router_proc_stats_read;
1018         stats->write_proc = lnet_router_proc_stats_write;
1019
1020         /* Initialize LNET_PROC_ROUTES */
1021         routes = create_proc_entry (LNET_PROC_ROUTES, 0444, NULL);
1022         if (routes == NULL) {
1023                 CERROR("couldn't create proc entry %s\n", LNET_PROC_ROUTES);
1024                 return;
1025         }
1026
1027         routes->proc_fops = &lnet_routes_fops;
1028         routes->data = NULL;
1029
1030         /* Initialize LNET_PROC_ROUTERS */
1031         routers = create_proc_entry (LNET_PROC_ROUTERS, 0444, NULL);
1032         if (routers == NULL) {
1033                 CERROR("couldn't create proc entry %s\n", LNET_PROC_ROUTERS);
1034                 return;
1035         }
1036
1037         routers->proc_fops = &lnet_routers_fops;
1038         routers->data = NULL;
1039
1040         /* Initialize LNET_PROC_PEERS */
1041         peers = create_proc_entry (LNET_PROC_PEERS, 0444, NULL);
1042         if (peers == NULL) {
1043                 CERROR("couldn't create proc entry %s\n", LNET_PROC_PEERS);
1044                 return;
1045         }
1046
1047         peers->proc_fops = &lnet_peer_fops;
1048         peers->data = NULL;
1049
1050         /* Initialize LNET_PROC_BUFFERS */
1051         peers = create_proc_entry (LNET_PROC_BUFFERS, 0444, NULL);
1052         if (peers == NULL) {
1053                 CERROR("couldn't create proc entry %s\n", LNET_PROC_BUFFERS);
1054                 return;
1055         }
1056
1057         peers->proc_fops = &lnet_buffers_fops;
1058         peers->data = NULL;
1059
1060         /* Initialize LNET_PROC_NIS */
1061         peers = create_proc_entry (LNET_PROC_NIS, 0444, NULL);
1062         if (peers == NULL) {
1063                 CERROR("couldn't create proc entry %s\n", LNET_PROC_NIS);
1064                 return;
1065         }
1066
1067         peers->proc_fops = &lnet_ni_fops;
1068         peers->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