Whamcloud - gitweb
i=liang,b=13065:
[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         char                     *aliveness = "NA";
607         lnet_peer_t              *lp;
608         lnet_nid_t                nid;
609         int                       maxcr;
610         int                       mintxcr;
611         int                       txcr;
612         int                       minrtrcr;
613         int                       rtrcr;
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         txqnob   = lp->lp_txqnob;
642         nrefs    = lp->lp_refcount;
643
644         if (lnet_isrouter(lp) || lp->lp_ni->ni_peertimeout > 0)
645                 aliveness = lp->lp_alive ? "up" : "down";
646
647         LNET_UNLOCK();
648
649         seq_printf(s, "%-24s %4d %5s %5d %5d %5d %5d %5d %d\n",
650                    libcfs_nid2str(nid), nrefs, aliveness,
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         int                     npeerrtrcr;
962         lnet_nid_t              nid;
963         int                     nref;
964
965         if (lnsi->lnsi_off == 0) {
966                 seq_printf(s, "%-24s %4s %4s %4s %5s %5s %5s\n",
967                            "nid", "refs", "peer", "rtr", "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         npeerrtrcr = ni->ni_peerrtrcredits;
982         nid        = ni->ni_nid;
983         nref       = ni->ni_refcount;
984
985         LNET_UNLOCK();
986
987         seq_printf(s, "%-24s %4d %4d %4d %5d %5d %5d\n",
988                    libcfs_nid2str(nid), nref,
989                    npeertxcr, npeerrtrcr, maxtxcr, txcr, mintxcr);
990         return 0;
991 }
992
993 static struct seq_operations lnet_ni_sops = {
994         /* start */ lnet_ni_seq_start,
995         /* stop */  lnet_ni_seq_stop,
996         /* next */  lnet_ni_seq_next,
997         /* show */  lnet_ni_seq_show,
998 };
999
1000 static int
1001 lnet_ni_seq_open(struct inode *inode, struct file *file)
1002 {
1003         struct proc_dir_entry *dp = PDE(inode);
1004         struct seq_file       *sf;
1005         int                    rc;
1006
1007         rc = seq_open(file, &lnet_ni_sops);
1008         if (rc == 0) {
1009                 sf = file->private_data;
1010                 sf->private = dp->data;
1011         }
1012
1013         return rc;
1014 }
1015
1016 static struct file_operations lnet_ni_fops;
1017
1018 static void
1019 lnet_init_ni_fops(void)
1020 {
1021         lnet_ni_fops.owner   =  THIS_MODULE;
1022         lnet_ni_fops.llseek  =  seq_lseek;
1023         lnet_ni_fops.read    =  seq_read;
1024         lnet_ni_fops.open    =  lnet_ni_seq_open;
1025         lnet_ni_fops.release =  seq_release;
1026 }
1027
1028 void
1029 lnet_proc_init(void)
1030 {
1031         struct proc_dir_entry *pde;
1032
1033 #if 0
1034         pde = proc_mkdir(LNET_PROC_ROOT, NULL);
1035         if (pde == NULL) {
1036                 CERROR("couldn't create "LNET_PROC_ROOT"\n");
1037                 return; 
1038         }
1039 #endif
1040         /* Initialize LNET_PROC_STATS */
1041         pde = create_proc_entry (LNET_PROC_STATS, 0644, NULL);
1042         if (pde == NULL) {
1043                 CERROR("couldn't create proc entry %s\n", LNET_PROC_STATS);
1044                 return;
1045         }
1046
1047         pde->data = NULL;
1048         pde->read_proc = lnet_router_proc_stats_read;
1049         pde->write_proc = lnet_router_proc_stats_write;
1050
1051         /* Initialize LNET_PROC_ROUTES */
1052         pde = create_proc_entry (LNET_PROC_ROUTES, 0444, NULL);
1053         if (pde == NULL) {
1054                 CERROR("couldn't create proc entry %s\n", LNET_PROC_ROUTES);
1055                 return;
1056         }
1057
1058         lnet_init_routes_fops();
1059         pde->proc_fops = &lnet_routes_fops;
1060         pde->data = NULL;
1061
1062         /* Initialize LNET_PROC_ROUTERS */
1063         pde = create_proc_entry (LNET_PROC_ROUTERS, 0444, NULL);
1064         if (pde == NULL) {
1065                 CERROR("couldn't create proc entry %s\n", LNET_PROC_ROUTERS);
1066                 return;
1067         }
1068
1069         lnet_init_routers_fops();
1070         pde->proc_fops = &lnet_routers_fops;
1071         pde->data = NULL;
1072
1073         /* Initialize LNET_PROC_PEERS */
1074         pde = create_proc_entry (LNET_PROC_PEERS, 0444, NULL);
1075         if (pde == NULL) {
1076                 CERROR("couldn't create proc entry %s\n", LNET_PROC_PEERS);
1077                 return;
1078         }
1079
1080         lnet_init_peer_fops();
1081         pde->proc_fops = &lnet_peer_fops;
1082         pde->data = NULL;
1083
1084         /* Initialize LNET_PROC_BUFFERS */
1085         pde = create_proc_entry (LNET_PROC_BUFFERS, 0444, NULL);
1086         if (pde == NULL) {
1087                 CERROR("couldn't create proc entry %s\n", LNET_PROC_BUFFERS);
1088                 return;
1089         }
1090
1091         lnet_init_buffers_fops();
1092         pde->proc_fops = &lnet_buffers_fops;
1093         pde->data = NULL;
1094
1095         /* Initialize LNET_PROC_NIS */
1096         pde = create_proc_entry (LNET_PROC_NIS, 0444, NULL);
1097         if (pde == NULL) {
1098                 CERROR("couldn't create proc entry %s\n", LNET_PROC_NIS);
1099                 return;
1100         }
1101
1102         lnet_init_ni_fops();
1103         pde->proc_fops = &lnet_ni_fops;
1104         pde->data = NULL;
1105 }
1106
1107 void
1108 lnet_proc_fini(void)
1109 {
1110         remove_proc_entry(LNET_PROC_STATS, 0);
1111         remove_proc_entry(LNET_PROC_ROUTES, 0);
1112         remove_proc_entry(LNET_PROC_ROUTERS, 0);
1113         remove_proc_entry(LNET_PROC_PEERS, 0);
1114         remove_proc_entry(LNET_PROC_BUFFERS, 0);
1115         remove_proc_entry(LNET_PROC_NIS, 0);
1116 #if 0   
1117         remove_proc_entry(LNET_PROC_ROOT, 0);
1118 #endif
1119 }
1120
1121 #else
1122
1123 void
1124 lnet_proc_init(void)
1125 {
1126 }
1127
1128 void
1129 lnet_proc_fini(void)
1130 {
1131 }
1132
1133 #endif