Whamcloud - gitweb
0554cc9a6f4bd4d0cd96285fc2ed7726eea25c2c
[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  */
31 #include <linux/miscdevice.h>
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/debugfs.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 <libcfs/crypto/llcrypt.h>
57 #include "tracefile.h"
58
59 struct lnet_debugfs_symlink_def {
60         const char *name;
61         const char *target;
62 };
63
64 static struct dentry *lnet_debugfs_root;
65
66 BLOCKING_NOTIFIER_HEAD(libcfs_ioctl_list);
67 EXPORT_SYMBOL(libcfs_ioctl_list);
68
69 static inline size_t libcfs_ioctl_packlen(struct libcfs_ioctl_data *data)
70 {
71         size_t len = sizeof(*data);
72
73         len += (data->ioc_inllen1 + 7) & ~7;
74         len += (data->ioc_inllen2 + 7) & ~7;
75         return len;
76 }
77
78 static bool libcfs_ioctl_is_invalid(struct libcfs_ioctl_data *data)
79 {
80         const int maxlen = 1 << 30;
81         if (data->ioc_hdr.ioc_len > maxlen)
82                 return true;
83
84         if (data->ioc_inllen1 > maxlen)
85                 return true;
86
87         if (data->ioc_inllen2 > maxlen)
88                 return true;
89
90         if (data->ioc_inlbuf1 && !data->ioc_inllen1)
91                 return true;
92
93         if (data->ioc_inlbuf2 && !data->ioc_inllen2)
94                 return true;
95
96         if (data->ioc_pbuf1 && !data->ioc_plen1)
97                 return true;
98
99         if (data->ioc_pbuf2 && !data->ioc_plen2)
100                 return true;
101
102         if (data->ioc_plen1 && !data->ioc_pbuf1)
103                 return true;
104
105         if (data->ioc_plen2 && !data->ioc_pbuf2)
106                 return true;
107
108         if (libcfs_ioctl_packlen(data) != data->ioc_hdr.ioc_len)
109                 return true;
110
111         if (data->ioc_inllen1 &&
112                 data->ioc_bulk[((data->ioc_inllen1 + 7) & ~7) +
113                                data->ioc_inllen2 - 1] != '\0')
114                 return true;
115
116         return false;
117 }
118
119 int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data)
120 {
121         ENTRY;
122
123         if (libcfs_ioctl_is_invalid(data)) {
124                 CERROR("libcfs ioctl: parameter not correctly formatted\n");
125                 RETURN(-EINVAL);
126         }
127
128         if (data->ioc_inllen1 != 0)
129                 data->ioc_inlbuf1 = &data->ioc_bulk[0];
130
131         if (data->ioc_inllen2 != 0)
132                 data->ioc_inlbuf2 = &data->ioc_bulk[0] +
133                                     cfs_size_round(data->ioc_inllen1);
134
135         RETURN(0);
136 }
137
138 int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp,
139                          struct libcfs_ioctl_hdr __user *uhdr)
140 {
141         struct libcfs_ioctl_hdr hdr;
142         int err;
143
144         ENTRY;
145         if (copy_from_user(&hdr, uhdr, sizeof(hdr)))
146                 RETURN(-EFAULT);
147
148         if (hdr.ioc_version != LIBCFS_IOCTL_VERSION &&
149             hdr.ioc_version != LIBCFS_IOCTL_VERSION2) {
150                 CERROR("libcfs ioctl: version mismatch expected %#x, got %#x\n",
151                        LIBCFS_IOCTL_VERSION, hdr.ioc_version);
152                 RETURN(-EINVAL);
153         }
154
155         if (hdr.ioc_len < sizeof(struct libcfs_ioctl_hdr)) {
156                 CERROR("libcfs ioctl: user buffer too small for ioctl\n");
157                 RETURN(-EINVAL);
158         }
159
160         if (hdr.ioc_len > LIBCFS_IOC_DATA_MAX) {
161                 CERROR("libcfs ioctl: user buffer is too large %d/%d\n",
162                        hdr.ioc_len, LIBCFS_IOC_DATA_MAX);
163                 RETURN(-EINVAL);
164         }
165
166         LIBCFS_ALLOC(*hdr_pp, hdr.ioc_len);
167         if (*hdr_pp == NULL)
168                 RETURN(-ENOMEM);
169
170         if (copy_from_user(*hdr_pp, uhdr, hdr.ioc_len))
171                 GOTO(free, err = -EFAULT);
172
173         if ((*hdr_pp)->ioc_version != hdr.ioc_version ||
174                 (*hdr_pp)->ioc_len != hdr.ioc_len) {
175                 GOTO(free, err = -EINVAL);
176         }
177
178         RETURN(0);
179
180 free:
181         LIBCFS_FREE(*hdr_pp, hdr.ioc_len);
182         RETURN(err);
183 }
184
185 static int libcfs_ioctl(unsigned long cmd, void __user *uparam)
186 {
187         struct libcfs_ioctl_data *data = NULL;
188         struct libcfs_ioctl_hdr  *hdr;
189         int                       err;
190         ENTRY;
191
192         /* 'cmd' and permissions get checked in our arch-specific caller */
193         err = libcfs_ioctl_getdata(&hdr, uparam);
194         if (err != 0) {
195                 CDEBUG_LIMIT(D_ERROR,
196                              "libcfs ioctl: data header error %d\n", err);
197                 RETURN(err);
198         }
199
200         if (hdr->ioc_version == LIBCFS_IOCTL_VERSION) {
201                 /* The libcfs_ioctl_data_adjust() function performs adjustment
202                  * operations on the libcfs_ioctl_data structure to make
203                  * it usable by the code.  This doesn't need to be called
204                  * for new data structures added. */
205                 data = container_of(hdr, struct libcfs_ioctl_data, ioc_hdr);
206                 err = libcfs_ioctl_data_adjust(data);
207                 if (err != 0)
208                         GOTO(out, err);
209         }
210
211         CDEBUG(D_IOCTL, "libcfs ioctl cmd %lu\n", cmd);
212         switch (cmd) {
213         case IOC_LIBCFS_CLEAR_DEBUG:
214                 libcfs_debug_clear_buffer();
215                 break;
216         case IOC_LIBCFS_MARK_DEBUG:
217                 if (data == NULL ||
218                     data->ioc_inlbuf1 == NULL ||
219                     data->ioc_inlbuf1[data->ioc_inllen1 - 1] != '\0')
220                         GOTO(out, err = -EINVAL);
221
222                 libcfs_debug_mark_buffer(data->ioc_inlbuf1);
223                 break;
224
225         default:
226                 err = blocking_notifier_call_chain(&libcfs_ioctl_list,
227                                                    cmd, hdr);
228                 if (!(err & NOTIFY_STOP_MASK))
229                         /* No-one claimed the ioctl */
230                         err = -EINVAL;
231                 else
232                         err = notifier_to_errno(err);
233                 if (copy_to_user(uparam, hdr, hdr->ioc_len) && !err)
234                         err = -EFAULT;
235                 break;
236         }
237 out:
238         LIBCFS_FREE(hdr, hdr->ioc_len);
239         RETURN(err);
240 }
241
242 static long
243 libcfs_psdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
244 {
245         if (!capable(CAP_SYS_ADMIN))
246                 return -EACCES;
247
248         if (_IOC_TYPE(cmd) != IOC_LIBCFS_TYPE ||
249             _IOC_NR(cmd) < IOC_LIBCFS_MIN_NR  ||
250             _IOC_NR(cmd) > IOC_LIBCFS_MAX_NR) {
251                 CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n",
252                        _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
253                 return -EINVAL;
254         }
255
256         return libcfs_ioctl(cmd, (void __user *)arg);
257 }
258
259 static const struct file_operations libcfs_fops = {
260         .owner                  = THIS_MODULE,
261         .unlocked_ioctl         = libcfs_psdev_ioctl,
262 };
263
264 static struct miscdevice libcfs_dev = {
265         .minor                  = MISC_DYNAMIC_MINOR,
266         .name                   = "lnet",
267         .fops                   = &libcfs_fops,
268 };
269
270 int lprocfs_call_handler(void *data, int write, loff_t *ppos,
271                          void __user *buffer, size_t *lenp,
272                          int (*handler)(void *data, int write, loff_t pos,
273                                         void __user *buffer, int len))
274 {
275         int rc = handler(data, write, *ppos, buffer, *lenp);
276
277         if (rc < 0)
278                 return rc;
279
280         if (write) {
281                 *ppos += *lenp;
282         } else {
283                 *lenp = rc;
284                 *ppos += rc;
285         }
286         return 0;
287 }
288 EXPORT_SYMBOL(lprocfs_call_handler);
289
290 static int __proc_dobitmasks(void *data, int write,
291                              loff_t pos, void __user *buffer, int nob)
292 {
293         const int     tmpstrlen = 512;
294         char         *tmpstr = NULL;
295         int           rc;
296         unsigned int *mask = data;
297         int           is_subsys = (mask == &libcfs_subsystem_debug) ? 1 : 0;
298         int           is_printk = (mask == &libcfs_printk) ? 1 : 0;
299
300         if (!write) {
301                 tmpstr = kmalloc(tmpstrlen, GFP_KERNEL | __GFP_ZERO);
302                 if (!tmpstr)
303                         return -ENOMEM;
304                 libcfs_debug_mask2str(tmpstr, tmpstrlen, *mask, is_subsys);
305                 rc = strlen(tmpstr);
306
307                 if (pos >= rc) {
308                         rc = 0;
309                 } else {
310                         rc = cfs_trace_copyout_string(buffer, nob,
311                                                       tmpstr + pos, "\n");
312                 }
313         } else {
314                 tmpstr = memdup_user_nul(buffer, nob);
315                 if (IS_ERR(tmpstr))
316                         return PTR_ERR(tmpstr);
317
318                 rc = libcfs_debug_str2mask(mask, strim(tmpstr), is_subsys);
319                 /* Always print LBUG/LASSERT to console, so keep this mask */
320                 if (is_printk)
321                         *mask |= D_EMERG;
322         }
323
324         kfree(tmpstr);
325         return rc;
326 }
327
328 static int proc_dobitmasks(struct ctl_table *table, int write,
329                            void __user *buffer, size_t *lenp, loff_t *ppos)
330 {
331         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
332                                     __proc_dobitmasks);
333 }
334
335 static int min_watchdog_ratelimit;              /* disable ratelimiting */
336 static int max_watchdog_ratelimit = (24*60*60); /* limit to once per day */
337
338 static int __proc_dump_kernel(void *data, int write,
339                               loff_t pos, void __user *buffer, int nob)
340 {
341         if (!write)
342                 return 0;
343
344         return cfs_trace_dump_debug_buffer_usrstr(buffer, nob);
345 }
346
347 static int proc_dump_kernel(struct ctl_table *table, int write,
348                             void __user *buffer, size_t *lenp, loff_t *ppos)
349 {
350         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
351                                     __proc_dump_kernel);
352 }
353
354 static int __proc_daemon_file(void *data, int write,
355                               loff_t pos, void __user *buffer, int nob)
356 {
357         if (!write) {
358                 int len = strlen(cfs_tracefile);
359
360                 if (pos >= len)
361                         return 0;
362
363                 return cfs_trace_copyout_string(buffer, nob,
364                                                 cfs_tracefile + pos, "\n");
365         }
366
367         return cfs_trace_daemon_command_usrstr(buffer, nob);
368 }
369
370 static int proc_daemon_file(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_daemon_file);
375 }
376
377 static int libcfs_force_lbug(struct ctl_table *table, int write,
378                              void __user *buffer,
379                              size_t *lenp, loff_t *ppos)
380 {
381         if (write)
382                 LBUG();
383         return 0;
384 }
385
386 static int proc_fail_loc(struct ctl_table *table, int write,
387                          void __user *buffer, size_t *lenp, loff_t *ppos)
388 {
389         int rc;
390         long old_fail_loc = cfs_fail_loc;
391
392         if (!*lenp || *ppos) {
393                 *lenp = 0;
394                 return 0;
395         }
396
397         if (write) {
398                 char *kbuf = memdup_user_nul(buffer, *lenp);
399
400                 if (IS_ERR(kbuf))
401                         return PTR_ERR(kbuf);
402                 rc = kstrtoul(kbuf, 0, &cfs_fail_loc);
403                 kfree(kbuf);
404                 *ppos += *lenp;
405         } else {
406                 char kbuf[64/3+3];
407
408                 rc = scnprintf(kbuf, sizeof(kbuf), "%lu\n", cfs_fail_loc);
409                 if (copy_to_user(buffer, kbuf, rc))
410                         rc = -EFAULT;
411                 else {
412                         *lenp = rc;
413                         *ppos += rc;
414                 }
415         }
416
417         if (old_fail_loc != cfs_fail_loc) {
418                 cfs_race_state = 1;
419                 wake_up(&cfs_race_waitq);
420         }
421         return rc;
422 }
423
424 int debugfs_doint(struct ctl_table *table, int write,
425                   void __user *buffer, size_t *lenp, loff_t *ppos)
426 {
427         int rc;
428
429         if (!*lenp || *ppos) {
430                 *lenp = 0;
431                 return 0;
432         }
433
434         if (write) {
435                 char *kbuf = memdup_user_nul(buffer, *lenp);
436                 int val;
437
438                 if (IS_ERR(kbuf))
439                         return PTR_ERR(kbuf);
440
441                 rc = kstrtoint(kbuf, 0, &val);
442                 kfree(kbuf);
443                 if (!rc) {
444                         if (table->extra1 && val < *(int *)table->extra1)
445                                 val = *(int *)table->extra1;
446                         if (table->extra2 && val > *(int *)table->extra2)
447                                 val = *(int *)table->extra2;
448                         *(int *)table->data = val;
449                 }
450                 *ppos += *lenp;
451         } else {
452                 char kbuf[64/3+3];
453
454                 rc = scnprintf(kbuf, sizeof(kbuf), "%u\n", *(int *)table->data);
455                 if (copy_to_user(buffer, kbuf, rc))
456                         rc = -EFAULT;
457                 else {
458                         *lenp = rc;
459                         *ppos += rc;
460                 }
461         }
462
463         return rc;
464 }
465 EXPORT_SYMBOL(debugfs_doint);
466
467 static int debugfs_dou64(struct ctl_table *table, int write,
468                          void __user *buffer, size_t *lenp, loff_t *ppos)
469 {
470         int rc;
471
472         if (!*lenp || *ppos) {
473                 *lenp = 0;
474                 return 0;
475         }
476
477         if (write) {
478                 char *kbuf = memdup_user_nul(buffer, *lenp);
479                 unsigned long long val;
480
481                 if (IS_ERR(kbuf))
482                         return PTR_ERR(kbuf);
483
484                 rc = kstrtoull(kbuf, 0, &val);
485                 kfree(kbuf);
486                 if (!rc)
487                         *(u64 *)table->data = val;
488                 *ppos += *lenp;
489         } else {
490                 char kbuf[64/3+3];
491
492                 rc = scnprintf(kbuf, sizeof(kbuf), "%llu\n",
493                                (unsigned long long)*(u64 *)table->data);
494                 if (copy_to_user(buffer, kbuf, rc))
495                         rc = -EFAULT;
496                 else {
497                         *lenp = rc;
498                         *ppos += rc;
499                 }
500         }
501
502         return rc;
503 }
504
505 static int debugfs_dostring(struct ctl_table *table, int write,
506                             void __user *buffer, size_t *lenp, loff_t *ppos)
507 {
508         int len = *lenp;
509         char *kbuf = table->data;
510
511         if (!len || *ppos) {
512                 *lenp = 0;
513                 return 0;
514         }
515         if (len > table->maxlen)
516                 len = table->maxlen;
517         if (write) {
518                 if (copy_from_user(kbuf, buffer, len))
519                         return -EFAULT;
520                 memset(kbuf+len, 0, table->maxlen - len);
521                 *ppos = *lenp;
522         } else {
523                 len = strnlen(kbuf, len);
524                 if (copy_to_user(buffer, kbuf, len))
525                         return -EFAULT;
526                 if (len < *lenp) {
527                         if (copy_to_user(buffer+len, "\n", 1))
528                                 return -EFAULT;
529                         len += 1;
530                 }
531                 *ppos += len;
532                 *lenp -= len;
533         }
534         return len;
535 }
536
537 static int __proc_cpt_table(void *data, int write,
538                             loff_t pos, void __user *buffer, int nob)
539 {
540         char *buf = NULL;
541         int   len = 4096;
542         int   rc  = 0;
543
544         if (write)
545                 return -EPERM;
546
547         while (1) {
548                 LIBCFS_ALLOC(buf, len);
549                 if (buf == NULL)
550                         return -ENOMEM;
551
552                 rc = cfs_cpt_table_print(cfs_cpt_tab, buf, len);
553                 if (rc >= 0)
554                         break;
555
556                 if (rc == -EFBIG) {
557                         LIBCFS_FREE(buf, len);
558                         len <<= 1;
559                         continue;
560                 }
561                 goto out;
562         }
563
564         if (pos >= rc) {
565                 rc = 0;
566                 goto out;
567         }
568
569         rc = cfs_trace_copyout_string(buffer, nob, buf + pos, NULL);
570 out:
571         if (buf != NULL)
572                 LIBCFS_FREE(buf, len);
573         return rc;
574 }
575
576 static int proc_cpt_table(struct ctl_table *table, int write,
577                           void __user *buffer, size_t *lenp, loff_t *ppos)
578 {
579         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
580                                     __proc_cpt_table);
581 }
582
583 static int __proc_cpt_distance(void *data, int write,
584                                loff_t pos, void __user *buffer, int nob)
585 {
586         char *buf = NULL;
587         int   len = 4096;
588         int   rc  = 0;
589
590         if (write)
591                 return -EPERM;
592
593         while (1) {
594                 LIBCFS_ALLOC(buf, len);
595                 if (buf == NULL)
596                         return -ENOMEM;
597
598                 rc = cfs_cpt_distance_print(cfs_cpt_tab, buf, len);
599                 if (rc >= 0)
600                         break;
601
602                 if (rc == -EFBIG) {
603                         LIBCFS_FREE(buf, len);
604                         len <<= 1;
605                         continue;
606                 }
607                 goto out;
608         }
609
610         if (pos >= rc) {
611                 rc = 0;
612                 goto out;
613         }
614
615         rc = cfs_trace_copyout_string(buffer, nob, buf + pos, NULL);
616  out:
617         if (buf != NULL)
618                 LIBCFS_FREE(buf, len);
619         return rc;
620 }
621
622 static int proc_cpt_distance(struct ctl_table *table, int write,
623                              void __user *buffer, size_t *lenp, loff_t *ppos)
624 {
625         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
626                                      __proc_cpt_distance);
627 }
628
629 static struct ctl_table lnet_table[] = {
630         {
631                 .procname       = "debug",
632                 .data           = &libcfs_debug,
633                 .maxlen         = sizeof(int),
634                 .mode           = 0644,
635                 .proc_handler   = &proc_dobitmasks,
636         },
637         {
638                 .procname       = "subsystem_debug",
639                 .data           = &libcfs_subsystem_debug,
640                 .maxlen         = sizeof(int),
641                 .mode           = 0644,
642                 .proc_handler   = &proc_dobitmasks,
643         },
644         {
645                 .procname       = "printk",
646                 .data           = &libcfs_printk,
647                 .maxlen         = sizeof(int),
648                 .mode           = 0644,
649                 .proc_handler   = &proc_dobitmasks,
650         },
651         {
652                 .procname       = "cpu_partition_table",
653                 .maxlen         = 128,
654                 .mode           = 0444,
655                 .proc_handler   = &proc_cpt_table,
656         },
657         {
658                 .procname       = "cpu_partition_distance",
659                 .maxlen         = 128,
660                 .mode           = 0444,
661                 .proc_handler   = &proc_cpt_distance,
662         },
663         {
664                 .procname       = "debug_log_upcall",
665                 .data           = lnet_debug_log_upcall,
666                 .maxlen         = sizeof(lnet_debug_log_upcall),
667                 .mode           = 0644,
668                 .proc_handler   = &debugfs_dostring,
669         },
670         {
671                 .procname       = "lnet_memused",
672                 .data           = (u64 *)&libcfs_kmem.counter,
673                 .maxlen         = sizeof(u64),
674                 .mode           = 0444,
675                 .proc_handler   = &debugfs_dou64,
676         },
677         {
678                 .procname       = "catastrophe",
679                 .data           = &libcfs_catastrophe,
680                 .maxlen         = sizeof(int),
681                 .mode           = 0444,
682                 .proc_handler   = &debugfs_doint,
683         },
684         {
685                 .procname       = "dump_kernel",
686                 .maxlen         = 256,
687                 .mode           = 0200,
688                 .proc_handler   = &proc_dump_kernel,
689         },
690         {
691                 .procname       = "daemon_file",
692                 .mode           = 0644,
693                 .maxlen         = 256,
694                 .proc_handler   = &proc_daemon_file,
695         },
696         {
697                 .procname       = "watchdog_ratelimit",
698                 .data           = &libcfs_watchdog_ratelimit,
699                 .maxlen         = sizeof(int),
700                 .mode           = 0644,
701                 .proc_handler   = &debugfs_doint,
702                 .extra1         = &min_watchdog_ratelimit,
703                 .extra2         = &max_watchdog_ratelimit,
704         },
705         {
706                 .procname       = "force_lbug",
707                 .data           = NULL,
708                 .maxlen         = 0,
709                 .mode           = 0200,
710                 .proc_handler   = &libcfs_force_lbug
711         },
712         {
713                 .procname       = "fail_loc",
714                 .data           = &cfs_fail_loc,
715                 .maxlen         = sizeof(cfs_fail_loc),
716                 .mode           = 0644,
717                 .proc_handler   = &proc_fail_loc
718         },
719         {
720                 .procname       = "fail_val",
721                 .data           = &cfs_fail_val,
722                 .maxlen         = sizeof(int),
723                 .mode           = 0644,
724                 .proc_handler   = &debugfs_doint
725         },
726         {
727                 .procname       = "fail_err",
728                 .data           = &cfs_fail_err,
729                 .maxlen         = sizeof(cfs_fail_err),
730                 .mode           = 0644,
731                 .proc_handler   = &debugfs_doint,
732         },
733         {
734         }
735 };
736
737 static const struct lnet_debugfs_symlink_def lnet_debugfs_symlinks[] = {
738         { .name         = "console_ratelimit",
739           .target       = "../../../module/libcfs/parameters/libcfs_console_ratelimit" },
740         { .name         = "debug_path",
741           .target       = "../../../module/libcfs/parameters/libcfs_debug_file_path" },
742         { .name         = "panic_on_lbug",
743           .target       = "../../../module/libcfs/parameters/libcfs_panic_on_lbug" },
744         { .name         = "console_backoff",
745           .target       = "../../../module/libcfs/parameters/libcfs_console_backoff" },
746         { .name         = "debug_mb",
747           .target       = "../../../module/libcfs/parameters/libcfs_debug_mb" },
748         { .name         = "console_min_delay_centisecs",
749           .target       = "../../../module/libcfs/parameters/libcfs_console_min_delay" },
750         { .name         = "console_max_delay_centisecs",
751           .target       = "../../../module/libcfs/parameters/libcfs_console_max_delay" },
752         { .name         = NULL },
753 };
754
755 static ssize_t lnet_debugfs_read(struct file *filp, char __user *buf,
756                                  size_t count, loff_t *ppos)
757 {
758         struct ctl_table *table = filp->private_data;
759         ssize_t rc = -EINVAL;
760
761         if (table) {
762                 rc = table->proc_handler(table, 0, buf, &count, ppos);
763                 if (!rc)
764                         rc = count;
765         }
766
767         return rc;
768 }
769
770 static ssize_t lnet_debugfs_write(struct file *filp, const char __user *buf,
771                                   size_t count, loff_t *ppos)
772 {
773         struct ctl_table *table = filp->private_data;
774         ssize_t rc = -EINVAL;
775
776         if (table) {
777                 rc = table->proc_handler(table, 1, (void __user *)buf, &count,
778                                          ppos);
779                 if (!rc)
780                         rc = count;
781         }
782
783         return rc;
784 }
785
786 static const struct file_operations lnet_debugfs_file_operations_rw = {
787         .open           = simple_open,
788         .read           = lnet_debugfs_read,
789         .write          = lnet_debugfs_write,
790         .llseek         = default_llseek,
791 };
792
793 static const struct file_operations lnet_debugfs_file_operations_ro = {
794         .open           = simple_open,
795         .read           = lnet_debugfs_read,
796         .llseek         = default_llseek,
797 };
798
799 static const struct file_operations lnet_debugfs_file_operations_wo = {
800         .open           = simple_open,
801         .write          = lnet_debugfs_write,
802         .llseek         = default_llseek,
803 };
804
805 static const struct file_operations *lnet_debugfs_fops_select(umode_t mode)
806 {
807         if (!(mode & S_IWUGO))
808                 return &lnet_debugfs_file_operations_ro;
809
810         if (!(mode & S_IRUGO))
811                 return &lnet_debugfs_file_operations_wo;
812
813         return &lnet_debugfs_file_operations_rw;
814 }
815
816 void lnet_insert_debugfs(struct ctl_table *table)
817 {
818         if (!lnet_debugfs_root)
819                 lnet_debugfs_root = debugfs_create_dir("lnet", NULL);
820
821         /* Even if we cannot create, just ignore it altogether) */
822         if (IS_ERR_OR_NULL(lnet_debugfs_root))
823                 return;
824
825         /* We don't save the dentry returned in next two calls, because
826          * we don't call debugfs_remove() but rather remove_recursive()
827          */
828         for (; table && table->procname; table++)
829                 debugfs_create_file(table->procname, table->mode,
830                                     lnet_debugfs_root, table,
831                                     lnet_debugfs_fops_select(table->mode));
832 }
833 EXPORT_SYMBOL_GPL(lnet_insert_debugfs);
834
835 static void lnet_insert_debugfs_links(
836                 const struct lnet_debugfs_symlink_def *symlinks)
837 {
838         for (; symlinks && symlinks->name; symlinks++)
839                 debugfs_create_symlink(symlinks->name, lnet_debugfs_root,
840                                        symlinks->target);
841 }
842
843 void lnet_remove_debugfs(struct ctl_table *table)
844 {
845         for (; table && table->procname; table++) {
846                 struct qstr dname = QSTR_INIT(table->procname,
847                                               strlen(table->procname));
848                 struct dentry *dentry;
849
850                 dentry = d_hash_and_lookup(lnet_debugfs_root, &dname);
851                 debugfs_remove(dentry);
852         }
853 }
854 EXPORT_SYMBOL_GPL(lnet_remove_debugfs);
855
856 static int __init libcfs_init(void)
857 {
858         int rc;
859
860         cfs_arch_init();
861
862         init_libcfs_vfree_atomic();
863
864         rc = libcfs_debug_init(5 * 1024 * 1024);
865         if (rc < 0) {
866                 pr_err("LustreError: libcfs_debug_init: rc = %d\n", rc);
867                 return (rc);
868         }
869
870         cfs_debug_init();
871
872         rc = cfs_cpu_init();
873         if (rc != 0)
874                 goto cleanup_debug;
875
876         rc = misc_register(&libcfs_dev);
877         if (rc) {
878                 CERROR("misc_register: error %d\n", rc);
879                 goto cleanup_cpu;
880         }
881
882         rc = cfs_wi_startup();
883         if (rc) {
884                 CERROR("initialize workitem: error %d\n", rc);
885                 goto cleanup_deregister;
886         }
887
888         cfs_rehash_wq = alloc_workqueue("cfs_rh", WQ_SYSFS, 4);
889         if (!cfs_rehash_wq) {
890                 rc = -ENOMEM;
891                 CERROR("libcfs: failed to start rehash workqueue: rc = %d\n",
892                        rc);
893                 goto cleanup_deregister;
894         }
895
896         rc = cfs_crypto_register();
897         if (rc) {
898                 CERROR("cfs_crypto_regster: error %d\n", rc);
899                 goto cleanup_wi;
900         }
901
902         lnet_insert_debugfs(lnet_table);
903         if (!IS_ERR_OR_NULL(lnet_debugfs_root))
904                 lnet_insert_debugfs_links(lnet_debugfs_symlinks);
905
906         rc = llcrypt_init();
907         if (rc) {
908                 CERROR("llcrypt_init: error %d\n", rc);
909                 goto cleanup_wi;
910         }
911
912         CDEBUG (D_OTHER, "portals setup OK\n");
913         return 0;
914 cleanup_wi:
915         cfs_wi_shutdown();
916 cleanup_deregister:
917         misc_deregister(&libcfs_dev);
918 cleanup_cpu:
919         cfs_cpu_fini();
920 cleanup_debug:
921         libcfs_debug_cleanup();
922         return rc;
923 }
924
925 static void __exit libcfs_exit(void)
926 {
927         int rc;
928
929         /* Remove everthing */
930         debugfs_remove_recursive(lnet_debugfs_root);
931         lnet_debugfs_root = NULL;
932
933         CDEBUG(D_MALLOC, "before Portals cleanup: kmem %lld\n",
934                libcfs_kmem_read());
935
936         llcrypt_exit();
937
938         if (cfs_rehash_wq) {
939                 destroy_workqueue(cfs_rehash_wq);
940                 cfs_rehash_wq = NULL;
941         }
942
943         cfs_crypto_unregister();
944         cfs_wi_shutdown();
945
946         misc_deregister(&libcfs_dev);
947
948         cfs_cpu_fini();
949
950         /* the below message is checked in test-framework.sh check_mem_leak() */
951         if (libcfs_kmem_read() != 0)
952                 CERROR("Portals memory leaked: %lld bytes\n",
953                        libcfs_kmem_read());
954
955         rc = libcfs_debug_cleanup();
956         if (rc)
957                 pr_err("LustreError: libcfs_debug_cleanup: rc = %d\n", rc);
958
959         exit_libcfs_vfree_atomic();
960 }
961
962 MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
963 MODULE_DESCRIPTION("Lustre helper library");
964 MODULE_VERSION(LIBCFS_VERSION);
965 MODULE_LICENSE("GPL");
966
967 module_init(libcfs_init);
968 module_exit(libcfs_exit);