Whamcloud - gitweb
c053f4c0b0ea17cda9ea42a8a9b5e788fb4acade
[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 /* this is really lnet_proc.c */
31
32 static cfs_sysctl_table_header_t *lnet_table_header = NULL;
33
34 #ifndef HAVE_SYSCTL_UNNUMBERED
35 #define CTL_LNET         (0x100)
36 enum {
37         PSDEV_LNET_STATS = 100,
38         PSDEV_LNET_ROUTES,
39         PSDEV_LNET_ROUTERS,
40         PSDEV_LNET_PEERS,
41         PSDEV_LNET_BUFFERS,
42         PSDEV_LNET_NIS,
43 };
44 #else
45 #define CTL_LNET           CTL_UNNUMBERED
46 #define PSDEV_LNET_STATS   CTL_UNNUMBERED
47 #define PSDEV_LNET_ROUTES  CTL_UNNUMBERED
48 #define PSDEV_LNET_ROUTERS CTL_UNNUMBERED
49 #define PSDEV_LNET_PEERS   CTL_UNNUMBERED
50 #define PSDEV_LNET_BUFFERS CTL_UNNUMBERED
51 #define PSDEV_LNET_NIS     CTL_UNNUMBERED
52 #endif
53
54 static int __proc_lnet_stats(void *data, int write,
55                              loff_t pos, void *buffer, int nob)
56 {
57         int              rc;
58         lnet_counters_t *ctrs;
59         int              len;
60         char            *tmpstr;
61         const int        tmpsiz = 256; /* 7 %u and 4 LPU64 */
62
63         if (write) {
64                 LNET_LOCK();
65                 memset(&the_lnet.ln_counters, 0, sizeof(the_lnet.ln_counters));
66                 LNET_UNLOCK();
67                 return 0;
68         }
69
70         /* read */
71
72         LIBCFS_ALLOC(ctrs, sizeof(*ctrs));
73         if (ctrs == NULL)
74                 return -ENOMEM;
75
76         LIBCFS_ALLOC(tmpstr, tmpsiz);
77         if (tmpstr == NULL) {
78                 LIBCFS_FREE(ctrs, sizeof(*ctrs));
79                 return -ENOMEM;
80         }
81
82         LNET_LOCK();
83         *ctrs = the_lnet.ln_counters;
84         LNET_UNLOCK();
85
86         len = snprintf(tmpstr, tmpsiz,
87                        "%u %u %u %u %u %u %u "LPU64" "LPU64" "
88                        LPU64" "LPU64,
89                        ctrs->msgs_alloc, ctrs->msgs_max,
90                        ctrs->errors,
91                        ctrs->send_count, ctrs->recv_count,
92                        ctrs->route_count, ctrs->drop_count,
93                        ctrs->send_length, ctrs->recv_length,
94                        ctrs->route_length, ctrs->drop_length);
95
96         if (pos >= min_t(int, len, strlen(tmpstr)))
97                 rc = 0;
98         else
99                 rc = cfs_trace_copyout_string(buffer, nob,
100                                               tmpstr + pos, "\n");
101
102         LIBCFS_FREE(tmpstr, tmpsiz);
103         LIBCFS_FREE(ctrs, sizeof(*ctrs));
104         return rc;
105 }
106
107 DECLARE_PROC_HANDLER(proc_lnet_stats);
108
109 int LL_PROC_PROTO(proc_lnet_routes)
110 {
111         int        rc     = 0;
112         char      *tmpstr;
113         char      *s;
114         const int  tmpsiz = 256;
115         int        len;
116         int       *ver_p  = (unsigned int *)(&filp->private_data);
117
118         DECLARE_LL_PROC_PPOS_DECL;
119
120         LASSERT (!write);
121
122         if (*lenp == 0)
123                 return 0;
124
125         LIBCFS_ALLOC(tmpstr, tmpsiz);
126         if (tmpstr == NULL)
127                 return -ENOMEM;
128
129         s = tmpstr; /* points to current position in tmpstr[] */
130
131         if (*ppos == 0) {
132                 s += snprintf(s, tmpstr + tmpsiz - s, "Routing %s\n",
133                               the_lnet.ln_routing ? "enabled" : "disabled");
134                 LASSERT (tmpstr + tmpsiz - s > 0);
135
136                 s += snprintf(s, tmpstr + tmpsiz - s, "%-8s %4s %7s %s\n",
137                               "net", "hops", "state", "router");
138                 LASSERT (tmpstr + tmpsiz - s > 0);
139
140                 LNET_LOCK();
141                 *ver_p = (unsigned int)the_lnet.ln_remote_nets_version;
142                 LNET_UNLOCK();
143         } else {
144                 cfs_list_t        *n;
145                 cfs_list_t        *r;
146                 lnet_route_t      *route = NULL;
147                 lnet_remotenet_t  *rnet  = NULL;
148                 int                skip  = *ppos - 1;
149
150                 LNET_LOCK();
151
152                 if (*ver_p != (unsigned int)the_lnet.ln_remote_nets_version) {
153                         LNET_UNLOCK();
154                         LIBCFS_FREE(tmpstr, tmpsiz);
155                         return -ESTALE;
156                 }
157
158                 n = the_lnet.ln_remote_nets.next;
159
160                 while (n != &the_lnet.ln_remote_nets && route == NULL) {
161                         rnet = cfs_list_entry(n, lnet_remotenet_t, lrn_list);
162
163                         r = rnet->lrn_routes.next;
164
165                         while (r != &rnet->lrn_routes) {
166                                 lnet_route_t *re =
167                                         cfs_list_entry(r, lnet_route_t,
168                                                        lr_list);
169                                 if (skip == 0) {
170                                         route = re;
171                                         break;
172                                 }
173
174                                 skip--;
175                                 r = r->next;
176                         }
177
178                         n = n->next;
179                 }
180
181                 if (route != NULL) {
182                         __u32        net   = rnet->lrn_net;
183                         unsigned int hops  = route->lr_hops;
184                         lnet_nid_t   nid   = route->lr_gateway->lp_nid;
185                         int          alive = route->lr_gateway->lp_alive;
186
187                         s += snprintf(s, tmpstr + tmpsiz - s, "%-8s %4u %7s %s\n",
188                                       libcfs_net2str(net), hops,
189                                       alive ? "up" : "down", libcfs_nid2str(nid));
190                         LASSERT (tmpstr + tmpsiz - s > 0);
191                 }
192
193                 LNET_UNLOCK();
194         }
195
196         len = s - tmpstr;     /* how many bytes was written */
197
198         if (len > *lenp) {    /* linux-supplied buffer is too small */
199                 rc = -EINVAL;
200         } else if (len > 0) { /* wrote something */
201                 if (cfs_copy_to_user(buffer, tmpstr, len))
202                         rc = -EFAULT;
203                 else
204                         *ppos += 1;
205         }
206
207         LIBCFS_FREE(tmpstr, tmpsiz);
208
209         if (rc == 0)
210                 *lenp = len;
211
212         return rc;
213 }
214
215 int LL_PROC_PROTO(proc_lnet_routers)
216 {
217         int        rc = 0;
218         char      *tmpstr;
219         char      *s;
220         const int  tmpsiz = 256;
221         int        len;
222         int       *ver_p = (unsigned int *)(&filp->private_data);
223
224         DECLARE_LL_PROC_PPOS_DECL;
225
226         LASSERT (!write);
227
228         if (*lenp == 0)
229                 return 0;
230
231         LIBCFS_ALLOC(tmpstr, tmpsiz);
232         if (tmpstr == NULL)
233                 return -ENOMEM;
234
235         s = tmpstr; /* points to current position in tmpstr[] */
236
237         if (*ppos == 0) {
238                 s += snprintf(s, tmpstr + tmpsiz - s,
239                               "%-4s %7s %9s %6s %12s %9s %8s %7s %s\n",
240                               "ref", "rtr_ref", "alive_cnt", "state", "last_ping",
241                               "ping_sent", "deadline", "down_ni", "router");
242                 LASSERT (tmpstr + tmpsiz - s > 0);
243
244                 LNET_LOCK();
245                 *ver_p = (unsigned int)the_lnet.ln_routers_version;
246                 LNET_UNLOCK();
247         } else {
248                 cfs_list_t        *r;
249                 lnet_peer_t       *peer = NULL;
250                 int                skip = *ppos - 1;
251
252                 LNET_LOCK();
253
254                 if (*ver_p != (unsigned int)the_lnet.ln_routers_version) {
255                         LNET_UNLOCK();
256                         LIBCFS_FREE(tmpstr, tmpsiz);
257                         return -ESTALE;
258                 }
259
260                 r = the_lnet.ln_routers.next;
261
262                 while (r != &the_lnet.ln_routers) {
263                         lnet_peer_t *lp = cfs_list_entry(r, lnet_peer_t,
264                                                          lp_rtr_list);
265
266                         if (skip == 0) {
267                                 peer = lp;
268                                 break;
269                         }
270
271                         skip--;
272                         r = r->next;
273                 }
274
275                 if (peer != NULL) {
276                         lnet_nid_t nid = peer->lp_nid;
277                         cfs_time_t now = cfs_time_current();
278                         cfs_time_t deadline = peer->lp_ping_deadline;
279                         int nrefs     = peer->lp_refcount;
280                         int nrtrrefs  = peer->lp_rtr_refcount;
281                         int alive_cnt = peer->lp_alive_count;
282                         int alive     = peer->lp_alive;
283                         int pingsent  = !peer->lp_ping_notsent;
284                         int last_ping = cfs_duration_sec(cfs_time_sub(now,
285                                                      peer->lp_ping_timestamp));
286                         int down_ni   = lnet_router_down_ni(peer,
287                                                     LNET_NIDNET(LNET_NID_ANY));
288
289                         if (deadline == 0)
290                                 s += snprintf(s, tmpstr + tmpsiz - s,
291                                               "%-4d %7d %9d %6s %12d %9d %8s %7d %s\n",
292                                               nrefs, nrtrrefs, alive_cnt,
293                                               alive ? "up" : "down", last_ping,
294                                               pingsent, "NA", down_ni,
295                                               libcfs_nid2str(nid));
296                         else
297                                 s += snprintf(s, tmpstr + tmpsiz - s,
298                                               "%-4d %7d %9d %6s %12d %9d %8lu %7d %s\n",
299                                               nrefs, nrtrrefs, alive_cnt,
300                                               alive ? "up" : "down", last_ping,
301                                               pingsent,
302                                               cfs_duration_sec(cfs_time_sub(deadline, now)),
303                                               down_ni, libcfs_nid2str(nid));
304                         LASSERT (tmpstr + tmpsiz - s > 0);
305                 }
306
307                 LNET_UNLOCK();
308         }
309
310         len = s - tmpstr;     /* how many bytes was written */
311
312         if (len > *lenp) {    /* linux-supplied buffer is too small */
313                 rc = -EINVAL;
314         } else if (len > 0) { /* wrote something */
315                 if (cfs_copy_to_user(buffer, tmpstr, len))
316                         rc = -EFAULT;
317                 else
318                         *ppos += 1;
319         }
320
321         LIBCFS_FREE(tmpstr, tmpsiz);
322
323         if (rc == 0)
324                 *lenp = len;
325
326         return rc;
327 }
328
329 /*
330  * NB: we don't use the highest bit of *ppos because it's signed;
331  *     next 9 bits is used to stash idx (assuming that
332  *     LNET_PEER_HASHSIZE < 512)
333  */
334 #define LNET_LOFFT_BITS (sizeof(loff_t) * 8)
335 #define LNET_PHASH_BITS 9
336 #define LNET_PHASH_IDX_MASK (((1ULL << LNET_PHASH_BITS) - 1) <<               \
337                              (LNET_LOFFT_BITS - LNET_PHASH_BITS - 1))
338 #define LNET_PHASH_NUM_MASK ((1ULL <<                                         \
339                               (LNET_LOFFT_BITS - LNET_PHASH_BITS -1)) - 1)
340 #define LNET_PHASH_IDX_GET(pos) (int)(((pos) & LNET_PHASH_IDX_MASK) >>  \
341                                       (LNET_LOFFT_BITS - LNET_PHASH_BITS -1))
342 #define LNET_PHASH_NUM_GET(pos) (int)((pos) & LNET_PHASH_NUM_MASK)
343 #define LNET_PHASH_POS_MAKE(idx, num) ((((loff_t)idx) << (LNET_LOFFT_BITS -   \
344                                                   LNET_PHASH_BITS -1)) | (num))
345
346 int LL_PROC_PROTO(proc_lnet_peers)
347 {
348         int        rc = 0;
349         char      *tmpstr;
350         char      *s;
351         const int  tmpsiz      = 256;
352         int        len;
353         int       *ver_p       = (unsigned int *)(&filp->private_data);
354         int        idx;
355         int        num;
356
357         DECLARE_LL_PROC_PPOS_DECL;
358
359         idx = LNET_PHASH_IDX_GET(*ppos);
360         num = LNET_PHASH_NUM_GET(*ppos);
361
362         CLASSERT ((1 << LNET_PHASH_BITS) > LNET_PEER_HASHSIZE);
363
364         LASSERT (!write);
365
366         if (*lenp == 0)
367                 return 0;
368
369         LIBCFS_ALLOC(tmpstr, tmpsiz);
370         if (tmpstr == NULL)
371                 return -ENOMEM;
372
373         s = tmpstr; /* points to current position in tmpstr[] */
374
375         if (*ppos == 0) {
376                 s += snprintf(s, tmpstr + tmpsiz - s,
377                               "%-24s %4s %5s %5s %5s %5s %5s %5s %s\n",
378                               "nid", "refs", "state", "max",
379                               "rtr", "min", "tx", "min", "queue");
380                 LASSERT (tmpstr + tmpsiz - s > 0);
381
382                 LNET_LOCK();
383                 *ver_p  = (unsigned int)the_lnet.ln_peertable_version;
384                 LNET_UNLOCK();
385
386                 num++;
387         } else {
388                 cfs_list_t        *p    = NULL;
389                 lnet_peer_t       *peer = NULL;
390                 int                skip = num - 1;
391
392                 LNET_LOCK();
393
394                 if (*ver_p != (unsigned int)the_lnet.ln_peertable_version) {
395                         LNET_UNLOCK();
396                         LIBCFS_FREE(tmpstr, tmpsiz);
397                         return -ESTALE;
398                 }
399
400                 while (idx < LNET_PEER_HASHSIZE) {
401                         if (p == NULL)
402                                 p = the_lnet.ln_peer_hash[idx].next;
403
404                         while (p != &the_lnet.ln_peer_hash[idx]) {
405                                 lnet_peer_t *lp = cfs_list_entry(p, lnet_peer_t,
406                                                                  lp_hashlist);
407                                 if (skip == 0) {
408                                         peer = lp;
409
410                                         /* minor optimiztion: start from idx+1
411                                          * on next iteration if we've just
412                                          * drained lp_hashlist */
413                                         if (lp->lp_hashlist.next ==
414                                             &the_lnet.ln_peer_hash[idx]) {
415                                                 num = 1;
416                                                 idx++;
417                                         } else {
418                                                 num++;
419                                         }
420
421                                         break;
422                                 }
423
424                                 skip--;
425                                 p = lp->lp_hashlist.next;
426                         }
427
428                         if (peer != NULL)
429                                 break;
430
431                         p = NULL;
432                         num = 1;
433                         idx++;
434                 }
435
436                 if (peer != NULL) {
437                         lnet_nid_t nid       = peer->lp_nid;
438                         int        nrefs     = peer->lp_refcount;
439                         char      *aliveness = "NA";
440                         int        maxcr     = peer->lp_ni->ni_peertxcredits;
441                         int        txcr      = peer->lp_txcredits;
442                         int        mintxcr   = peer->lp_mintxcredits;
443                         int        rtrcr     = peer->lp_rtrcredits;
444                         int        minrtrcr  = peer->lp_minrtrcredits;
445                         int        txqnob    = peer->lp_txqnob;
446
447                         if (lnet_isrouter(peer) ||
448                             lnet_peer_aliveness_enabled(peer))
449                                 aliveness = peer->lp_alive ? "up" : "down";
450
451                         s += snprintf(s, tmpstr + tmpsiz - s,
452                                       "%-24s %4d %5s %5d %5d %5d %5d %5d %d\n",
453                                       libcfs_nid2str(nid), nrefs, aliveness,
454                                       maxcr, rtrcr, minrtrcr, txcr,
455                                       mintxcr, txqnob);
456                         LASSERT (tmpstr + tmpsiz - s > 0);
457                 }
458
459                 LNET_UNLOCK();
460         }
461
462         len = s - tmpstr;     /* how many bytes was written */
463
464         if (len > *lenp) {    /* linux-supplied buffer is too small */
465                 rc = -EINVAL;
466         } else if (len > 0) { /* wrote something */
467                 if (cfs_copy_to_user(buffer, tmpstr, len))
468                         rc = -EFAULT;
469                 else
470                         *ppos = LNET_PHASH_POS_MAKE(idx, num);
471         }
472
473         LIBCFS_FREE(tmpstr, tmpsiz);
474
475         if (rc == 0)
476                 *lenp = len;
477
478         return rc;
479 }
480
481 static int __proc_lnet_buffers(void *data, int write,
482                                loff_t pos, void *buffer, int nob)
483 {
484
485         int              rc;
486         int              len;
487         char            *s;
488         char            *tmpstr;
489         const int        tmpsiz = 64 * (LNET_NRBPOOLS + 1); /* (4 %d) * 4 */
490         int              idx;
491
492         LASSERT (!write);
493
494         LIBCFS_ALLOC(tmpstr, tmpsiz);
495         if (tmpstr == NULL)
496                 return -ENOMEM;
497
498         s = tmpstr; /* points to current position in tmpstr[] */
499
500         s += snprintf(s, tmpstr + tmpsiz - s,
501                       "%5s %5s %7s %7s\n",
502                       "pages", "count", "credits", "min");
503         LASSERT (tmpstr + tmpsiz - s > 0);
504
505         LNET_LOCK();
506
507         for (idx = 0; idx < LNET_NRBPOOLS; idx++) {
508                 lnet_rtrbufpool_t *rbp = &the_lnet.ln_rtrpools[idx];
509
510                 int npages = rbp->rbp_npages;
511                 int nbuf   = rbp->rbp_nbuffers;
512                 int cr     = rbp->rbp_credits;
513                 int mincr  = rbp->rbp_mincredits;
514
515                 s += snprintf(s, tmpstr + tmpsiz - s,
516                               "%5d %5d %7d %7d\n",
517                               npages, nbuf, cr, mincr);
518                 LASSERT (tmpstr + tmpsiz - s > 0);
519         }
520
521         LNET_UNLOCK();
522
523         len = s - tmpstr;
524
525         if (pos >= min_t(int, len, strlen(tmpstr)))
526                 rc = 0;
527         else
528                 rc = cfs_trace_copyout_string(buffer, nob,
529                                               tmpstr + pos, NULL);
530
531         LIBCFS_FREE(tmpstr, tmpsiz);
532         return rc;
533 }
534
535 DECLARE_PROC_HANDLER(proc_lnet_buffers);
536
537 int LL_PROC_PROTO(proc_lnet_nis)
538 {
539         int        rc = 0;
540         char      *tmpstr;
541         char      *s;
542         const int  tmpsiz = 256;
543         int        len;
544
545         DECLARE_LL_PROC_PPOS_DECL;
546
547         LASSERT (!write);
548
549         if (*lenp == 0)
550                 return 0;
551
552         LIBCFS_ALLOC(tmpstr, tmpsiz);
553         if (tmpstr == NULL)
554                 return -ENOMEM;
555
556         s = tmpstr; /* points to current position in tmpstr[] */
557
558         if (*ppos == 0) {
559                 s += snprintf(s, tmpstr + tmpsiz - s,
560                               "%-24s %6s %5s %4s %4s %4s %5s %5s %5s\n",
561                               "nid", "status", "alive", "refs", "peer",
562                               "rtr", "max", "tx", "min");
563                 LASSERT (tmpstr + tmpsiz - s > 0);
564         } else {
565                 cfs_list_t        *n;
566                 lnet_ni_t         *ni   = NULL;
567                 int                skip = *ppos - 1;
568
569                 LNET_LOCK();
570
571                 n = the_lnet.ln_nis.next;
572
573                 while (n != &the_lnet.ln_nis) {
574                         lnet_ni_t *a_ni = cfs_list_entry(n, lnet_ni_t, ni_list);
575
576                         if (skip == 0) {
577                                 ni = a_ni;
578                                 break;
579                         }
580
581                         skip--;
582                         n = n->next;
583                 }
584
585                 if (ni != NULL) {
586                         cfs_time_t now = cfs_time_current();
587                         int        last_alive = -1;
588                         int        maxtxcr = ni->ni_maxtxcredits;
589                         int        txcr = ni->ni_txcredits;
590                         int        mintxcr = ni->ni_mintxcredits;
591                         int        npeertxcr = ni->ni_peertxcredits;
592                         int        npeerrtrcr = ni->ni_peerrtrcredits;
593                         lnet_nid_t nid = ni->ni_nid;
594                         int        nref = ni->ni_refcount;
595                         char      *stat;
596
597                         if (the_lnet.ln_routing)
598                                 last_alive = cfs_duration_sec(cfs_time_sub(now,
599                                                             ni->ni_last_alive));
600                         if (ni->ni_lnd->lnd_type == LOLND)  /* @lo forever alive */
601                                 last_alive = 0;
602
603                         LASSERT (ni->ni_status != NULL);
604                         stat = (ni->ni_status->ns_status == LNET_NI_STATUS_UP) ?
605                                                                   "up" : "down";
606
607                         s += snprintf(s, tmpstr + tmpsiz - s,
608                                       "%-24s %6s %5d %4d %4d %4d %5d %5d %5d\n",
609                                       libcfs_nid2str(nid), stat, last_alive, nref,
610                                       npeertxcr, npeerrtrcr, maxtxcr,
611                                       txcr, mintxcr);
612                         LASSERT (tmpstr + tmpsiz - s > 0);
613                 }
614
615                 LNET_UNLOCK();
616         }
617
618         len = s - tmpstr;     /* how many bytes was written */
619
620         if (len > *lenp) {    /* linux-supplied buffer is too small */
621                 rc = -EINVAL;
622         } else if (len > 0) { /* wrote something */
623                 if (cfs_copy_to_user(buffer, tmpstr, len))
624                         rc = -EFAULT;
625                 else
626                         *ppos += 1;
627         }
628
629         LIBCFS_FREE(tmpstr, tmpsiz);
630
631         if (rc == 0)
632                 *lenp = len;
633
634         return rc;
635 }
636
637 static cfs_sysctl_table_t lnet_table[] = {
638         /*
639          * NB No .strategy entries have been provided since sysctl(8) prefers
640          * to go via /proc for portability.
641          */
642         {
643                 .ctl_name = PSDEV_LNET_STATS,
644                 .procname = "stats",
645                 .mode     = 0644,
646                 .proc_handler = &proc_lnet_stats,
647         },
648         {
649                 .ctl_name = PSDEV_LNET_ROUTES,
650                 .procname = "routes",
651                 .mode     = 0444,
652                 .proc_handler = &proc_lnet_routes,
653         },
654         {
655                 .ctl_name = PSDEV_LNET_ROUTERS,
656                 .procname = "routers",
657                 .mode     = 0444,
658                 .proc_handler = &proc_lnet_routers,
659         },
660         {
661                 .ctl_name = PSDEV_LNET_PEERS,
662                 .procname = "peers",
663                 .mode     = 0444,
664                 .proc_handler = &proc_lnet_peers,
665         },
666         {
667                 .ctl_name = PSDEV_LNET_PEERS,
668                 .procname = "buffers",
669                 .mode     = 0444,
670                 .proc_handler = &proc_lnet_buffers,
671         },
672         {
673                 .ctl_name = PSDEV_LNET_NIS,
674                 .procname = "nis",
675                 .mode     = 0444,
676                 .proc_handler = &proc_lnet_nis,
677         },
678         {0}
679 };
680
681 static cfs_sysctl_table_t top_table[] = {
682         {
683                 .ctl_name = CTL_LNET,
684                 .procname = "lnet",
685                 .mode     = 0555,
686                 .data     = NULL,
687                 .maxlen   = 0,
688                 .child    = lnet_table,
689         },
690         {
691                 .ctl_name = 0
692         }
693 };
694
695 void
696 lnet_proc_init(void)
697 {
698 #ifdef CONFIG_SYSCTL
699         if (lnet_table_header == NULL)
700                 lnet_table_header = cfs_register_sysctl_table(top_table, 0);
701 #endif
702 }
703
704 void
705 lnet_proc_fini(void)
706 {
707 #ifdef CONFIG_SYSCTL
708         if (lnet_table_header != NULL)
709                 cfs_unregister_sysctl_table(lnet_table_header);
710
711         lnet_table_header = NULL;
712 #endif
713 }
714
715 #else
716
717 void
718 lnet_proc_init(void)
719 {
720 }
721
722 void
723 lnet_proc_fini(void)
724 {
725 }
726
727 #endif