]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/staging/lustre/lustre/libcfs/module.c
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target...
[mirror_ubuntu-artful-kernel.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, 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
54 # define DEBUG_SUBSYSTEM S_LNET
55
56 #include "../../include/linux/libcfs/libcfs.h"
57 #include <asm/div64.h>
58
59 #include "../../include/linux/libcfs/libcfs_crypto.h"
60 #include "../../include/linux/lnet/lib-lnet.h"
61 #include "../../include/linux/lnet/lnet.h"
62 #include "tracefile.h"
63
64 MODULE_AUTHOR("Peter J. Braam <braam@clusterfs.com>");
65 MODULE_DESCRIPTION("Portals v3.1");
66 MODULE_LICENSE("GPL");
67
68 extern struct miscdevice libcfs_dev;
69 extern struct cfs_wi_sched *cfs_sched_rehash;
70 extern void libcfs_init_nidstrings(void);
71
72 static int insert_proc(void);
73 static void remove_proc(void);
74
75 static struct ctl_table_header *lnet_table_header;
76 extern char lnet_upcall[1024];
77 /**
78 * The path of debug log dump upcall script.
79 */
80 extern char lnet_debug_log_upcall[1024];
81
82 #define CTL_LNET (0x100)
83
84 enum {
85 PSDEV_DEBUG = 1, /* control debugging */
86 PSDEV_SUBSYSTEM_DEBUG, /* control debugging */
87 PSDEV_PRINTK, /* force all messages to console */
88 PSDEV_CONSOLE_RATELIMIT, /* ratelimit console messages */
89 PSDEV_CONSOLE_MAX_DELAY_CS, /* maximum delay over which we skip messages */
90 PSDEV_CONSOLE_MIN_DELAY_CS, /* initial delay over which we skip messages */
91 PSDEV_CONSOLE_BACKOFF, /* delay increase factor */
92 PSDEV_DEBUG_PATH, /* crashdump log location */
93 PSDEV_DEBUG_DUMP_PATH, /* crashdump tracelog location */
94 PSDEV_CPT_TABLE, /* information about cpu partitions */
95 PSDEV_LNET_UPCALL, /* User mode upcall script */
96 PSDEV_LNET_MEMUSED, /* bytes currently PORTAL_ALLOCated */
97 PSDEV_LNET_CATASTROPHE, /* if we have LBUGged or panic'd */
98 PSDEV_LNET_PANIC_ON_LBUG, /* flag to panic on LBUG */
99 PSDEV_LNET_DUMP_KERNEL, /* snapshot kernel debug buffer to file */
100 PSDEV_LNET_DAEMON_FILE, /* spool kernel debug buffer to file */
101 PSDEV_LNET_DEBUG_MB, /* size of debug buffer */
102 PSDEV_LNET_DEBUG_LOG_UPCALL, /* debug log upcall script */
103 PSDEV_LNET_WATCHDOG_RATELIMIT, /* ratelimit watchdog messages */
104 PSDEV_LNET_FORCE_LBUG, /* hook to force an LBUG */
105 PSDEV_LNET_FAIL_LOC, /* control test failures instrumentation */
106 PSDEV_LNET_FAIL_VAL, /* userdata for fail loc */
107 };
108
109 static void kportal_memhog_free (struct libcfs_device_userstate *ldu)
110 {
111 struct page **level0p = &ldu->ldu_memhog_root_page;
112 struct page **level1p;
113 struct page **level2p;
114 int count1;
115 int count2;
116
117 if (*level0p != NULL) {
118
119 level1p = (struct page **)page_address(*level0p);
120 count1 = 0;
121
122 while (count1 < PAGE_CACHE_SIZE/sizeof(struct page *) &&
123 *level1p != NULL) {
124
125 level2p = (struct page **)page_address(*level1p);
126 count2 = 0;
127
128 while (count2 < PAGE_CACHE_SIZE/sizeof(struct page *) &&
129 *level2p != NULL) {
130
131 __free_page(*level2p);
132 ldu->ldu_memhog_pages--;
133 level2p++;
134 count2++;
135 }
136
137 __free_page(*level1p);
138 ldu->ldu_memhog_pages--;
139 level1p++;
140 count1++;
141 }
142
143 __free_page(*level0p);
144 ldu->ldu_memhog_pages--;
145
146 *level0p = NULL;
147 }
148
149 LASSERT (ldu->ldu_memhog_pages == 0);
150 }
151
152 static int kportal_memhog_alloc(struct libcfs_device_userstate *ldu, int npages,
153 gfp_t flags)
154 {
155 struct page **level0p;
156 struct page **level1p;
157 struct page **level2p;
158 int count1;
159 int count2;
160
161 LASSERT (ldu->ldu_memhog_pages == 0);
162 LASSERT (ldu->ldu_memhog_root_page == NULL);
163
164 if (npages < 0)
165 return -EINVAL;
166
167 if (npages == 0)
168 return 0;
169
170 level0p = &ldu->ldu_memhog_root_page;
171 *level0p = alloc_page(flags);
172 if (*level0p == NULL)
173 return -ENOMEM;
174 ldu->ldu_memhog_pages++;
175
176 level1p = (struct page **)page_address(*level0p);
177 count1 = 0;
178 memset(level1p, 0, PAGE_CACHE_SIZE);
179
180 while (ldu->ldu_memhog_pages < npages &&
181 count1 < PAGE_CACHE_SIZE/sizeof(struct page *)) {
182
183 if (cfs_signal_pending())
184 return -EINTR;
185
186 *level1p = alloc_page(flags);
187 if (*level1p == NULL)
188 return -ENOMEM;
189 ldu->ldu_memhog_pages++;
190
191 level2p = (struct page **)page_address(*level1p);
192 count2 = 0;
193 memset(level2p, 0, PAGE_CACHE_SIZE);
194
195 while (ldu->ldu_memhog_pages < npages &&
196 count2 < PAGE_CACHE_SIZE/sizeof(struct page *)) {
197
198 if (cfs_signal_pending())
199 return -EINTR;
200
201 *level2p = alloc_page(flags);
202 if (*level2p == NULL)
203 return -ENOMEM;
204 ldu->ldu_memhog_pages++;
205
206 level2p++;
207 count2++;
208 }
209
210 level1p++;
211 count1++;
212 }
213
214 return 0;
215 }
216
217 /* called when opening /dev/device */
218 static int libcfs_psdev_open(unsigned long flags, void *args)
219 {
220 struct libcfs_device_userstate *ldu;
221
222 try_module_get(THIS_MODULE);
223
224 LIBCFS_ALLOC(ldu, sizeof(*ldu));
225 if (ldu != NULL) {
226 ldu->ldu_memhog_pages = 0;
227 ldu->ldu_memhog_root_page = NULL;
228 }
229 *(struct libcfs_device_userstate **)args = ldu;
230
231 return 0;
232 }
233
234 /* called when closing /dev/device */
235 static int libcfs_psdev_release(unsigned long flags, void *args)
236 {
237 struct libcfs_device_userstate *ldu;
238
239 ldu = (struct libcfs_device_userstate *)args;
240 if (ldu != NULL) {
241 kportal_memhog_free(ldu);
242 LIBCFS_FREE(ldu, sizeof(*ldu));
243 }
244
245 module_put(THIS_MODULE);
246 return 0;
247 }
248
249 static DECLARE_RWSEM(ioctl_list_sem);
250 static LIST_HEAD(ioctl_list);
251
252 int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand)
253 {
254 int rc = 0;
255
256 down_write(&ioctl_list_sem);
257 if (!list_empty(&hand->item))
258 rc = -EBUSY;
259 else
260 list_add_tail(&hand->item, &ioctl_list);
261 up_write(&ioctl_list_sem);
262
263 return rc;
264 }
265 EXPORT_SYMBOL(libcfs_register_ioctl);
266
267 int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand)
268 {
269 int rc = 0;
270
271 down_write(&ioctl_list_sem);
272 if (list_empty(&hand->item))
273 rc = -ENOENT;
274 else
275 list_del_init(&hand->item);
276 up_write(&ioctl_list_sem);
277
278 return rc;
279 }
280 EXPORT_SYMBOL(libcfs_deregister_ioctl);
281
282 static int libcfs_ioctl_int(struct cfs_psdev_file *pfile, unsigned long cmd,
283 void *arg, struct libcfs_ioctl_data *data)
284 {
285 int err = -EINVAL;
286
287 switch (cmd) {
288 case IOC_LIBCFS_CLEAR_DEBUG:
289 libcfs_debug_clear_buffer();
290 return 0;
291 /*
292 * case IOC_LIBCFS_PANIC:
293 * Handled in arch/cfs_module.c
294 */
295 case IOC_LIBCFS_MARK_DEBUG:
296 if (data->ioc_inlbuf1 == NULL ||
297 data->ioc_inlbuf1[data->ioc_inllen1 - 1] != '\0')
298 return -EINVAL;
299 libcfs_debug_mark_buffer(data->ioc_inlbuf1);
300 return 0;
301 case IOC_LIBCFS_MEMHOG:
302 if (pfile->private_data == NULL) {
303 err = -EINVAL;
304 } else {
305 kportal_memhog_free(pfile->private_data);
306 /* XXX The ioc_flags is not GFP flags now, need to be fixed */
307 err = kportal_memhog_alloc(pfile->private_data,
308 data->ioc_count,
309 data->ioc_flags);
310 if (err != 0)
311 kportal_memhog_free(pfile->private_data);
312 }
313 break;
314
315 case IOC_LIBCFS_PING_TEST: {
316 extern void (kping_client)(struct libcfs_ioctl_data *);
317 void (*ping)(struct libcfs_ioctl_data *);
318
319 CDEBUG(D_IOCTL, "doing %d pings to nid %s (%s)\n",
320 data->ioc_count, libcfs_nid2str(data->ioc_nid),
321 libcfs_nid2str(data->ioc_nid));
322 ping = symbol_get(kping_client);
323 if (!ping)
324 CERROR("symbol_get failed\n");
325 else {
326 ping(data);
327 symbol_put(kping_client);
328 }
329 return 0;
330 }
331
332 default: {
333 struct libcfs_ioctl_handler *hand;
334 err = -EINVAL;
335 down_read(&ioctl_list_sem);
336 list_for_each_entry(hand, &ioctl_list, item) {
337 err = hand->handle_ioctl(cmd, data);
338 if (err != -EINVAL) {
339 if (err == 0)
340 err = libcfs_ioctl_popdata(arg,
341 data, sizeof (*data));
342 break;
343 }
344 }
345 up_read(&ioctl_list_sem);
346 break;
347 }
348 }
349
350 return err;
351 }
352
353 static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, void *arg)
354 {
355 char *buf;
356 struct libcfs_ioctl_data *data;
357 int err = 0;
358
359 LIBCFS_ALLOC_GFP(buf, 1024, GFP_IOFS);
360 if (buf == NULL)
361 return -ENOMEM;
362
363 /* 'cmd' and permissions get checked in our arch-specific caller */
364 if (libcfs_ioctl_getdata(buf, buf + 800, (void *)arg)) {
365 CERROR("PORTALS ioctl: data error\n");
366 err = -EINVAL;
367 goto out;
368 }
369 data = (struct libcfs_ioctl_data *)buf;
370
371 err = libcfs_ioctl_int(pfile, cmd, arg, data);
372
373 out:
374 LIBCFS_FREE(buf, 1024);
375 return err;
376 }
377
378
379 struct cfs_psdev_ops libcfs_psdev_ops = {
380 libcfs_psdev_open,
381 libcfs_psdev_release,
382 NULL,
383 NULL,
384 libcfs_ioctl
385 };
386
387 static int init_libcfs_module(void)
388 {
389 int rc;
390
391 libcfs_arch_init();
392 libcfs_init_nidstrings();
393
394 rc = libcfs_debug_init(5 * 1024 * 1024);
395 if (rc < 0) {
396 pr_err("LustreError: libcfs_debug_init: %d\n", rc);
397 return rc;
398 }
399
400 rc = cfs_cpu_init();
401 if (rc != 0)
402 goto cleanup_debug;
403
404 rc = misc_register(&libcfs_dev);
405 if (rc) {
406 CERROR("misc_register: error %d\n", rc);
407 goto cleanup_cpu;
408 }
409
410 rc = cfs_wi_startup();
411 if (rc) {
412 CERROR("initialize workitem: error %d\n", rc);
413 goto cleanup_deregister;
414 }
415
416 /* max to 4 threads, should be enough for rehash */
417 rc = min(cfs_cpt_weight(cfs_cpt_table, CFS_CPT_ANY), 4);
418 rc = cfs_wi_sched_create("cfs_rh", cfs_cpt_table, CFS_CPT_ANY,
419 rc, &cfs_sched_rehash);
420 if (rc != 0) {
421 CERROR("Startup workitem scheduler: error: %d\n", rc);
422 goto cleanup_deregister;
423 }
424
425 rc = cfs_crypto_register();
426 if (rc) {
427 CERROR("cfs_crypto_register: error %d\n", rc);
428 goto cleanup_wi;
429 }
430
431
432 rc = insert_proc();
433 if (rc) {
434 CERROR("insert_proc: error %d\n", rc);
435 goto cleanup_crypto;
436 }
437
438 CDEBUG (D_OTHER, "portals setup OK\n");
439 return 0;
440 cleanup_crypto:
441 cfs_crypto_unregister();
442 cleanup_wi:
443 cfs_wi_shutdown();
444 cleanup_deregister:
445 misc_deregister(&libcfs_dev);
446 cleanup_cpu:
447 cfs_cpu_fini();
448 cleanup_debug:
449 libcfs_debug_cleanup();
450 return rc;
451 }
452
453 static void exit_libcfs_module(void)
454 {
455 int rc;
456
457 remove_proc();
458
459 CDEBUG(D_MALLOC, "before Portals cleanup: kmem %d\n",
460 atomic_read(&libcfs_kmemory));
461
462 if (cfs_sched_rehash != NULL) {
463 cfs_wi_sched_destroy(cfs_sched_rehash);
464 cfs_sched_rehash = NULL;
465 }
466
467 cfs_crypto_unregister();
468 cfs_wi_shutdown();
469
470 rc = misc_deregister(&libcfs_dev);
471 if (rc)
472 CERROR("misc_deregister error %d\n", rc);
473
474 cfs_cpu_fini();
475
476 if (atomic_read(&libcfs_kmemory) != 0)
477 CERROR("Portals memory leaked: %d bytes\n",
478 atomic_read(&libcfs_kmemory));
479
480 rc = libcfs_debug_cleanup();
481 if (rc)
482 pr_err("LustreError: libcfs_debug_cleanup: %d\n", rc);
483
484 libcfs_arch_cleanup();
485 }
486
487 static int proc_call_handler(void *data, int write, loff_t *ppos,
488 void __user *buffer, size_t *lenp,
489 int (*handler)(void *data, int write,
490 loff_t pos, void __user *buffer, int len))
491 {
492 int rc = handler(data, write, *ppos, buffer, *lenp);
493
494 if (rc < 0)
495 return rc;
496
497 if (write) {
498 *ppos += *lenp;
499 } else {
500 *lenp = rc;
501 *ppos += rc;
502 }
503 return 0;
504 }
505
506 static int __proc_dobitmasks(void *data, int write,
507 loff_t pos, void __user *buffer, int nob)
508 {
509 const int tmpstrlen = 512;
510 char *tmpstr;
511 int rc;
512 unsigned int *mask = data;
513 int is_subsys = (mask == &libcfs_subsystem_debug) ? 1 : 0;
514 int is_printk = (mask == &libcfs_printk) ? 1 : 0;
515
516 rc = cfs_trace_allocate_string_buffer(&tmpstr, tmpstrlen);
517 if (rc < 0)
518 return rc;
519
520 if (!write) {
521 libcfs_debug_mask2str(tmpstr, tmpstrlen, *mask, is_subsys);
522 rc = strlen(tmpstr);
523
524 if (pos >= rc) {
525 rc = 0;
526 } else {
527 rc = cfs_trace_copyout_string(buffer, nob,
528 tmpstr + pos, "\n");
529 }
530 } else {
531 rc = cfs_trace_copyin_string(tmpstr, tmpstrlen, buffer, nob);
532 if (rc < 0) {
533 cfs_trace_free_string_buffer(tmpstr, tmpstrlen);
534 return rc;
535 }
536
537 rc = libcfs_debug_str2mask(mask, tmpstr, is_subsys);
538 /* Always print LBUG/LASSERT to console, so keep this mask */
539 if (is_printk)
540 *mask |= D_EMERG;
541 }
542
543 cfs_trace_free_string_buffer(tmpstr, tmpstrlen);
544 return rc;
545 }
546
547 static int proc_dobitmasks(struct ctl_table *table, int write,
548 void __user *buffer, size_t *lenp, loff_t *ppos)
549 {
550 return proc_call_handler(table->data, write, ppos, buffer, lenp,
551 __proc_dobitmasks);
552 }
553
554 static int min_watchdog_ratelimit; /* disable ratelimiting */
555 static int max_watchdog_ratelimit = (24*60*60); /* limit to once per day */
556
557 static int __proc_dump_kernel(void *data, int write,
558 loff_t pos, void __user *buffer, int nob)
559 {
560 if (!write)
561 return 0;
562
563 return cfs_trace_dump_debug_buffer_usrstr(buffer, nob);
564 }
565
566 static int proc_dump_kernel(struct ctl_table *table, int write,
567 void __user *buffer, size_t *lenp, loff_t *ppos)
568 {
569 return proc_call_handler(table->data, write, ppos, buffer, lenp,
570 __proc_dump_kernel);
571 }
572
573 static int __proc_daemon_file(void *data, int write,
574 loff_t pos, void __user *buffer, int nob)
575 {
576 if (!write) {
577 int len = strlen(cfs_tracefile);
578
579 if (pos >= len)
580 return 0;
581
582 return cfs_trace_copyout_string(buffer, nob,
583 cfs_tracefile + pos, "\n");
584 }
585
586 return cfs_trace_daemon_command_usrstr(buffer, nob);
587 }
588
589 static int proc_daemon_file(struct ctl_table *table, int write,
590 void __user *buffer, size_t *lenp, loff_t *ppos)
591 {
592 return proc_call_handler(table->data, write, ppos, buffer, lenp,
593 __proc_daemon_file);
594 }
595
596 static int __proc_debug_mb(void *data, int write,
597 loff_t pos, void __user *buffer, int nob)
598 {
599 if (!write) {
600 char tmpstr[32];
601 int len = snprintf(tmpstr, sizeof(tmpstr), "%d",
602 cfs_trace_get_debug_mb());
603
604 if (pos >= len)
605 return 0;
606
607 return cfs_trace_copyout_string(buffer, nob, tmpstr + pos,
608 "\n");
609 }
610
611 return cfs_trace_set_debug_mb_usrstr(buffer, nob);
612 }
613
614 static int proc_debug_mb(struct ctl_table *table, int write,
615 void __user *buffer, size_t *lenp, loff_t *ppos)
616 {
617 return proc_call_handler(table->data, write, ppos, buffer, lenp,
618 __proc_debug_mb);
619 }
620
621 static int proc_console_max_delay_cs(struct ctl_table *table, int write,
622 void __user *buffer, size_t *lenp,
623 loff_t *ppos)
624 {
625 int rc, max_delay_cs;
626 struct ctl_table dummy = *table;
627 long d;
628
629 dummy.data = &max_delay_cs;
630 dummy.proc_handler = &proc_dointvec;
631
632 if (!write) { /* read */
633 max_delay_cs = cfs_duration_sec(libcfs_console_max_delay * 100);
634 rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
635 return rc;
636 }
637
638 /* write */
639 max_delay_cs = 0;
640 rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
641 if (rc < 0)
642 return rc;
643 if (max_delay_cs <= 0)
644 return -EINVAL;
645
646 d = cfs_time_seconds(max_delay_cs) / 100;
647 if (d == 0 || d < libcfs_console_min_delay)
648 return -EINVAL;
649 libcfs_console_max_delay = d;
650
651 return rc;
652 }
653
654 static int proc_console_min_delay_cs(struct ctl_table *table, int write,
655 void __user *buffer, size_t *lenp,
656 loff_t *ppos)
657 {
658 int rc, min_delay_cs;
659 struct ctl_table dummy = *table;
660 long d;
661
662 dummy.data = &min_delay_cs;
663 dummy.proc_handler = &proc_dointvec;
664
665 if (!write) { /* read */
666 min_delay_cs = cfs_duration_sec(libcfs_console_min_delay * 100);
667 rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
668 return rc;
669 }
670
671 /* write */
672 min_delay_cs = 0;
673 rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
674 if (rc < 0)
675 return rc;
676 if (min_delay_cs <= 0)
677 return -EINVAL;
678
679 d = cfs_time_seconds(min_delay_cs) / 100;
680 if (d == 0 || d > libcfs_console_max_delay)
681 return -EINVAL;
682 libcfs_console_min_delay = d;
683
684 return rc;
685 }
686
687 static int proc_console_backoff(struct ctl_table *table, int write,
688 void __user *buffer, size_t *lenp, loff_t *ppos)
689 {
690 int rc, backoff;
691 struct ctl_table dummy = *table;
692
693 dummy.data = &backoff;
694 dummy.proc_handler = &proc_dointvec;
695
696 if (!write) { /* read */
697 backoff = libcfs_console_backoff;
698 rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
699 return rc;
700 }
701
702 /* write */
703 backoff = 0;
704 rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
705 if (rc < 0)
706 return rc;
707 if (backoff <= 0)
708 return -EINVAL;
709
710 libcfs_console_backoff = backoff;
711
712 return rc;
713 }
714
715 static int libcfs_force_lbug(struct ctl_table *table, int write,
716 void __user *buffer,
717 size_t *lenp, loff_t *ppos)
718 {
719 if (write)
720 LBUG();
721 return 0;
722 }
723
724 static int proc_fail_loc(struct ctl_table *table, int write,
725 void __user *buffer,
726 size_t *lenp, loff_t *ppos)
727 {
728 int rc;
729 long old_fail_loc = cfs_fail_loc;
730
731 rc = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
732 if (old_fail_loc != cfs_fail_loc)
733 wake_up(&cfs_race_waitq);
734 return rc;
735 }
736
737 static int __proc_cpt_table(void *data, int write,
738 loff_t pos, void __user *buffer, int nob)
739 {
740 char *buf = NULL;
741 int len = 4096;
742 int rc = 0;
743
744 if (write)
745 return -EPERM;
746
747 LASSERT(cfs_cpt_table != NULL);
748
749 while (1) {
750 LIBCFS_ALLOC(buf, len);
751 if (buf == NULL)
752 return -ENOMEM;
753
754 rc = cfs_cpt_table_print(cfs_cpt_table, buf, len);
755 if (rc >= 0)
756 break;
757
758 if (rc == -EFBIG) {
759 LIBCFS_FREE(buf, len);
760 len <<= 1;
761 continue;
762 }
763 goto out;
764 }
765
766 if (pos >= rc) {
767 rc = 0;
768 goto out;
769 }
770
771 rc = cfs_trace_copyout_string(buffer, nob, buf + pos, NULL);
772 out:
773 if (buf != NULL)
774 LIBCFS_FREE(buf, len);
775 return rc;
776 }
777
778 static int proc_cpt_table(struct ctl_table *table, int write,
779 void __user *buffer, size_t *lenp, loff_t *ppos)
780 {
781 return proc_call_handler(table->data, write, ppos, buffer, lenp,
782 __proc_cpt_table);
783 }
784
785 static struct ctl_table lnet_table[] = {
786 /*
787 * NB No .strategy entries have been provided since sysctl(8) prefers
788 * to go via /proc for portability.
789 */
790 {
791 .procname = "debug",
792 .data = &libcfs_debug,
793 .maxlen = sizeof(int),
794 .mode = 0644,
795 .proc_handler = &proc_dobitmasks,
796 },
797 {
798 .procname = "subsystem_debug",
799 .data = &libcfs_subsystem_debug,
800 .maxlen = sizeof(int),
801 .mode = 0644,
802 .proc_handler = &proc_dobitmasks,
803 },
804 {
805 .procname = "printk",
806 .data = &libcfs_printk,
807 .maxlen = sizeof(int),
808 .mode = 0644,
809 .proc_handler = &proc_dobitmasks,
810 },
811 {
812 .procname = "console_ratelimit",
813 .data = &libcfs_console_ratelimit,
814 .maxlen = sizeof(int),
815 .mode = 0644,
816 .proc_handler = &proc_dointvec
817 },
818 {
819 .procname = "console_max_delay_centisecs",
820 .maxlen = sizeof(int),
821 .mode = 0644,
822 .proc_handler = &proc_console_max_delay_cs
823 },
824 {
825 .procname = "console_min_delay_centisecs",
826 .maxlen = sizeof(int),
827 .mode = 0644,
828 .proc_handler = &proc_console_min_delay_cs
829 },
830 {
831 .procname = "console_backoff",
832 .maxlen = sizeof(int),
833 .mode = 0644,
834 .proc_handler = &proc_console_backoff
835 },
836
837 {
838 .procname = "debug_path",
839 .data = libcfs_debug_file_path_arr,
840 .maxlen = sizeof(libcfs_debug_file_path_arr),
841 .mode = 0644,
842 .proc_handler = &proc_dostring,
843 },
844
845 {
846 .procname = "cpu_partition_table",
847 .maxlen = 128,
848 .mode = 0444,
849 .proc_handler = &proc_cpt_table,
850 },
851
852 {
853 .procname = "upcall",
854 .data = lnet_upcall,
855 .maxlen = sizeof(lnet_upcall),
856 .mode = 0644,
857 .proc_handler = &proc_dostring,
858 },
859 {
860 .procname = "debug_log_upcall",
861 .data = lnet_debug_log_upcall,
862 .maxlen = sizeof(lnet_debug_log_upcall),
863 .mode = 0644,
864 .proc_handler = &proc_dostring,
865 },
866 {
867 .procname = "lnet_memused",
868 .data = (int *)&libcfs_kmemory.counter,
869 .maxlen = sizeof(int),
870 .mode = 0444,
871 .proc_handler = &proc_dointvec,
872 },
873 {
874 .procname = "catastrophe",
875 .data = &libcfs_catastrophe,
876 .maxlen = sizeof(int),
877 .mode = 0444,
878 .proc_handler = &proc_dointvec,
879 },
880 {
881 .procname = "panic_on_lbug",
882 .data = &libcfs_panic_on_lbug,
883 .maxlen = sizeof(int),
884 .mode = 0644,
885 .proc_handler = &proc_dointvec,
886 },
887 {
888 .procname = "dump_kernel",
889 .maxlen = 256,
890 .mode = 0200,
891 .proc_handler = &proc_dump_kernel,
892 },
893 {
894 .procname = "daemon_file",
895 .mode = 0644,
896 .maxlen = 256,
897 .proc_handler = &proc_daemon_file,
898 },
899 {
900 .procname = "debug_mb",
901 .mode = 0644,
902 .proc_handler = &proc_debug_mb,
903 },
904 {
905 .procname = "watchdog_ratelimit",
906 .data = &libcfs_watchdog_ratelimit,
907 .maxlen = sizeof(int),
908 .mode = 0644,
909 .proc_handler = &proc_dointvec_minmax,
910 .extra1 = &min_watchdog_ratelimit,
911 .extra2 = &max_watchdog_ratelimit,
912 },
913 {
914 .procname = "force_lbug",
915 .data = NULL,
916 .maxlen = 0,
917 .mode = 0200,
918 .proc_handler = &libcfs_force_lbug
919 },
920 {
921 .procname = "fail_loc",
922 .data = &cfs_fail_loc,
923 .maxlen = sizeof(cfs_fail_loc),
924 .mode = 0644,
925 .proc_handler = &proc_fail_loc
926 },
927 {
928 .procname = "fail_val",
929 .data = &cfs_fail_val,
930 .maxlen = sizeof(int),
931 .mode = 0644,
932 .proc_handler = &proc_dointvec
933 },
934 {
935 }
936 };
937
938 static struct ctl_table top_table[] = {
939 {
940 .procname = "lnet",
941 .mode = 0555,
942 .data = NULL,
943 .maxlen = 0,
944 .child = lnet_table,
945 },
946 {
947 }
948 };
949
950 static int insert_proc(void)
951 {
952 if (lnet_table_header == NULL)
953 lnet_table_header = register_sysctl_table(top_table);
954 return 0;
955 }
956
957 static void remove_proc(void)
958 {
959 if (lnet_table_header != NULL)
960 unregister_sysctl_table(lnet_table_header);
961
962 lnet_table_header = NULL;
963 }
964
965 MODULE_VERSION("1.0.0");
966
967 module_init(init_libcfs_module);
968 module_exit(exit_libcfs_module);