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