]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/lustre/lustre/libcfs/module.c
611607ab92dbceaf68ec8b35187c39cd221c6994
[karo-tx-linux.git] / drivers / staging / lustre / lustre / 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.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2012, 2015 Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36 #include <linux/module.h>
37 #include <linux/kernel.h>
38 #include <linux/mm.h>
39 #include <linux/string.h>
40 #include <linux/stat.h>
41 #include <linux/errno.h>
42 #include <linux/unistd.h>
43 #include <net/sock.h>
44 #include <linux/uio.h>
45
46 #include <linux/uaccess.h>
47
48 #include <linux/fs.h>
49 #include <linux/file.h>
50 #include <linux/list.h>
51
52 #include <linux/sysctl.h>
53 #include <linux/debugfs.h>
54
55 # define DEBUG_SUBSYSTEM S_LNET
56
57 #include "../../include/linux/libcfs/libcfs.h"
58 #include <asm/div64.h>
59
60 #include "../../include/linux/libcfs/libcfs_crypto.h"
61 #include "../../include/linux/lnet/lib-lnet.h"
62 #include "../../include/linux/lnet/lnet.h"
63 #include "tracefile.h"
64
65 MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
66 MODULE_DESCRIPTION("Portals v3.1");
67 MODULE_LICENSE("GPL");
68
69 static struct dentry *lnet_debugfs_root;
70
71 /* called when opening /dev/device */
72 static int libcfs_psdev_open(unsigned long flags, void *args)
73 {
74         try_module_get(THIS_MODULE);
75         return 0;
76 }
77
78 /* called when closing /dev/device */
79 static int libcfs_psdev_release(unsigned long flags, void *args)
80 {
81         module_put(THIS_MODULE);
82         return 0;
83 }
84
85 static DECLARE_RWSEM(ioctl_list_sem);
86 static LIST_HEAD(ioctl_list);
87
88 int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand)
89 {
90         int rc = 0;
91
92         down_write(&ioctl_list_sem);
93         if (!list_empty(&hand->item))
94                 rc = -EBUSY;
95         else
96                 list_add_tail(&hand->item, &ioctl_list);
97         up_write(&ioctl_list_sem);
98
99         return rc;
100 }
101 EXPORT_SYMBOL(libcfs_register_ioctl);
102
103 int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand)
104 {
105         int rc = 0;
106
107         down_write(&ioctl_list_sem);
108         if (list_empty(&hand->item))
109                 rc = -ENOENT;
110         else
111                 list_del_init(&hand->item);
112         up_write(&ioctl_list_sem);
113
114         return rc;
115 }
116 EXPORT_SYMBOL(libcfs_deregister_ioctl);
117
118 static int libcfs_ioctl_int(struct cfs_psdev_file *pfile, unsigned long cmd,
119                             void __user *arg, struct libcfs_ioctl_data *data)
120 {
121         int err = -EINVAL;
122
123         switch (cmd) {
124         case IOC_LIBCFS_CLEAR_DEBUG:
125                 libcfs_debug_clear_buffer();
126                 return 0;
127         /*
128          * case IOC_LIBCFS_PANIC:
129          * Handled in arch/cfs_module.c
130          */
131         case IOC_LIBCFS_MARK_DEBUG:
132                 if (data->ioc_inlbuf1 == NULL ||
133                     data->ioc_inlbuf1[data->ioc_inllen1 - 1] != '\0')
134                         return -EINVAL;
135                 libcfs_debug_mark_buffer(data->ioc_inlbuf1);
136                 return 0;
137
138         default: {
139                 struct libcfs_ioctl_handler *hand;
140
141                 err = -EINVAL;
142                 down_read(&ioctl_list_sem);
143                 list_for_each_entry(hand, &ioctl_list, item) {
144                         err = hand->handle_ioctl(cmd, data);
145                         if (err != -EINVAL) {
146                                 if (err == 0)
147                                         err = libcfs_ioctl_popdata(arg,
148                                                         data, sizeof(*data));
149                                 break;
150                         }
151                 }
152                 up_read(&ioctl_list_sem);
153                 break;
154         }
155         }
156
157         return err;
158 }
159
160 static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd,
161                         void __user *arg)
162 {
163         char    *buf;
164         struct libcfs_ioctl_data *data;
165         int err = 0;
166
167         LIBCFS_ALLOC_GFP(buf, 1024, GFP_KERNEL);
168         if (buf == NULL)
169                 return -ENOMEM;
170
171         /* 'cmd' and permissions get checked in our arch-specific caller */
172         if (libcfs_ioctl_getdata(buf, buf + 800, arg)) {
173                 CERROR("PORTALS ioctl: data error\n");
174                 err = -EINVAL;
175                 goto out;
176         }
177         data = (struct libcfs_ioctl_data *)buf;
178
179         err = libcfs_ioctl_int(pfile, cmd, arg, data);
180
181 out:
182         LIBCFS_FREE(buf, 1024);
183         return err;
184 }
185
186 struct cfs_psdev_ops libcfs_psdev_ops = {
187         libcfs_psdev_open,
188         libcfs_psdev_release,
189         NULL,
190         NULL,
191         libcfs_ioctl
192 };
193
194 static int proc_call_handler(void *data, int write, loff_t *ppos,
195                 void __user *buffer, size_t *lenp,
196                 int (*handler)(void *data, int write,
197                 loff_t pos, void __user *buffer, int len))
198 {
199         int rc = handler(data, write, *ppos, buffer, *lenp);
200
201         if (rc < 0)
202                 return rc;
203
204         if (write) {
205                 *ppos += *lenp;
206         } else {
207                 *lenp = rc;
208                 *ppos += rc;
209         }
210         return 0;
211 }
212
213 static int __proc_dobitmasks(void *data, int write,
214                              loff_t pos, void __user *buffer, int nob)
215 {
216         const int     tmpstrlen = 512;
217         char     *tmpstr;
218         int        rc;
219         unsigned int *mask = data;
220         int        is_subsys = (mask == &libcfs_subsystem_debug) ? 1 : 0;
221         int        is_printk = (mask == &libcfs_printk) ? 1 : 0;
222
223         rc = cfs_trace_allocate_string_buffer(&tmpstr, tmpstrlen);
224         if (rc < 0)
225                 return rc;
226
227         if (!write) {
228                 libcfs_debug_mask2str(tmpstr, tmpstrlen, *mask, is_subsys);
229                 rc = strlen(tmpstr);
230
231                 if (pos >= rc) {
232                         rc = 0;
233                 } else {
234                         rc = cfs_trace_copyout_string(buffer, nob,
235                                                       tmpstr + pos, "\n");
236                 }
237         } else {
238                 rc = cfs_trace_copyin_string(tmpstr, tmpstrlen, buffer, nob);
239                 if (rc < 0) {
240                         kfree(tmpstr);
241                         return rc;
242                 }
243
244                 rc = libcfs_debug_str2mask(mask, tmpstr, is_subsys);
245                 /* Always print LBUG/LASSERT to console, so keep this mask */
246                 if (is_printk)
247                         *mask |= D_EMERG;
248         }
249
250         kfree(tmpstr);
251         return rc;
252 }
253
254 static int proc_dobitmasks(struct ctl_table *table, int write,
255                            void __user *buffer, size_t *lenp, loff_t *ppos)
256 {
257         return proc_call_handler(table->data, write, ppos, buffer, lenp,
258                                  __proc_dobitmasks);
259 }
260
261 static int __proc_dump_kernel(void *data, int write,
262                               loff_t pos, void __user *buffer, int nob)
263 {
264         if (!write)
265                 return 0;
266
267         return cfs_trace_dump_debug_buffer_usrstr(buffer, nob);
268 }
269
270 static int proc_dump_kernel(struct ctl_table *table, int write,
271                             void __user *buffer, size_t *lenp, loff_t *ppos)
272 {
273         return proc_call_handler(table->data, write, ppos, buffer, lenp,
274                                  __proc_dump_kernel);
275 }
276
277 static int __proc_daemon_file(void *data, int write,
278                               loff_t pos, void __user *buffer, int nob)
279 {
280         if (!write) {
281                 int len = strlen(cfs_tracefile);
282
283                 if (pos >= len)
284                         return 0;
285
286                 return cfs_trace_copyout_string(buffer, nob,
287                                                 cfs_tracefile + pos, "\n");
288         }
289
290         return cfs_trace_daemon_command_usrstr(buffer, nob);
291 }
292
293 static int proc_daemon_file(struct ctl_table *table, int write,
294                             void __user *buffer, size_t *lenp, loff_t *ppos)
295 {
296         return proc_call_handler(table->data, write, ppos, buffer, lenp,
297                                  __proc_daemon_file);
298 }
299
300 static int libcfs_force_lbug(struct ctl_table *table, int write,
301                              void __user *buffer,
302                              size_t *lenp, loff_t *ppos)
303 {
304         if (write)
305                 LBUG();
306         return 0;
307 }
308
309 static int proc_fail_loc(struct ctl_table *table, int write,
310                          void __user *buffer,
311                          size_t *lenp, loff_t *ppos)
312 {
313         int rc;
314         long old_fail_loc = cfs_fail_loc;
315
316         rc = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
317         if (old_fail_loc != cfs_fail_loc)
318                 wake_up(&cfs_race_waitq);
319         return rc;
320 }
321
322 static int __proc_cpt_table(void *data, int write,
323                             loff_t pos, void __user *buffer, int nob)
324 {
325         char *buf = NULL;
326         int   len = 4096;
327         int   rc  = 0;
328
329         if (write)
330                 return -EPERM;
331
332         LASSERT(cfs_cpt_table != NULL);
333
334         while (1) {
335                 LIBCFS_ALLOC(buf, len);
336                 if (buf == NULL)
337                         return -ENOMEM;
338
339                 rc = cfs_cpt_table_print(cfs_cpt_table, buf, len);
340                 if (rc >= 0)
341                         break;
342
343                 if (rc == -EFBIG) {
344                         LIBCFS_FREE(buf, len);
345                         len <<= 1;
346                         continue;
347                 }
348                 goto out;
349         }
350
351         if (pos >= rc) {
352                 rc = 0;
353                 goto out;
354         }
355
356         rc = cfs_trace_copyout_string(buffer, nob, buf + pos, NULL);
357  out:
358         if (buf != NULL)
359                 LIBCFS_FREE(buf, len);
360         return rc;
361 }
362
363 static int proc_cpt_table(struct ctl_table *table, int write,
364                            void __user *buffer, size_t *lenp, loff_t *ppos)
365 {
366         return proc_call_handler(table->data, write, ppos, buffer, lenp,
367                                  __proc_cpt_table);
368 }
369
370 static struct ctl_table lnet_table[] = {
371         /*
372          * NB No .strategy entries have been provided since sysctl(8) prefers
373          * to go via /proc for portability.
374          */
375         {
376                 .procname = "debug",
377                 .data     = &libcfs_debug,
378                 .maxlen   = sizeof(int),
379                 .mode     = 0644,
380                 .proc_handler = &proc_dobitmasks,
381         },
382         {
383                 .procname = "subsystem_debug",
384                 .data     = &libcfs_subsystem_debug,
385                 .maxlen   = sizeof(int),
386                 .mode     = 0644,
387                 .proc_handler = &proc_dobitmasks,
388         },
389         {
390                 .procname = "printk",
391                 .data     = &libcfs_printk,
392                 .maxlen   = sizeof(int),
393                 .mode     = 0644,
394                 .proc_handler = &proc_dobitmasks,
395         },
396         {
397                 .procname = "cpu_partition_table",
398                 .maxlen   = 128,
399                 .mode     = 0444,
400                 .proc_handler = &proc_cpt_table,
401         },
402
403         {
404                 .procname = "upcall",
405                 .data     = lnet_upcall,
406                 .maxlen   = sizeof(lnet_upcall),
407                 .mode     = 0644,
408                 .proc_handler = &proc_dostring,
409         },
410         {
411                 .procname = "debug_log_upcall",
412                 .data     = lnet_debug_log_upcall,
413                 .maxlen   = sizeof(lnet_debug_log_upcall),
414                 .mode     = 0644,
415                 .proc_handler = &proc_dostring,
416         },
417         {
418                 .procname = "catastrophe",
419                 .data     = &libcfs_catastrophe,
420                 .maxlen   = sizeof(int),
421                 .mode     = 0444,
422                 .proc_handler = &proc_dointvec,
423         },
424         {
425                 .procname = "dump_kernel",
426                 .maxlen   = 256,
427                 .mode     = 0200,
428                 .proc_handler = &proc_dump_kernel,
429         },
430         {
431                 .procname = "daemon_file",
432                 .mode     = 0644,
433                 .maxlen   = 256,
434                 .proc_handler = &proc_daemon_file,
435         },
436         {
437                 .procname = "force_lbug",
438                 .data     = NULL,
439                 .maxlen   = 0,
440                 .mode     = 0200,
441                 .proc_handler = &libcfs_force_lbug
442         },
443         {
444                 .procname = "fail_loc",
445                 .data     = &cfs_fail_loc,
446                 .maxlen   = sizeof(cfs_fail_loc),
447                 .mode     = 0644,
448                 .proc_handler = &proc_fail_loc
449         },
450         {
451                 .procname = "fail_val",
452                 .data     = &cfs_fail_val,
453                 .maxlen   = sizeof(int),
454                 .mode     = 0644,
455                 .proc_handler = &proc_dointvec
456         },
457         {
458         }
459 };
460
461 static const struct lnet_debugfs_symlink_def lnet_debugfs_symlinks[] = {
462         { "console_ratelimit",
463           "/sys/module/libcfs/parameters/libcfs_console_ratelimit"},
464         { "debug_path",
465           "/sys/module/libcfs/parameters/libcfs_debug_file_path"},
466         { "panic_on_lbug",
467           "/sys/module/libcfs/parameters/libcfs_panic_on_lbug"},
468         { "libcfs_console_backoff",
469           "/sys/module/libcfs/parameters/libcfs_console_backoff"},
470         { "debug_mb",
471           "/sys/module/libcfs/parameters/libcfs_debug_mb"},
472         { "console_min_delay_centisecs",
473           "/sys/module/libcfs/parameters/libcfs_console_min_delay"},
474         { "console_max_delay_centisecs",
475           "/sys/module/libcfs/parameters/libcfs_console_max_delay"},
476         {},
477 };
478
479 static ssize_t lnet_debugfs_read(struct file *filp, char __user *buf,
480                                  size_t count, loff_t *ppos)
481 {
482         struct ctl_table *table = filp->private_data;
483         int error;
484
485         error = table->proc_handler(table, 0, (void __user *)buf, &count, ppos);
486         if (!error)
487                 error = count;
488
489         return error;
490 }
491
492 static ssize_t lnet_debugfs_write(struct file *filp, const char __user *buf,
493                                   size_t count, loff_t *ppos)
494 {
495         struct ctl_table *table = filp->private_data;
496         int error;
497
498         error = table->proc_handler(table, 1, (void __user *)buf, &count, ppos);
499         if (!error)
500                 error = count;
501
502         return error;
503 }
504
505 static const struct file_operations lnet_debugfs_file_operations_rw = {
506         .open           = simple_open,
507         .read           = lnet_debugfs_read,
508         .write          = lnet_debugfs_write,
509         .llseek         = default_llseek,
510 };
511
512 static const struct file_operations lnet_debugfs_file_operations_ro = {
513         .open           = simple_open,
514         .read           = lnet_debugfs_read,
515         .llseek         = default_llseek,
516 };
517
518 static const struct file_operations lnet_debugfs_file_operations_wo = {
519         .open           = simple_open,
520         .write          = lnet_debugfs_write,
521         .llseek         = default_llseek,
522 };
523
524 static const struct file_operations *lnet_debugfs_fops_select(umode_t mode)
525 {
526         if (!(mode & S_IWUGO))
527                 return &lnet_debugfs_file_operations_ro;
528
529         if (!(mode & S_IRUGO))
530                 return &lnet_debugfs_file_operations_wo;
531
532         return &lnet_debugfs_file_operations_rw;
533 }
534
535 void lustre_insert_debugfs(struct ctl_table *table,
536                            const struct lnet_debugfs_symlink_def *symlinks)
537 {
538         if (lnet_debugfs_root == NULL)
539                 lnet_debugfs_root = debugfs_create_dir("lnet", NULL);
540
541         /* Even if we cannot create, just ignore it altogether) */
542         if (IS_ERR_OR_NULL(lnet_debugfs_root))
543                 return;
544
545         /* We don't save the dentry returned in next two calls, because
546          * we don't call debugfs_remove() but rather remove_recursive()
547          */
548         for (; table->procname; table++)
549                 debugfs_create_file(table->procname, table->mode,
550                                     lnet_debugfs_root, table,
551                                     lnet_debugfs_fops_select(table->mode));
552
553         for (; symlinks && symlinks->name; symlinks++)
554                 debugfs_create_symlink(symlinks->name, lnet_debugfs_root,
555                                        symlinks->target);
556
557 }
558 EXPORT_SYMBOL_GPL(lustre_insert_debugfs);
559
560 static void lustre_remove_debugfs(void)
561 {
562         if (lnet_debugfs_root != NULL)
563                 debugfs_remove_recursive(lnet_debugfs_root);
564
565         lnet_debugfs_root = NULL;
566 }
567
568 static int init_libcfs_module(void)
569 {
570         int rc;
571
572         rc = libcfs_debug_init(5 * 1024 * 1024);
573         if (rc < 0) {
574                 pr_err("LustreError: libcfs_debug_init: %d\n", rc);
575                 return rc;
576         }
577
578         rc = cfs_cpu_init();
579         if (rc != 0)
580                 goto cleanup_debug;
581
582         rc = misc_register(&libcfs_dev);
583         if (rc) {
584                 CERROR("misc_register: error %d\n", rc);
585                 goto cleanup_cpu;
586         }
587
588         rc = cfs_wi_startup();
589         if (rc) {
590                 CERROR("initialize workitem: error %d\n", rc);
591                 goto cleanup_deregister;
592         }
593
594         /* max to 4 threads, should be enough for rehash */
595         rc = min(cfs_cpt_weight(cfs_cpt_table, CFS_CPT_ANY), 4);
596         rc = cfs_wi_sched_create("cfs_rh", cfs_cpt_table, CFS_CPT_ANY,
597                                  rc, &cfs_sched_rehash);
598         if (rc != 0) {
599                 CERROR("Startup workitem scheduler: error: %d\n", rc);
600                 goto cleanup_deregister;
601         }
602
603         rc = cfs_crypto_register();
604         if (rc) {
605                 CERROR("cfs_crypto_register: error %d\n", rc);
606                 goto cleanup_wi;
607         }
608
609         lustre_insert_debugfs(lnet_table, lnet_debugfs_symlinks);
610
611         CDEBUG(D_OTHER, "portals setup OK\n");
612         return 0;
613  cleanup_wi:
614         cfs_wi_shutdown();
615  cleanup_deregister:
616         misc_deregister(&libcfs_dev);
617 cleanup_cpu:
618         cfs_cpu_fini();
619  cleanup_debug:
620         libcfs_debug_cleanup();
621         return rc;
622 }
623
624 static void exit_libcfs_module(void)
625 {
626         int rc;
627
628         lustre_remove_debugfs();
629
630         if (cfs_sched_rehash) {
631                 cfs_wi_sched_destroy(cfs_sched_rehash);
632                 cfs_sched_rehash = NULL;
633         }
634
635         cfs_crypto_unregister();
636         cfs_wi_shutdown();
637
638         misc_deregister(&libcfs_dev);
639
640         cfs_cpu_fini();
641
642         rc = libcfs_debug_cleanup();
643         if (rc)
644                 pr_err("LustreError: libcfs_debug_cleanup: %d\n", rc);
645 }
646
647 MODULE_VERSION("1.0.0");
648
649 module_init(init_libcfs_module);
650 module_exit(exit_libcfs_module);