Whamcloud - gitweb
b84f586af5f38aa4e8ea0a086dad5e6934d2acc5
[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, 2017, 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/miscdevice.h>
33 #include <linux/module.h>
34 #include <linux/kernel.h>
35 #include <linux/mm.h>
36 #include <linux/string.h>
37 #include <linux/stat.h>
38 #include <linux/errno.h>
39 #include <linux/unistd.h>
40 #include <net/sock.h>
41 #include <linux/uio.h>
42 #include <linux/uaccess.h>
43
44 #include <linux/fs.h>
45 #include <linux/file.h>
46 #include <linux/list.h>
47
48 #include <linux/sysctl.h>
49 #include <linux/debugfs.h>
50 #include <asm/div64.h>
51
52 #define DEBUG_SUBSYSTEM S_LNET
53
54 #include <libcfs/libcfs.h>
55 #include <libcfs/libcfs_crypto.h>
56 #include <lnet/lib-lnet.h>
57 #include "tracefile.h"
58
59 static struct dentry *lnet_debugfs_root;
60
61 BLOCKING_NOTIFIER_HEAD(libcfs_ioctl_list);
62 EXPORT_SYMBOL(libcfs_ioctl_list);
63
64 static int libcfs_ioctl(unsigned long cmd, void __user *uparam)
65 {
66         struct libcfs_ioctl_data *data = NULL;
67         struct libcfs_ioctl_hdr  *hdr;
68         int                       err;
69         ENTRY;
70
71         /* 'cmd' and permissions get checked in our arch-specific caller */
72         err = libcfs_ioctl_getdata(&hdr, uparam);
73         if (err != 0) {
74                 CDEBUG_LIMIT(D_ERROR,
75                              "libcfs ioctl: data header error %d\n", err);
76                 RETURN(err);
77         }
78
79         if (hdr->ioc_version == LIBCFS_IOCTL_VERSION) {
80                 /* The libcfs_ioctl_data_adjust() function performs adjustment
81                  * operations on the libcfs_ioctl_data structure to make
82                  * it usable by the code.  This doesn't need to be called
83                  * for new data structures added. */
84                 data = container_of(hdr, struct libcfs_ioctl_data, ioc_hdr);
85                 err = libcfs_ioctl_data_adjust(data);
86                 if (err != 0)
87                         GOTO(out, err);
88         }
89
90         CDEBUG(D_IOCTL, "libcfs ioctl cmd %lu\n", cmd);
91         switch (cmd) {
92         case IOC_LIBCFS_CLEAR_DEBUG:
93                 libcfs_debug_clear_buffer();
94                 break;
95         case IOC_LIBCFS_MARK_DEBUG:
96                 if (data == NULL ||
97                     data->ioc_inlbuf1 == NULL ||
98                     data->ioc_inlbuf1[data->ioc_inllen1 - 1] != '\0')
99                         GOTO(out, err = -EINVAL);
100
101                 libcfs_debug_mark_buffer(data->ioc_inlbuf1);
102                 break;
103
104         default:
105                 err = blocking_notifier_call_chain(&libcfs_ioctl_list,
106                                                    cmd, hdr);
107                 if (!(err & NOTIFY_STOP_MASK))
108                         /* No-one claimed the ioctl */
109                         err = -EINVAL;
110                 else
111                         err = notifier_to_errno(err);
112                 if (!err)
113                         if (copy_to_user(uparam, hdr, hdr->ioc_len))
114                                 err = -EFAULT;
115                 break;
116         }
117 out:
118         LIBCFS_FREE(hdr, hdr->ioc_len);
119         RETURN(err);
120 }
121
122 static long
123 libcfs_psdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
124 {
125         if (!capable(CAP_SYS_ADMIN))
126                 return -EACCES;
127
128         if (_IOC_TYPE(cmd) != IOC_LIBCFS_TYPE ||
129             _IOC_NR(cmd) < IOC_LIBCFS_MIN_NR  ||
130             _IOC_NR(cmd) > IOC_LIBCFS_MAX_NR) {
131                 CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n",
132                        _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
133                 return -EINVAL;
134         }
135
136         return libcfs_ioctl(cmd, (void __user *)arg);
137 }
138
139 static const struct file_operations libcfs_fops = {
140         .owner                  = THIS_MODULE,
141         .unlocked_ioctl         = libcfs_psdev_ioctl,
142 };
143
144 static struct miscdevice libcfs_dev = {
145         .minor                  = MISC_DYNAMIC_MINOR,
146         .name                   = "lnet",
147         .fops                   = &libcfs_fops,
148 };
149
150 int lprocfs_call_handler(void *data, int write, loff_t *ppos,
151                          void __user *buffer, size_t *lenp,
152                          int (*handler)(void *data, int write, loff_t pos,
153                                         void __user *buffer, int len))
154 {
155         int rc = handler(data, write, *ppos, buffer, *lenp);
156
157         if (rc < 0)
158                 return rc;
159
160         if (write) {
161                 *ppos += *lenp;
162         } else {
163                 *lenp = rc;
164                 *ppos += rc;
165         }
166         return 0;
167 }
168 EXPORT_SYMBOL(lprocfs_call_handler);
169
170 static int __proc_dobitmasks(void *data, int write,
171                              loff_t pos, void __user *buffer, int nob)
172 {
173         const int     tmpstrlen = 512;
174         char         *tmpstr;
175         int           rc;
176         unsigned int *mask = data;
177         int           is_subsys = (mask == &libcfs_subsystem_debug) ? 1 : 0;
178         int           is_printk = (mask == &libcfs_printk) ? 1 : 0;
179
180         rc = cfs_trace_allocate_string_buffer(&tmpstr, tmpstrlen);
181         if (rc < 0)
182                 return rc;
183
184         if (!write) {
185                 libcfs_debug_mask2str(tmpstr, tmpstrlen, *mask, is_subsys);
186                 rc = strlen(tmpstr);
187
188                 if (pos >= rc) {
189                         rc = 0;
190                 } else {
191                         rc = cfs_trace_copyout_string(buffer, nob,
192                                                       tmpstr + pos, "\n");
193                 }
194         } else {
195                 rc = cfs_trace_copyin_string(tmpstr, tmpstrlen, buffer, nob);
196                 if (rc < 0) {
197                         kfree(tmpstr);
198                         return rc;
199                 }
200
201                 rc = libcfs_debug_str2mask(mask, tmpstr, is_subsys);
202                 /* Always print LBUG/LASSERT to console, so keep this mask */
203                 if (is_printk)
204                         *mask |= D_EMERG;
205         }
206
207         kfree(tmpstr);
208         return rc;
209 }
210
211 static int proc_dobitmasks(struct ctl_table *table, int write,
212                            void __user *buffer, size_t *lenp, loff_t *ppos)
213 {
214         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
215                                     __proc_dobitmasks);
216 }
217
218 static int min_watchdog_ratelimit;              /* disable ratelimiting */
219 static int max_watchdog_ratelimit = (24*60*60); /* limit to once per day */
220
221 static int __proc_dump_kernel(void *data, int write,
222                               loff_t pos, void __user *buffer, int nob)
223 {
224         if (!write)
225                 return 0;
226
227         return cfs_trace_dump_debug_buffer_usrstr(buffer, nob);
228 }
229
230 static int proc_dump_kernel(struct ctl_table *table, int write,
231                             void __user *buffer, size_t *lenp, loff_t *ppos)
232 {
233         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
234                                     __proc_dump_kernel);
235 }
236
237 static int __proc_daemon_file(void *data, int write,
238                               loff_t pos, void __user *buffer, int nob)
239 {
240         if (!write) {
241                 int len = strlen(cfs_tracefile);
242
243                 if (pos >= len)
244                         return 0;
245
246                 return cfs_trace_copyout_string(buffer, nob,
247                                                 cfs_tracefile + pos, "\n");
248         }
249
250         return cfs_trace_daemon_command_usrstr(buffer, nob);
251 }
252
253 static int proc_daemon_file(struct ctl_table *table, int write,
254                             void __user *buffer, size_t *lenp, loff_t *ppos)
255 {
256         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
257                                     __proc_daemon_file);
258 }
259
260 static int libcfs_force_lbug(struct ctl_table *table, int write,
261                              void __user *buffer,
262                              size_t *lenp, loff_t *ppos)
263 {
264         if (write)
265                 LBUG();
266         return 0;
267 }
268
269 static int proc_fail_loc(struct ctl_table *table, int write,
270                          void __user *buffer, size_t *lenp, loff_t *ppos)
271 {
272         int rc;
273         long old_fail_loc = cfs_fail_loc;
274
275         rc = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
276         if (old_fail_loc != cfs_fail_loc)
277                 wake_up(&cfs_race_waitq);
278         return rc;
279 }
280
281 static int __proc_cpt_table(void *data, int write,
282                             loff_t pos, void __user *buffer, int nob)
283 {
284         char *buf = NULL;
285         int   len = 4096;
286         int   rc  = 0;
287
288         if (write)
289                 return -EPERM;
290
291         LASSERT(cfs_cpt_table != NULL);
292
293         while (1) {
294                 LIBCFS_ALLOC(buf, len);
295                 if (buf == NULL)
296                         return -ENOMEM;
297
298                 rc = cfs_cpt_table_print(cfs_cpt_table, buf, len);
299                 if (rc >= 0)
300                         break;
301
302                 if (rc == -EFBIG) {
303                         LIBCFS_FREE(buf, len);
304                         len <<= 1;
305                         continue;
306                 }
307                 goto out;
308         }
309
310         if (pos >= rc) {
311                 rc = 0;
312                 goto out;
313         }
314
315         rc = cfs_trace_copyout_string(buffer, nob, buf + pos, NULL);
316 out:
317         if (buf != NULL)
318                 LIBCFS_FREE(buf, len);
319         return rc;
320 }
321
322 static int proc_cpt_table(struct ctl_table *table, int write,
323                           void __user *buffer, size_t *lenp, loff_t *ppos)
324 {
325         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
326                                     __proc_cpt_table);
327 }
328
329 static int __proc_cpt_distance(void *data, int write,
330                                loff_t pos, void __user *buffer, int nob)
331 {
332         char *buf = NULL;
333         int   len = 4096;
334         int   rc  = 0;
335
336         if (write)
337                 return -EPERM;
338
339         LASSERT(cfs_cpt_table != NULL);
340
341         while (1) {
342                 LIBCFS_ALLOC(buf, len);
343                 if (buf == NULL)
344                         return -ENOMEM;
345
346                 rc = cfs_cpt_distance_print(cfs_cpt_table, buf, len);
347                 if (rc >= 0)
348                         break;
349
350                 if (rc == -EFBIG) {
351                         LIBCFS_FREE(buf, len);
352                         len <<= 1;
353                         continue;
354                 }
355                 goto out;
356         }
357
358         if (pos >= rc) {
359                 rc = 0;
360                 goto out;
361         }
362
363         rc = cfs_trace_copyout_string(buffer, nob, buf + pos, NULL);
364  out:
365         if (buf != NULL)
366                 LIBCFS_FREE(buf, len);
367         return rc;
368 }
369
370 static int proc_cpt_distance(struct ctl_table *table, int write,
371                              void __user *buffer, size_t *lenp, loff_t *ppos)
372 {
373         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
374                                      __proc_cpt_distance);
375 }
376
377 static struct ctl_table lnet_table[] = {
378         {
379                 INIT_CTL_NAME
380                 .procname       = "debug",
381                 .data           = &libcfs_debug,
382                 .maxlen         = sizeof(int),
383                 .mode           = 0644,
384                 .proc_handler   = &proc_dobitmasks,
385         },
386         {
387                 INIT_CTL_NAME
388                 .procname       = "subsystem_debug",
389                 .data           = &libcfs_subsystem_debug,
390                 .maxlen         = sizeof(int),
391                 .mode           = 0644,
392                 .proc_handler   = &proc_dobitmasks,
393         },
394         {
395                 INIT_CTL_NAME
396                 .procname       = "printk",
397                 .data           = &libcfs_printk,
398                 .maxlen         = sizeof(int),
399                 .mode           = 0644,
400                 .proc_handler   = &proc_dobitmasks,
401         },
402         {
403                 INIT_CTL_NAME
404                 .procname       = "cpu_partition_table",
405                 .maxlen         = 128,
406                 .mode           = 0444,
407                 .proc_handler   = &proc_cpt_table,
408         },
409         {
410                 INIT_CTL_NAME
411                 .procname       = "cpu_partition_distance",
412                 .maxlen         = 128,
413                 .mode           = 0444,
414                 .proc_handler   = &proc_cpt_distance,
415         },
416         {
417                 INIT_CTL_NAME
418                 .procname       = "debug_log_upcall",
419                 .data           = lnet_debug_log_upcall,
420                 .maxlen         = sizeof(lnet_debug_log_upcall),
421                 .mode           = 0644,
422                 .proc_handler   = &proc_dostring,
423         },
424         {
425                 INIT_CTL_NAME
426                 .procname       = "lnet_memused",
427                 .data           = (int *)&libcfs_kmemory.counter,
428                 .maxlen         = sizeof(int),
429                 .mode           = 0444,
430                 .proc_handler   = &proc_dointvec,
431         },
432         {
433                 INIT_CTL_NAME
434                 .procname       = "catastrophe",
435                 .data           = &libcfs_catastrophe,
436                 .maxlen         = sizeof(int),
437                 .mode           = 0444,
438                 .proc_handler   = &proc_dointvec,
439         },
440         {
441                 INIT_CTL_NAME
442                 .procname       = "dump_kernel",
443                 .maxlen         = 256,
444                 .mode           = 0200,
445                 .proc_handler   = &proc_dump_kernel,
446         },
447         {
448                 INIT_CTL_NAME
449                 .procname       = "daemon_file",
450                 .mode           = 0644,
451                 .maxlen         = 256,
452                 .proc_handler   = &proc_daemon_file,
453         },
454         {
455                 INIT_CTL_NAME
456                 .procname       = "watchdog_ratelimit",
457                 .data           = &libcfs_watchdog_ratelimit,
458                 .maxlen         = sizeof(int),
459                 .mode           = 0644,
460                 .proc_handler   = &proc_dointvec_minmax,
461                 .extra1         = &min_watchdog_ratelimit,
462                 .extra2         = &max_watchdog_ratelimit,
463         },
464         {
465                 INIT_CTL_NAME
466                 .procname       = "force_lbug",
467                 .data           = NULL,
468                 .maxlen         = 0,
469                 .mode           = 0200,
470                 .proc_handler   = &libcfs_force_lbug
471         },
472         {
473                 INIT_CTL_NAME
474                 .procname       = "fail_loc",
475                 .data           = &cfs_fail_loc,
476                 .maxlen         = sizeof(cfs_fail_loc),
477                 .mode           = 0644,
478                 .proc_handler   = &proc_fail_loc
479         },
480         {
481                 INIT_CTL_NAME
482                 .procname       = "fail_val",
483                 .data           = &cfs_fail_val,
484                 .maxlen         = sizeof(int),
485                 .mode           = 0644,
486                 .proc_handler   = &proc_dointvec
487         },
488         {
489                 INIT_CTL_NAME
490                 .procname       = "fail_err",
491                 .data           = &cfs_fail_err,
492                 .maxlen         = sizeof(cfs_fail_err),
493                 .mode           = 0644,
494                 .proc_handler   = &proc_dointvec,
495         },
496         {
497         }
498 };
499
500 static const struct lnet_debugfs_symlink_def lnet_debugfs_symlinks[] = {
501         { .name         = "console_ratelimit",
502           .target       = "../../../module/libcfs/parameters/libcfs_console_ratelimit" },
503         { .name         = "debug_path",
504           .target       = "../../../module/libcfs/parameters/libcfs_debug_file_path" },
505         { .name         = "panic_on_lbug",
506           .target       = "../../../module/libcfs/parameters/libcfs_panic_on_lbug" },
507         { .name         = "console_backoff",
508           .target       = "../../../module/libcfs/parameters/libcfs_console_backoff" },
509         { .name         = "debug_mb",
510           .target       = "../../../module/libcfs/parameters/libcfs_debug_mb" },
511         { .name         = "console_min_delay_centisecs",
512           .target       = "../../../module/libcfs/parameters/libcfs_console_min_delay" },
513         { .name         = "console_max_delay_centisecs",
514           .target       = "../../../module/libcfs/parameters/libcfs_console_max_delay" },
515         { .name         = NULL },
516 };
517
518 static ssize_t lnet_debugfs_read(struct file *filp, char __user *buf,
519                                  size_t count, loff_t *ppos)
520 {
521         struct ctl_table *table = filp->private_data;
522         ssize_t rc = -EINVAL;
523
524         if (table) {
525                 rc = table->proc_handler(table, 0, buf, &count, ppos);
526                 if (!rc)
527                         rc = count;
528         }
529
530         return rc;
531 }
532
533 static ssize_t lnet_debugfs_write(struct file *filp, const char __user *buf,
534                                   size_t count, loff_t *ppos)
535 {
536         struct ctl_table *table = filp->private_data;
537         ssize_t rc = -EINVAL;
538
539         if (table) {
540                 rc = table->proc_handler(table, 1, (void __user *)buf, &count,
541                                          ppos);
542                 if (!rc)
543                         rc = count;
544         }
545
546         return rc;
547 }
548
549 static const struct file_operations lnet_debugfs_file_operations_rw = {
550         .open           = simple_open,
551         .read           = lnet_debugfs_read,
552         .write          = lnet_debugfs_write,
553         .llseek         = default_llseek,
554 };
555
556 static const struct file_operations lnet_debugfs_file_operations_ro = {
557         .open           = simple_open,
558         .read           = lnet_debugfs_read,
559         .llseek         = default_llseek,
560 };
561
562 static const struct file_operations lnet_debugfs_file_operations_wo = {
563         .open           = simple_open,
564         .write          = lnet_debugfs_write,
565         .llseek         = default_llseek,
566 };
567
568 static const struct file_operations *lnet_debugfs_fops_select(umode_t mode)
569 {
570         if (!(mode & S_IWUGO))
571                 return &lnet_debugfs_file_operations_ro;
572
573         if (!(mode & S_IRUGO))
574                 return &lnet_debugfs_file_operations_wo;
575
576         return &lnet_debugfs_file_operations_rw;
577 }
578
579 void lnet_insert_debugfs(struct ctl_table *table)
580 {
581         if (!lnet_debugfs_root)
582                 lnet_debugfs_root = debugfs_create_dir("lnet", NULL);
583
584         /* Even if we cannot create, just ignore it altogether) */
585         if (IS_ERR_OR_NULL(lnet_debugfs_root))
586                 return;
587
588         /* We don't save the dentry returned in next two calls, because
589          * we don't call debugfs_remove() but rather remove_recursive()
590          */
591         for (; table && table->procname; table++)
592                 debugfs_create_file(table->procname, table->mode,
593                                     lnet_debugfs_root, table,
594                                     lnet_debugfs_fops_select(table->mode));
595 }
596 EXPORT_SYMBOL_GPL(lnet_insert_debugfs);
597
598 static void lnet_insert_debugfs_links(
599                 const struct lnet_debugfs_symlink_def *symlinks)
600 {
601         for (; symlinks && symlinks->name; symlinks++)
602                 debugfs_create_symlink(symlinks->name, lnet_debugfs_root,
603                                        symlinks->target);
604 }
605
606 void lnet_remove_debugfs(struct ctl_table *table)
607 {
608         for (; table && table->procname; table++) {
609                 struct qstr dname = QSTR_INIT(table->procname,
610                                               strlen(table->procname));
611                 struct dentry *dentry;
612
613                 dentry = d_hash_and_lookup(lnet_debugfs_root, &dname);
614                 debugfs_remove(dentry);
615         }
616 }
617 EXPORT_SYMBOL_GPL(lnet_remove_debugfs);
618
619 static int __init libcfs_init(void)
620 {
621         int rc;
622
623 #ifndef HAVE_WAIT_VAR_EVENT
624         wait_bit_init();
625 #endif
626         rc = libcfs_debug_init(5 * 1024 * 1024);
627         if (rc < 0) {
628                 printk(KERN_ERR "LustreError: libcfs_debug_init: %d\n", rc);
629                 return (rc);
630         }
631
632         rc = cfs_cpu_init();
633         if (rc != 0)
634                 goto cleanup_debug;
635
636         rc = misc_register(&libcfs_dev);
637         if (rc) {
638                 CERROR("misc_register: error %d\n", rc);
639                 goto cleanup_cpu;
640         }
641
642         rc = cfs_wi_startup();
643         if (rc) {
644                 CERROR("initialize workitem: error %d\n", rc);
645                 goto cleanup_deregister;
646         }
647
648         cfs_rehash_wq = alloc_workqueue("cfs_rh", WQ_SYSFS, 4);
649         if (!cfs_rehash_wq) {
650                 rc = -ENOMEM;
651                 CERROR("libcfs: failed to start rehash workqueue: rc = %d\n",
652                        rc);
653                 goto cleanup_deregister;
654         }
655
656         rc = cfs_crypto_register();
657         if (rc) {
658                 CERROR("cfs_crypto_regster: error %d\n", rc);
659                 goto cleanup_wi;
660         }
661
662         lnet_insert_debugfs(lnet_table);
663         if (!IS_ERR_OR_NULL(lnet_debugfs_root))
664                 lnet_insert_debugfs_links(lnet_debugfs_symlinks);
665
666         CDEBUG (D_OTHER, "portals setup OK\n");
667         return 0;
668 cleanup_wi:
669         cfs_wi_shutdown();
670 cleanup_deregister:
671         misc_deregister(&libcfs_dev);
672 cleanup_cpu:
673         cfs_cpu_fini();
674 cleanup_debug:
675         libcfs_debug_cleanup();
676         return rc;
677 }
678
679 static void __exit libcfs_exit(void)
680 {
681         int rc;
682
683         /* Remove everthing */
684         debugfs_remove_recursive(lnet_debugfs_root);
685         lnet_debugfs_root = NULL;
686
687         CDEBUG(D_MALLOC, "before Portals cleanup: kmem %d\n",
688                atomic_read(&libcfs_kmemory));
689
690         if (cfs_rehash_wq) {
691                 destroy_workqueue(cfs_rehash_wq);
692                 cfs_rehash_wq = NULL;
693         }
694
695         cfs_crypto_unregister();
696         cfs_wi_shutdown();
697
698         misc_deregister(&libcfs_dev);
699
700         cfs_cpu_fini();
701
702         /* the below message is checked in test-framework.sh check_mem_leak() */
703         if (atomic_read(&libcfs_kmemory) != 0)
704                 CERROR("Portals memory leaked: %d bytes\n",
705                        atomic_read(&libcfs_kmemory));
706
707         rc = libcfs_debug_cleanup();
708         if (rc)
709                 printk(KERN_ERR "LustreError: libcfs_debug_cleanup: %d\n",
710                        rc);
711 }
712
713 MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
714 MODULE_DESCRIPTION("Lustre helper library");
715 MODULE_VERSION(LIBCFS_VERSION);
716 MODULE_LICENSE("GPL");
717
718 module_init(libcfs_init);
719 module_exit(libcfs_exit);