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