Whamcloud - gitweb
3a696e910a244df4580fbddfeace9c683fc61125
[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 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 int lprocfs_call_handler(void *data, int write, loff_t *ppos,
123                          void __user *buffer, size_t *lenp,
124                          int (*handler)(void *data, int write, loff_t pos,
125                                         void __user *buffer, int len))
126 {
127         int rc = handler(data, write, *ppos, buffer, *lenp);
128
129         if (rc < 0)
130                 return rc;
131
132         if (write) {
133                 *ppos += *lenp;
134         } else {
135                 *lenp = rc;
136                 *ppos += rc;
137         }
138         return 0;
139 }
140 EXPORT_SYMBOL(lprocfs_call_handler);
141
142 static int __proc_dobitmasks(void *data, int write,
143                              loff_t pos, void __user *buffer, int nob)
144 {
145         const int     tmpstrlen = 512;
146         char         *tmpstr;
147         int           rc;
148         unsigned int *mask = data;
149         int           is_subsys = (mask == &libcfs_subsystem_debug) ? 1 : 0;
150         int           is_printk = (mask == &libcfs_printk) ? 1 : 0;
151
152         rc = cfs_trace_allocate_string_buffer(&tmpstr, tmpstrlen);
153         if (rc < 0)
154                 return rc;
155
156         if (!write) {
157                 libcfs_debug_mask2str(tmpstr, tmpstrlen, *mask, is_subsys);
158                 rc = strlen(tmpstr);
159
160                 if (pos >= rc) {
161                         rc = 0;
162                 } else {
163                         rc = cfs_trace_copyout_string(buffer, nob,
164                                                       tmpstr + pos, "\n");
165                 }
166         } else {
167                 rc = cfs_trace_copyin_string(tmpstr, tmpstrlen, buffer, nob);
168                 if (rc < 0) {
169                         kfree(tmpstr);
170                         return rc;
171                 }
172
173                 rc = libcfs_debug_str2mask(mask, tmpstr, is_subsys);
174                 /* Always print LBUG/LASSERT to console, so keep this mask */
175                 if (is_printk)
176                         *mask |= D_EMERG;
177         }
178
179         kfree(tmpstr);
180         return rc;
181 }
182
183 static int proc_dobitmasks(struct ctl_table *table, int write,
184                            void __user *buffer, size_t *lenp, loff_t *ppos)
185 {
186         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
187                                     __proc_dobitmasks);
188 }
189
190 static int min_watchdog_ratelimit;              /* disable ratelimiting */
191 static int max_watchdog_ratelimit = (24*60*60); /* limit to once per day */
192
193 static int __proc_dump_kernel(void *data, int write,
194                               loff_t pos, void __user *buffer, int nob)
195 {
196         if (!write)
197                 return 0;
198
199         return cfs_trace_dump_debug_buffer_usrstr(buffer, nob);
200 }
201
202 static int proc_dump_kernel(struct ctl_table *table, int write,
203                             void __user *buffer, size_t *lenp, loff_t *ppos)
204 {
205         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
206                                     __proc_dump_kernel);
207 }
208
209 static int __proc_daemon_file(void *data, int write,
210                               loff_t pos, void __user *buffer, int nob)
211 {
212         if (!write) {
213                 int len = strlen(cfs_tracefile);
214
215                 if (pos >= len)
216                         return 0;
217
218                 return cfs_trace_copyout_string(buffer, nob,
219                                                 cfs_tracefile + pos, "\n");
220         }
221
222         return cfs_trace_daemon_command_usrstr(buffer, nob);
223 }
224
225 static int proc_daemon_file(struct ctl_table *table, int write,
226                             void __user *buffer, size_t *lenp, loff_t *ppos)
227 {
228         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
229                                     __proc_daemon_file);
230 }
231
232 static int libcfs_force_lbug(struct ctl_table *table, int write,
233                              void __user *buffer,
234                              size_t *lenp, loff_t *ppos)
235 {
236         if (write)
237                 LBUG();
238         return 0;
239 }
240
241 static int proc_fail_loc(struct ctl_table *table, int write,
242                          void __user *buffer, size_t *lenp, loff_t *ppos)
243 {
244         int rc;
245         long old_fail_loc = cfs_fail_loc;
246
247         rc = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
248         if (old_fail_loc != cfs_fail_loc)
249                 wake_up(&cfs_race_waitq);
250         return rc;
251 }
252
253 static int __proc_cpt_table(void *data, int write,
254                             loff_t pos, void __user *buffer, int nob)
255 {
256         char *buf = NULL;
257         int   len = 4096;
258         int   rc  = 0;
259
260         if (write)
261                 return -EPERM;
262
263         LASSERT(cfs_cpt_table != NULL);
264
265         while (1) {
266                 LIBCFS_ALLOC(buf, len);
267                 if (buf == NULL)
268                         return -ENOMEM;
269
270                 rc = cfs_cpt_table_print(cfs_cpt_table, buf, len);
271                 if (rc >= 0)
272                         break;
273
274                 if (rc == -EFBIG) {
275                         LIBCFS_FREE(buf, len);
276                         len <<= 1;
277                         continue;
278                 }
279                 goto out;
280         }
281
282         if (pos >= rc) {
283                 rc = 0;
284                 goto out;
285         }
286
287         rc = cfs_trace_copyout_string(buffer, nob, buf + pos, NULL);
288 out:
289         if (buf != NULL)
290                 LIBCFS_FREE(buf, len);
291         return rc;
292 }
293
294 static int proc_cpt_table(struct ctl_table *table, int write,
295                           void __user *buffer, size_t *lenp, loff_t *ppos)
296 {
297         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
298                                     __proc_cpt_table);
299 }
300
301 static int __proc_cpt_distance(void *data, int write,
302                                loff_t pos, void __user *buffer, int nob)
303 {
304         char *buf = NULL;
305         int   len = 4096;
306         int   rc  = 0;
307
308         if (write)
309                 return -EPERM;
310
311         LASSERT(cfs_cpt_table != NULL);
312
313         while (1) {
314                 LIBCFS_ALLOC(buf, len);
315                 if (buf == NULL)
316                         return -ENOMEM;
317
318                 rc = cfs_cpt_distance_print(cfs_cpt_table, buf, len);
319                 if (rc >= 0)
320                         break;
321
322                 if (rc == -EFBIG) {
323                         LIBCFS_FREE(buf, len);
324                         len <<= 1;
325                         continue;
326                 }
327                 goto out;
328         }
329
330         if (pos >= rc) {
331                 rc = 0;
332                 goto out;
333         }
334
335         rc = cfs_trace_copyout_string(buffer, nob, buf + pos, NULL);
336  out:
337         if (buf != NULL)
338                 LIBCFS_FREE(buf, len);
339         return rc;
340 }
341
342 static int proc_cpt_distance(struct ctl_table *table, int write,
343                              void __user *buffer, size_t *lenp, loff_t *ppos)
344 {
345         return lprocfs_call_handler(table->data, write, ppos, buffer, lenp,
346                                      __proc_cpt_distance);
347 }
348
349 static struct ctl_table lnet_table[] = {
350         {
351                 INIT_CTL_NAME
352                 .procname       = "debug",
353                 .data           = &libcfs_debug,
354                 .maxlen         = sizeof(int),
355                 .mode           = 0644,
356                 .proc_handler   = &proc_dobitmasks,
357         },
358         {
359                 INIT_CTL_NAME
360                 .procname       = "subsystem_debug",
361                 .data           = &libcfs_subsystem_debug,
362                 .maxlen         = sizeof(int),
363                 .mode           = 0644,
364                 .proc_handler   = &proc_dobitmasks,
365         },
366         {
367                 INIT_CTL_NAME
368                 .procname       = "printk",
369                 .data           = &libcfs_printk,
370                 .maxlen         = sizeof(int),
371                 .mode           = 0644,
372                 .proc_handler   = &proc_dobitmasks,
373         },
374         {
375                 INIT_CTL_NAME
376                 .procname       = "cpu_partition_table",
377                 .maxlen         = 128,
378                 .mode           = 0444,
379                 .proc_handler   = &proc_cpt_table,
380         },
381         {
382                 INIT_CTL_NAME
383                 .procname       = "cpu_partition_distance",
384                 .maxlen         = 128,
385                 .mode           = 0444,
386                 .proc_handler   = &proc_cpt_distance,
387         },
388         {
389                 INIT_CTL_NAME
390                 .procname       = "debug_log_upcall",
391                 .data           = lnet_debug_log_upcall,
392                 .maxlen         = sizeof(lnet_debug_log_upcall),
393                 .mode           = 0644,
394                 .proc_handler   = &proc_dostring,
395         },
396         {
397                 INIT_CTL_NAME
398                 .procname       = "lnet_memused",
399                 .data           = (int *)&libcfs_kmemory.counter,
400                 .maxlen         = sizeof(int),
401                 .mode           = 0444,
402                 .proc_handler   = &proc_dointvec,
403         },
404         {
405                 INIT_CTL_NAME
406                 .procname       = "catastrophe",
407                 .data           = &libcfs_catastrophe,
408                 .maxlen         = sizeof(int),
409                 .mode           = 0444,
410                 .proc_handler   = &proc_dointvec,
411         },
412         {
413                 INIT_CTL_NAME
414                 .procname       = "dump_kernel",
415                 .maxlen         = 256,
416                 .mode           = 0200,
417                 .proc_handler   = &proc_dump_kernel,
418         },
419         {
420                 INIT_CTL_NAME
421                 .procname       = "daemon_file",
422                 .mode           = 0644,
423                 .maxlen         = 256,
424                 .proc_handler   = &proc_daemon_file,
425         },
426         {
427                 INIT_CTL_NAME
428                 .procname       = "watchdog_ratelimit",
429                 .data           = &libcfs_watchdog_ratelimit,
430                 .maxlen         = sizeof(int),
431                 .mode           = 0644,
432                 .proc_handler   = &proc_dointvec_minmax,
433                 .extra1         = &min_watchdog_ratelimit,
434                 .extra2         = &max_watchdog_ratelimit,
435         },
436         {
437                 INIT_CTL_NAME
438                 .procname       = "force_lbug",
439                 .data           = NULL,
440                 .maxlen         = 0,
441                 .mode           = 0200,
442                 .proc_handler   = &libcfs_force_lbug
443         },
444         {
445                 INIT_CTL_NAME
446                 .procname       = "fail_loc",
447                 .data           = &cfs_fail_loc,
448                 .maxlen         = sizeof(cfs_fail_loc),
449                 .mode           = 0644,
450                 .proc_handler   = &proc_fail_loc
451         },
452         {
453                 INIT_CTL_NAME
454                 .procname       = "fail_val",
455                 .data           = &cfs_fail_val,
456                 .maxlen         = sizeof(int),
457                 .mode           = 0644,
458                 .proc_handler   = &proc_dointvec
459         },
460         {
461                 INIT_CTL_NAME
462                 .procname       = "fail_err",
463                 .data           = &cfs_fail_err,
464                 .maxlen         = sizeof(cfs_fail_err),
465                 .mode           = 0644,
466                 .proc_handler   = &proc_dointvec,
467         },
468         {
469         }
470 };
471
472 static const struct lnet_debugfs_symlink_def lnet_debugfs_symlinks[] = {
473         { .name         = "console_ratelimit",
474           .target       = "../../../module/libcfs/parameters/libcfs_console_ratelimit" },
475         { .name         = "debug_path",
476           .target       = "../../../module/libcfs/parameters/libcfs_debug_file_path" },
477         { .name         = "panic_on_lbug",
478           .target       = "../../../module/libcfs/parameters/libcfs_panic_on_lbug" },
479         { .name         = "console_backoff",
480           .target       = "../../../module/libcfs/parameters/libcfs_console_backoff" },
481         { .name         = "debug_mb",
482           .target       = "../../../module/libcfs/parameters/libcfs_debug_mb" },
483         { .name         = "console_min_delay_centisecs",
484           .target       = "../../../module/libcfs/parameters/libcfs_console_min_delay" },
485         { .name         = "console_max_delay_centisecs",
486           .target       = "../../../module/libcfs/parameters/libcfs_console_max_delay" },
487         { .name         = NULL },
488 };
489
490 static ssize_t lnet_debugfs_read(struct file *filp, char __user *buf,
491                                  size_t count, loff_t *ppos)
492 {
493         struct ctl_table *table = filp->private_data;
494         ssize_t rc = -EINVAL;
495
496         if (table) {
497                 rc = table->proc_handler(table, 0, buf, &count, ppos);
498                 if (!rc)
499                         rc = count;
500         }
501
502         return rc;
503 }
504
505 static ssize_t lnet_debugfs_write(struct file *filp, const char __user *buf,
506                                   size_t count, loff_t *ppos)
507 {
508         struct ctl_table *table = filp->private_data;
509         ssize_t rc = -EINVAL;
510
511         if (table) {
512                 rc = table->proc_handler(table, 1, (void __user *)buf, &count,
513                                          ppos);
514                 if (!rc)
515                         rc = count;
516         }
517
518         return rc;
519 }
520
521 static const struct file_operations lnet_debugfs_file_operations_rw = {
522         .open           = simple_open,
523         .read           = lnet_debugfs_read,
524         .write          = lnet_debugfs_write,
525         .llseek         = default_llseek,
526 };
527
528 static const struct file_operations lnet_debugfs_file_operations_ro = {
529         .open           = simple_open,
530         .read           = lnet_debugfs_read,
531         .llseek         = default_llseek,
532 };
533
534 static const struct file_operations lnet_debugfs_file_operations_wo = {
535         .open           = simple_open,
536         .write          = lnet_debugfs_write,
537         .llseek         = default_llseek,
538 };
539
540 static const struct file_operations *lnet_debugfs_fops_select(umode_t mode)
541 {
542         if (!(mode & S_IWUGO))
543                 return &lnet_debugfs_file_operations_ro;
544
545         if (!(mode & S_IRUGO))
546                 return &lnet_debugfs_file_operations_wo;
547
548         return &lnet_debugfs_file_operations_rw;
549 }
550
551 void lnet_insert_debugfs(struct ctl_table *table,
552                          const struct lnet_debugfs_symlink_def *symlinks)
553 {
554         if (!lnet_debugfs_root)
555                 lnet_debugfs_root = debugfs_create_dir("lnet", NULL);
556
557         /* Even if we cannot create, just ignore it altogether) */
558         if (IS_ERR_OR_NULL(lnet_debugfs_root))
559                 return;
560
561         /* We don't save the dentry returned in next two calls, because
562          * we don't call debugfs_remove() but rather remove_recursive()
563          */
564         for (; table && table->procname; table++)
565                 debugfs_create_file(table->procname, table->mode,
566                                     lnet_debugfs_root, table,
567                                     lnet_debugfs_fops_select(table->mode));
568
569         for (; symlinks && symlinks->name; symlinks++)
570                 debugfs_create_symlink(symlinks->name, lnet_debugfs_root,
571                                        symlinks->target);
572 }
573 EXPORT_SYMBOL_GPL(lnet_insert_debugfs);
574
575 static void lnet_remove_debugfs(void)
576 {
577         debugfs_remove_recursive(lnet_debugfs_root);
578
579         lnet_debugfs_root = NULL;
580 }
581
582 static int __init libcfs_init(void)
583 {
584         int rc;
585
586         rc = libcfs_debug_init(5 * 1024 * 1024);
587         if (rc < 0) {
588                 printk(KERN_ERR "LustreError: libcfs_debug_init: %d\n", rc);
589                 return (rc);
590         }
591
592         rc = cfs_cpu_init();
593         if (rc != 0)
594                 goto cleanup_debug;
595
596         rc = misc_register(&libcfs_dev);
597         if (rc) {
598                 CERROR("misc_register: error %d\n", rc);
599                 goto cleanup_cpu;
600         }
601
602         rc = cfs_wi_startup();
603         if (rc) {
604                 CERROR("initialize workitem: error %d\n", rc);
605                 goto cleanup_deregister;
606         }
607
608         cfs_rehash_wq = alloc_workqueue("cfs_rh", WQ_SYSFS, 4);
609         if (!cfs_rehash_wq) {
610                 rc = -ENOMEM;
611                 CERROR("libcfs: failed to start rehash workqueue: rc = %d\n",
612                        rc);
613                 goto cleanup_deregister;
614         }
615
616         rc = cfs_crypto_register();
617         if (rc) {
618                 CERROR("cfs_crypto_regster: error %d\n", rc);
619                 goto cleanup_wi;
620         }
621
622         lnet_insert_debugfs(lnet_table, lnet_debugfs_symlinks);
623
624         CDEBUG (D_OTHER, "portals setup OK\n");
625         return 0;
626 cleanup_wi:
627         cfs_wi_shutdown();
628 cleanup_deregister:
629         misc_deregister(&libcfs_dev);
630 cleanup_cpu:
631         cfs_cpu_fini();
632 cleanup_debug:
633         libcfs_debug_cleanup();
634         return rc;
635 }
636
637 static void __exit libcfs_exit(void)
638 {
639         int rc;
640
641         lnet_remove_debugfs();
642
643         CDEBUG(D_MALLOC, "before Portals cleanup: kmem %d\n",
644                atomic_read(&libcfs_kmemory));
645
646         if (cfs_rehash_wq) {
647                 destroy_workqueue(cfs_rehash_wq);
648                 cfs_rehash_wq = NULL;
649         }
650
651         cfs_crypto_unregister();
652         cfs_wi_shutdown();
653
654         misc_deregister(&libcfs_dev);
655
656         cfs_cpu_fini();
657
658         if (atomic_read(&libcfs_kmemory) != 0)
659                 CERROR("Portals memory leaked: %d bytes\n",
660                        atomic_read(&libcfs_kmemory));
661
662         rc = libcfs_debug_cleanup();
663         if (rc)
664                 printk(KERN_ERR "LustreError: libcfs_debug_cleanup: %d\n",
665                        rc);
666 }
667
668 MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
669 MODULE_DESCRIPTION("Lustre helper library");
670 MODULE_VERSION(LIBCFS_VERSION);
671 MODULE_LICENSE("GPL");
672
673 module_init(libcfs_init);
674 module_exit(libcfs_exit);