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