Whamcloud - gitweb
LU-6202 libcfs: replace libcfs_register_ioctl with a blocking notifier_chain
[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;
495
496         rc = table->proc_handler(table, 0, buf, &count, ppos);
497         if (!rc)
498                 rc = count;
499
500         return rc;
501 }
502
503 static ssize_t lnet_debugfs_write(struct file *filp, const char __user *buf,
504                                   size_t count, loff_t *ppos)
505 {
506         struct ctl_table *table = filp->private_data;
507         ssize_t rc;
508
509         rc = table->proc_handler(table, 1, (void __user *)buf, &count, ppos);
510         if (!rc)
511                 rc = count;
512
513         return rc;
514 }
515
516 static const struct file_operations lnet_debugfs_file_operations_rw = {
517         .open           = simple_open,
518         .read           = lnet_debugfs_read,
519         .write          = lnet_debugfs_write,
520         .llseek         = default_llseek,
521 };
522
523 static const struct file_operations lnet_debugfs_file_operations_ro = {
524         .open           = simple_open,
525         .read           = lnet_debugfs_read,
526         .llseek         = default_llseek,
527 };
528
529 static const struct file_operations lnet_debugfs_file_operations_wo = {
530         .open           = simple_open,
531         .write          = lnet_debugfs_write,
532         .llseek         = default_llseek,
533 };
534
535 static const struct file_operations *lnet_debugfs_fops_select(umode_t mode)
536 {
537         if (!(mode & S_IWUGO))
538                 return &lnet_debugfs_file_operations_ro;
539
540         if (!(mode & S_IRUGO))
541                 return &lnet_debugfs_file_operations_wo;
542
543         return &lnet_debugfs_file_operations_rw;
544 }
545
546 void lnet_insert_debugfs(struct ctl_table *table,
547                          const struct lnet_debugfs_symlink_def *symlinks)
548 {
549         if (!lnet_debugfs_root)
550                 lnet_debugfs_root = debugfs_create_dir("lnet", NULL);
551
552         /* Even if we cannot create, just ignore it altogether) */
553         if (IS_ERR_OR_NULL(lnet_debugfs_root))
554                 return;
555
556         /* We don't save the dentry returned in next two calls, because
557          * we don't call debugfs_remove() but rather remove_recursive()
558          */
559         for (; table && table->procname; table++)
560                 debugfs_create_file(table->procname, table->mode,
561                                     lnet_debugfs_root, table,
562                                     lnet_debugfs_fops_select(table->mode));
563
564         for (; symlinks && symlinks->name; symlinks++)
565                 debugfs_create_symlink(symlinks->name, lnet_debugfs_root,
566                                        symlinks->target);
567 }
568 EXPORT_SYMBOL_GPL(lnet_insert_debugfs);
569
570 static void lnet_remove_debugfs(void)
571 {
572         debugfs_remove_recursive(lnet_debugfs_root);
573
574         lnet_debugfs_root = NULL;
575 }
576
577 static int __init libcfs_init(void)
578 {
579         int rc;
580
581         rc = libcfs_debug_init(5 * 1024 * 1024);
582         if (rc < 0) {
583                 printk(KERN_ERR "LustreError: libcfs_debug_init: %d\n", rc);
584                 return (rc);
585         }
586
587         rc = cfs_cpu_init();
588         if (rc != 0)
589                 goto cleanup_debug;
590
591         rc = misc_register(&libcfs_dev);
592         if (rc) {
593                 CERROR("misc_register: error %d\n", rc);
594                 goto cleanup_cpu;
595         }
596
597         rc = cfs_wi_startup();
598         if (rc) {
599                 CERROR("initialize workitem: error %d\n", rc);
600                 goto cleanup_deregister;
601         }
602
603         /* max to 4 threads, should be enough for rehash */
604         rc = min(cfs_cpt_weight(cfs_cpt_table, CFS_CPT_ANY), 4);
605         rc = cfs_wi_sched_create("cfs_rh", cfs_cpt_table, CFS_CPT_ANY,
606                                  rc, &cfs_sched_rehash);
607         if (rc != 0) {
608                 CERROR("Startup workitem scheduler: error: %d\n", rc);
609                 goto cleanup_deregister;
610         }
611
612         rc = cfs_crypto_register();
613         if (rc) {
614                 CERROR("cfs_crypto_regster: error %d\n", rc);
615                 goto cleanup_wi;
616         }
617
618         lnet_insert_debugfs(lnet_table, lnet_debugfs_symlinks);
619
620         CDEBUG (D_OTHER, "portals setup OK\n");
621         return 0;
622 cleanup_wi:
623         cfs_wi_shutdown();
624 cleanup_deregister:
625         misc_deregister(&libcfs_dev);
626 cleanup_cpu:
627         cfs_cpu_fini();
628 cleanup_debug:
629         libcfs_debug_cleanup();
630         return rc;
631 }
632
633 static void __exit libcfs_exit(void)
634 {
635         int rc;
636
637         lnet_remove_debugfs();
638
639         CDEBUG(D_MALLOC, "before Portals cleanup: kmem %d\n",
640                atomic_read(&libcfs_kmemory));
641
642         if (cfs_sched_rehash != NULL) {
643                 cfs_wi_sched_destroy(cfs_sched_rehash);
644                 cfs_sched_rehash = NULL;
645         }
646
647         cfs_crypto_unregister();
648         cfs_wi_shutdown();
649
650         misc_deregister(&libcfs_dev);
651
652         cfs_cpu_fini();
653
654         if (atomic_read(&libcfs_kmemory) != 0)
655                 CERROR("Portals memory leaked: %d bytes\n",
656                        atomic_read(&libcfs_kmemory));
657
658         rc = libcfs_debug_cleanup();
659         if (rc)
660                 printk(KERN_ERR "LustreError: libcfs_debug_cleanup: %d\n",
661                        rc);
662 }
663
664 MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
665 MODULE_DESCRIPTION("Lustre helper library");
666 MODULE_VERSION(LIBCFS_VERSION);
667 MODULE_LICENSE("GPL");
668
669 module_init(libcfs_init);
670 module_exit(libcfs_exit);