Whamcloud - gitweb
LU-8418 libcfs: remove lnet upcall code
[fs/lustre-release.git] / libcfs / libcfs / module.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2012, 2015, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  * Lustre is a trademark of Sun Microsystems, Inc.
31  */
32 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/mm.h>
35 #include <linux/string.h>
36 #include <linux/stat.h>
37 #include <linux/errno.h>
38 #include <linux/unistd.h>
39 #include <net/sock.h>
40 #include <linux/uio.h>
41 #include <linux/uaccess.h>
42
43 #include <linux/fs.h>
44 #include <linux/file.h>
45 #include <linux/list.h>
46
47 #include <linux/sysctl.h>
48 #include <linux/proc_fs.h>
49 #include <asm/div64.h>
50
51 #define DEBUG_SUBSYSTEM S_LNET
52
53 #include <libcfs/libcfs.h>
54 #include <libcfs/libcfs_crypto.h>
55 #include <lnet/lib-lnet.h>
56 #include "tracefile.h"
57
58 #ifdef CONFIG_SYSCTL
59 static struct ctl_table_header *lnet_table_header;
60 #endif
61
62 static DECLARE_RWSEM(ioctl_list_sem);
63 static LIST_HEAD(ioctl_list);
64
65 int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand)
66 {
67         int rc = 0;
68
69         down_write(&ioctl_list_sem);
70         if (!list_empty(&hand->item))
71                 rc = -EBUSY;
72         else
73                 list_add_tail(&hand->item, &ioctl_list);
74         up_write(&ioctl_list_sem);
75
76         return rc;
77 }
78 EXPORT_SYMBOL(libcfs_register_ioctl);
79
80 int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand)
81 {
82         int rc = 0;
83
84         down_write(&ioctl_list_sem);
85         if (list_empty(&hand->item))
86                 rc = -ENOENT;
87         else
88                 list_del_init(&hand->item);
89         up_write(&ioctl_list_sem);
90
91         return rc;
92 }
93 EXPORT_SYMBOL(libcfs_deregister_ioctl);
94
95 int libcfs_ioctl(unsigned long cmd, void __user *uparam)
96 {
97         struct libcfs_ioctl_data *data = NULL;
98         struct libcfs_ioctl_hdr  *hdr;
99         int                       err;
100         ENTRY;
101
102         /* 'cmd' and permissions get checked in our arch-specific caller */
103         err = libcfs_ioctl_getdata(&hdr, uparam);
104         if (err != 0) {
105                 CDEBUG_LIMIT(D_ERROR,
106                              "libcfs ioctl: data header error %d\n", err);
107                 RETURN(err);
108         }
109
110         if (hdr->ioc_version == LIBCFS_IOCTL_VERSION) {
111                 /* The libcfs_ioctl_data_adjust() function performs adjustment
112                  * operations on the libcfs_ioctl_data structure to make
113                  * it usable by the code.  This doesn't need to be called
114                  * for new data structures added. */
115                 data = container_of(hdr, struct libcfs_ioctl_data, ioc_hdr);
116                 err = libcfs_ioctl_data_adjust(data);
117                 if (err != 0)
118                         GOTO(out, err);
119         }
120
121         CDEBUG(D_IOCTL, "libcfs ioctl cmd %lu\n", cmd);
122         switch (cmd) {
123         case IOC_LIBCFS_CLEAR_DEBUG:
124                 libcfs_debug_clear_buffer();
125                 break;
126         case IOC_LIBCFS_MARK_DEBUG:
127                 if (data == NULL ||
128                     data->ioc_inlbuf1 == NULL ||
129                     data->ioc_inlbuf1[data->ioc_inllen1 - 1] != '\0')
130                         GOTO(out, err = -EINVAL);
131
132                 libcfs_debug_mark_buffer(data->ioc_inlbuf1);
133                 break;
134
135         default: {
136                 struct libcfs_ioctl_handler *hand;
137
138                 err = -EINVAL;
139                 down_read(&ioctl_list_sem);
140                 list_for_each_entry(hand, &ioctl_list, item) {
141                         err = hand->handle_ioctl(cmd, hdr);
142                         if (err == -EINVAL)
143                                 continue;
144
145                         if (err == 0) {
146                                 if (copy_to_user(uparam, hdr, hdr->ioc_len))
147                                         err = -EFAULT;
148                         }
149                         break;
150                 }
151                 up_read(&ioctl_list_sem);
152                 break; }
153         }
154 out:
155         LIBCFS_FREE(hdr, hdr->ioc_len);
156         RETURN(err);
157 }
158
159 int
160 lprocfs_call_handler(void *data, int write, loff_t *ppos,
161                      void __user *buffer, size_t *lenp,
162                      int (*handler)(void *data, int write, loff_t pos,
163                                     void __user *buffer, int len))
164 {
165         int rc = handler(data, write, *ppos, buffer, *lenp);
166
167         if (rc < 0)
168                 return rc;
169
170         if (write) {
171                 *ppos += *lenp;
172         } else {
173                 *lenp = rc;
174                 *ppos += rc;
175         }
176         return 0;
177 }
178 EXPORT_SYMBOL(lprocfs_call_handler);
179
180 static int __proc_dobitmasks(void *data, int write,
181                              loff_t pos, void __user *buffer, int nob)
182 {
183         const int     tmpstrlen = 512;
184         char         *tmpstr;
185         int           rc;
186         unsigned int *mask = data;
187         int           is_subsys = (mask == &libcfs_subsystem_debug) ? 1 : 0;
188         int           is_printk = (mask == &libcfs_printk) ? 1 : 0;
189
190         rc = cfs_trace_allocate_string_buffer(&tmpstr, tmpstrlen);
191         if (rc < 0)
192                 return rc;
193
194         if (!write) {
195                 libcfs_debug_mask2str(tmpstr, tmpstrlen, *mask, is_subsys);
196                 rc = strlen(tmpstr);
197
198                 if (pos >= rc) {
199                         rc = 0;
200                 } else {
201                         rc = cfs_trace_copyout_string(buffer, nob,
202                                                       tmpstr + pos, "\n");
203                 }
204         } else {
205                 rc = cfs_trace_copyin_string(tmpstr, tmpstrlen, buffer, nob);
206                 if (rc < 0) {
207                         kfree(tmpstr);
208                         return rc;
209                 }
210
211                 rc = libcfs_debug_str2mask(mask, tmpstr, is_subsys);
212                 /* Always print LBUG/LASSERT to console, so keep this mask */
213                 if (is_printk)
214                         *mask |= D_EMERG;
215         }
216
217         kfree(tmpstr);
218         return rc;
219 }
220
221 static int
222 proc_dobitmasks(struct ctl_table *table, int write,
223                 void __user *buffer, size_t *lenp, loff_t *ppos)
224 {
225         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
226                                     __proc_dobitmasks);
227 }
228
229 static int min_watchdog_ratelimit;              /* disable ratelimiting */
230 static int max_watchdog_ratelimit = (24*60*60); /* limit to once per day */
231
232 static int __proc_dump_kernel(void *data, int write,
233                               loff_t pos, void __user *buffer, int nob)
234 {
235         if (!write)
236                 return 0;
237
238         return cfs_trace_dump_debug_buffer_usrstr(buffer, nob);
239 }
240
241 static int
242 proc_dump_kernel(struct ctl_table *table, int write, void __user *buffer,
243                  size_t *lenp, loff_t *ppos)
244 {
245         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
246                                     __proc_dump_kernel);
247 }
248
249 static int __proc_daemon_file(void *data, int write,
250                               loff_t pos, void __user *buffer, int nob)
251 {
252         if (!write) {
253                 int len = strlen(cfs_tracefile);
254
255                 if (pos >= len)
256                         return 0;
257
258                 return cfs_trace_copyout_string(buffer, nob,
259                                                 cfs_tracefile + pos, "\n");
260         }
261
262         return cfs_trace_daemon_command_usrstr(buffer, nob);
263 }
264
265 static int
266 proc_daemon_file(struct ctl_table *table, int write, void __user *buffer,
267                  size_t *lenp, loff_t *ppos)
268 {
269         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
270                                     __proc_daemon_file);
271 }
272
273 static int __proc_debug_mb(void *data, int write,
274                            loff_t pos, void __user *buffer, int nob)
275 {
276         if (!write) {
277                 char tmpstr[32];
278                 int  len = snprintf(tmpstr, sizeof(tmpstr), "%d",
279                                     cfs_trace_get_debug_mb());
280
281                 if (pos >= len)
282                         return 0;
283
284                 return cfs_trace_copyout_string(buffer, nob, tmpstr + pos,
285                                                 "\n");
286         }
287
288         return cfs_trace_set_debug_mb_usrstr(buffer, nob);
289 }
290
291 static int
292 proc_debug_mb(struct ctl_table *table, int write, void __user *buffer,
293               size_t *lenp, loff_t *ppos)
294 {
295         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
296                                     __proc_debug_mb);
297 }
298
299 static int
300 proc_console_max_delay_cs(struct ctl_table *table, int write,
301                           void __user *buffer, size_t *lenp, loff_t *ppos)
302 {
303         int rc, max_delay_cs;
304         struct ctl_table dummy = *table;
305         cfs_duration_t d;
306
307         dummy.data = &max_delay_cs;
308         dummy.proc_handler = &proc_dointvec;
309
310         if (!write) { /* read */
311                 max_delay_cs = cfs_duration_sec(libcfs_console_max_delay * 100);
312                 rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
313                 return rc;
314         }
315
316         /* write */
317         max_delay_cs = 0;
318         rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
319         if (rc < 0)
320                 return rc;
321         if (max_delay_cs <= 0)
322                 return -EINVAL;
323
324         d = cfs_time_seconds(max_delay_cs) / 100;
325         if (d == 0 || d < libcfs_console_min_delay)
326                 return -EINVAL;
327         libcfs_console_max_delay = d;
328
329         return rc;
330 }
331
332 static int
333 proc_console_min_delay_cs(struct ctl_table *table, int write,
334                           void __user *buffer, size_t *lenp, loff_t *ppos)
335 {
336         int rc, min_delay_cs;
337         struct ctl_table dummy = *table;
338         cfs_duration_t d;
339
340         dummy.data = &min_delay_cs;
341         dummy.proc_handler = &proc_dointvec;
342
343         if (!write) { /* read */
344                 min_delay_cs = cfs_duration_sec(libcfs_console_min_delay * 100);
345                 rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
346                 return rc;
347         }
348
349         /* write */
350         min_delay_cs = 0;
351         rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
352         if (rc < 0)
353                 return rc;
354         if (min_delay_cs <= 0)
355                 return -EINVAL;
356
357         d = cfs_time_seconds(min_delay_cs) / 100;
358         if (d == 0 || d > libcfs_console_max_delay)
359                 return -EINVAL;
360         libcfs_console_min_delay = d;
361
362         return rc;
363 }
364
365 static int
366 proc_console_backoff(struct ctl_table *table, int write, void __user *buffer,
367                      size_t *lenp, loff_t *ppos)
368 {
369         int rc, backoff;
370         struct ctl_table dummy = *table;
371
372         dummy.data = &backoff;
373         dummy.proc_handler = &proc_dointvec;
374
375         if (!write) { /* read */
376                 backoff = libcfs_console_backoff;
377                 rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
378                 return rc;
379         }
380
381         /* write */
382         backoff = 0;
383         rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
384         if (rc < 0)
385                 return rc;
386
387         if (backoff <= 0)
388                 return -EINVAL;
389
390         libcfs_console_backoff = backoff;
391
392         return rc;
393 }
394
395 static int
396 libcfs_force_lbug(struct ctl_table *table, int write, void __user *buffer,
397                   size_t *lenp, loff_t *ppos)
398 {
399         if (write)
400                 LBUG();
401         return 0;
402 }
403
404 static int
405 proc_fail_loc(struct ctl_table *table, int write, void __user *buffer,
406               size_t *lenp, loff_t *ppos)
407 {
408         int rc;
409         long old_fail_loc = cfs_fail_loc;
410
411         rc = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
412         if (old_fail_loc != cfs_fail_loc)
413                 wake_up(&cfs_race_waitq);
414         return rc;
415 }
416
417 static int __proc_cpt_table(void *data, int write,
418                             loff_t pos, void __user *buffer, int nob)
419 {
420         char *buf = NULL;
421         int   len = 4096;
422         int   rc  = 0;
423
424         if (write)
425                 return -EPERM;
426
427         LASSERT(cfs_cpt_table != NULL);
428
429         while (1) {
430                 LIBCFS_ALLOC(buf, len);
431                 if (buf == NULL)
432                         return -ENOMEM;
433
434                 rc = cfs_cpt_table_print(cfs_cpt_table, buf, len);
435                 if (rc >= 0)
436                         break;
437
438                 if (rc == -EFBIG) {
439                         LIBCFS_FREE(buf, len);
440                         len <<= 1;
441                         continue;
442                 }
443                 goto out;
444         }
445
446         if (pos >= rc) {
447                 rc = 0;
448                 goto out;
449         }
450
451         rc = cfs_trace_copyout_string(buffer, nob, buf + pos, NULL);
452 out:
453         if (buf != NULL)
454                 LIBCFS_FREE(buf, len);
455         return rc;
456 }
457
458 static int
459 proc_cpt_table(struct ctl_table *table, int write, void __user *buffer,
460                size_t *lenp, loff_t *ppos)
461 {
462         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
463                                     __proc_cpt_table);
464 }
465
466 static struct ctl_table lnet_table[] = {
467         /*
468          * NB No .strategy entries have been provided since sysctl(8) prefers
469          * to go via /proc for portability.
470          */
471         {
472                 INIT_CTL_NAME
473                 .procname       = "debug",
474                 .data           = &libcfs_debug,
475                 .maxlen         = sizeof(int),
476                 .mode           = 0644,
477                 .proc_handler   = &proc_dobitmasks,
478         },
479         {
480                 INIT_CTL_NAME
481                 .procname       = "subsystem_debug",
482                 .data           = &libcfs_subsystem_debug,
483                 .maxlen         = sizeof(int),
484                 .mode           = 0644,
485                 .proc_handler   = &proc_dobitmasks,
486         },
487         {
488                 INIT_CTL_NAME
489                 .procname       = "printk",
490                 .data           = &libcfs_printk,
491                 .maxlen         = sizeof(int),
492                 .mode           = 0644,
493                 .proc_handler   = &proc_dobitmasks,
494         },
495         {
496                 INIT_CTL_NAME
497                 .procname       = "console_ratelimit",
498                 .data           = &libcfs_console_ratelimit,
499                 .maxlen         = sizeof(int),
500                 .mode           = 0644,
501                 .proc_handler   = &proc_dointvec
502         },
503         {
504                 INIT_CTL_NAME
505                 .procname       = "console_max_delay_centisecs",
506                 .maxlen         = sizeof(int),
507                 .mode           = 0644,
508                 .proc_handler   = &proc_console_max_delay_cs
509         },
510         {
511                 INIT_CTL_NAME
512                 .procname       = "console_min_delay_centisecs",
513                 .maxlen         = sizeof(int),
514                 .mode           = 0644,
515                 .proc_handler   = &proc_console_min_delay_cs
516         },
517         {
518                 INIT_CTL_NAME
519                 .procname       = "console_backoff",
520                 .maxlen         = sizeof(int),
521                 .mode           = 0644,
522                 .proc_handler   = &proc_console_backoff
523         },
524         {
525                 INIT_CTL_NAME
526                 .procname       = "debug_path",
527                 .data           = libcfs_debug_file_path_arr,
528                 .maxlen         = sizeof(libcfs_debug_file_path_arr),
529                 .mode           = 0644,
530                 .proc_handler   = &proc_dostring,
531         },
532         {
533                 INIT_CTL_NAME
534                 .procname       = "cpu_partition_table",
535                 .maxlen         = 128,
536                 .mode           = 0444,
537                 .proc_handler   = &proc_cpt_table,
538         },
539         {
540                 INIT_CTL_NAME
541                 .procname       = "debug_log_upcall",
542                 .data           = lnet_debug_log_upcall,
543                 .maxlen         = sizeof(lnet_debug_log_upcall),
544                 .mode           = 0644,
545                 .proc_handler   = &proc_dostring,
546         },
547         {
548                 INIT_CTL_NAME
549                 .procname       = "lnet_memused",
550                 .data           = (int *)&libcfs_kmemory.counter,
551                 .maxlen         = sizeof(int),
552                 .mode           = 0444,
553                 .proc_handler   = &proc_dointvec,
554         },
555         {
556                 INIT_CTL_NAME
557                 .procname       = "catastrophe",
558                 .data           = &libcfs_catastrophe,
559                 .maxlen         = sizeof(int),
560                 .mode           = 0444,
561                 .proc_handler   = &proc_dointvec,
562         },
563         {
564                 INIT_CTL_NAME
565                 .procname       = "panic_on_lbug",
566                 .data           = &libcfs_panic_on_lbug,
567                 .maxlen         = sizeof(int),
568                 .mode           = 0644,
569                 .proc_handler   = &proc_dointvec,
570         },
571         {
572                 INIT_CTL_NAME
573                 .procname       = "dump_kernel",
574                 .maxlen         = 256,
575                 .mode           = 0200,
576                 .proc_handler   = &proc_dump_kernel,
577         },
578         {
579                 INIT_CTL_NAME
580                 .procname       = "daemon_file",
581                 .mode           = 0644,
582                 .maxlen         = 256,
583                 .proc_handler   = &proc_daemon_file,
584         },
585         {
586                 INIT_CTL_NAME
587                 .procname       = "debug_mb",
588                 .mode           = 0644,
589                 .proc_handler   = &proc_debug_mb,
590         },
591         {
592                 INIT_CTL_NAME
593                 .procname       = "watchdog_ratelimit",
594                 .data           = &libcfs_watchdog_ratelimit,
595                 .maxlen         = sizeof(int),
596                 .mode           = 0644,
597                 .proc_handler   = &proc_dointvec_minmax,
598                 .extra1         = &min_watchdog_ratelimit,
599                 .extra2         = &max_watchdog_ratelimit,
600         },
601         {
602                 INIT_CTL_NAME
603                 .procname       = "force_lbug",
604                 .data           = NULL,
605                 .maxlen         = 0,
606                 .mode           = 0200,
607                 .proc_handler   = &libcfs_force_lbug
608         },
609         {
610                 INIT_CTL_NAME
611                 .procname       = "fail_loc",
612                 .data           = &cfs_fail_loc,
613                 .maxlen         = sizeof(cfs_fail_loc),
614                 .mode           = 0644,
615                 .proc_handler   = &proc_fail_loc
616         },
617         {
618                 INIT_CTL_NAME
619                 .procname       = "fail_val",
620                 .data           = &cfs_fail_val,
621                 .maxlen         = sizeof(int),
622                 .mode           = 0644,
623                 .proc_handler   = &proc_dointvec
624         },
625         {
626                 INIT_CTL_NAME
627                 .procname       = "fail_err",
628                 .data           = &cfs_fail_err,
629                 .maxlen         = sizeof(cfs_fail_err),
630                 .mode           = 0644,
631                 .proc_handler   = &proc_dointvec,
632         },
633         {
634         }
635 };
636
637 #ifdef CONFIG_SYSCTL
638 static struct ctl_table top_table[] = {
639         {
640                 INIT_CTL_NAME
641                 .procname       = "lnet",
642                 .mode           = 0555,
643                 .data           = NULL,
644                 .maxlen         = 0,
645                 .child          = lnet_table,
646         },
647         { 0 }
648 };
649 #endif
650
651 static int insert_proc(void)
652 {
653 #ifdef CONFIG_SYSCTL
654         if (lnet_table_header == NULL)
655                 lnet_table_header = register_sysctl_table(top_table);
656 #endif
657         return 0;
658 }
659
660 static void remove_proc(void)
661 {
662 #ifdef CONFIG_SYSCTL
663         if (lnet_table_header != NULL)
664                 unregister_sysctl_table(lnet_table_header);
665
666         lnet_table_header = NULL;
667 #endif
668 }
669
670 static int __init libcfs_init(void)
671 {
672         int rc;
673
674         rc = libcfs_debug_init(5 * 1024 * 1024);
675         if (rc < 0) {
676                 printk(KERN_ERR "LustreError: libcfs_debug_init: %d\n", rc);
677                 return (rc);
678         }
679
680         rc = cfs_cpu_init();
681         if (rc != 0)
682                 goto cleanup_debug;
683
684         rc = misc_register(&libcfs_dev);
685         if (rc) {
686                 CERROR("misc_register: error %d\n", rc);
687                 goto cleanup_cpu;
688         }
689
690         rc = cfs_wi_startup();
691         if (rc) {
692                 CERROR("initialize workitem: error %d\n", rc);
693                 goto cleanup_deregister;
694         }
695
696         /* max to 4 threads, should be enough for rehash */
697         rc = min(cfs_cpt_weight(cfs_cpt_table, CFS_CPT_ANY), 4);
698         rc = cfs_wi_sched_create("cfs_rh", cfs_cpt_table, CFS_CPT_ANY,
699                                  rc, &cfs_sched_rehash);
700         if (rc != 0) {
701                 CERROR("Startup workitem scheduler: error: %d\n", rc);
702                 goto cleanup_deregister;
703         }
704
705         rc = cfs_crypto_register();
706         if (rc) {
707                 CERROR("cfs_crypto_regster: error %d\n", rc);
708                 goto cleanup_wi;
709         }
710
711
712         rc = insert_proc();
713         if (rc) {
714                 CERROR("insert_proc: error %d\n", rc);
715                 goto cleanup_crypto;
716         }
717
718         CDEBUG (D_OTHER, "portals setup OK\n");
719         return 0;
720 cleanup_crypto:
721         cfs_crypto_unregister();
722 cleanup_wi:
723         cfs_wi_shutdown();
724 cleanup_deregister:
725         misc_deregister(&libcfs_dev);
726 cleanup_cpu:
727         cfs_cpu_fini();
728 cleanup_debug:
729         libcfs_debug_cleanup();
730         return rc;
731 }
732
733 static void __exit libcfs_exit(void)
734 {
735         int rc;
736
737         remove_proc();
738
739         CDEBUG(D_MALLOC, "before Portals cleanup: kmem %d\n",
740                atomic_read(&libcfs_kmemory));
741
742         if (cfs_sched_rehash != NULL) {
743                 cfs_wi_sched_destroy(cfs_sched_rehash);
744                 cfs_sched_rehash = NULL;
745         }
746
747         cfs_crypto_unregister();
748         cfs_wi_shutdown();
749
750         misc_deregister(&libcfs_dev);
751
752         cfs_cpu_fini();
753
754         if (atomic_read(&libcfs_kmemory) != 0)
755                 CERROR("Portals memory leaked: %d bytes\n",
756                        atomic_read(&libcfs_kmemory));
757
758         rc = libcfs_debug_cleanup();
759         if (rc)
760                 printk(KERN_ERR "LustreError: libcfs_debug_cleanup: %d\n",
761                        rc);
762 }
763
764 MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
765 MODULE_DESCRIPTION("Lustre helper library");
766 MODULE_VERSION(LIBCFS_VERSION);
767 MODULE_LICENSE("GPL");
768
769 module_init(libcfs_init);
770 module_exit(libcfs_exit);