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