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