2 * This file is part of the SPL: Solaris Porting Layer.
4 * Copyright (c) 2008 Lawrence Livermore National Security, LLC.
5 * Produced at Lawrence Livermore National Laboratory
7 * Brian Behlendorf <behlendorf1@llnl.gov>,
8 * Herb Wartens <wartens2@llnl.gov>,
9 * Jim Garlick <garlick@llnl.gov>
12 * This is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #ifdef DEBUG_SUBSYSTEM
30 #undef DEBUG_SUBSYSTEM
33 #define DEBUG_SUBSYSTEM S_PROC
36 static unsigned long table_min
= 0;
37 static unsigned long table_max
= ~0;
41 static struct ctl_table_header
*spl_header
= NULL
;
42 static struct proc_dir_entry
*proc_sys
= NULL
;
43 static struct proc_dir_entry
*proc_sys_spl
= NULL
;
45 static struct proc_dir_entry
*proc_sys_spl_mutex
= NULL
;
46 static struct proc_dir_entry
*proc_sys_spl_mutex_stats
= NULL
;
49 static struct proc_dir_entry
*proc_sys_spl_kmem
= NULL
;
52 struct proc_dir_entry
*proc_sys_spl_kstat
= NULL
;
57 #define CTL_SPL_DEBUG 0x88
58 #define CTL_SPL_MUTEX 0x89
59 #define CTL_SPL_KMEM 0x90
60 #define CTL_SPL_KSTAT 0x91
63 CTL_VERSION
= 1, /* Version */
64 CTL_HOSTID
, /* Host id reported by /usr/bin/hostid */
65 CTL_HW_SERIAL
, /* Hardware serial number from hostid */
67 CTL_DEBUG_SUBSYS
, /* Debug subsystem */
68 CTL_DEBUG_MASK
, /* Debug mask */
69 CTL_DEBUG_PRINTK
, /* Force all messages to console */
70 CTL_DEBUG_MB
, /* Debug buffer size */
71 CTL_DEBUG_BINARY
, /* Include binary data in buffer */
72 CTL_DEBUG_CATASTROPHE
, /* Set if we have BUG'd or panic'd */
73 CTL_DEBUG_PANIC_ON_BUG
, /* Set if we should panic on BUG */
74 CTL_DEBUG_PATH
, /* Dump log location */
75 CTL_DEBUG_DUMP
, /* Dump debug buffer to file */
76 CTL_DEBUG_FORCE_BUG
, /* Hook to force a BUG */
77 CTL_DEBUG_STACK_SIZE
, /* Max observed stack size */
79 CTL_CONSOLE_RATELIMIT
, /* Ratelimit console messages */
80 CTL_CONSOLE_MAX_DELAY_CS
, /* Max delay at which we skip messages */
81 CTL_CONSOLE_MIN_DELAY_CS
, /* Init delay at which we skip messages */
82 CTL_CONSOLE_BACKOFF
, /* Delay increase factor */
85 CTL_KMEM_KMEMUSED
, /* Crrently alloc'd kmem bytes */
86 CTL_KMEM_KMEMMAX
, /* Max alloc'd by kmem bytes */
87 CTL_KMEM_VMEMUSED
, /* Currently alloc'd vmem bytes */
88 CTL_KMEM_VMEMMAX
, /* Max alloc'd by vmem bytes */
89 CTL_KMEM_ALLOC_FAILED
, /* Cache allocation failed */
92 CTL_MUTEX_STATS
, /* Global mutex statistics */
93 CTL_MUTEX_STATS_PER
, /* Per mutex statistics */
94 CTL_MUTEX_SPIN_MAX
, /* Maximum mutex spin iterations */
98 proc_copyin_string(char *kbuffer
, int kbuffer_size
,
99 const char *ubuffer
, int ubuffer_size
)
103 if (ubuffer_size
> kbuffer_size
)
106 if (copy_from_user((void *)kbuffer
, (void *)ubuffer
, ubuffer_size
))
109 /* strip trailing whitespace */
110 size
= strnlen(kbuffer
, ubuffer_size
);
112 if (!isspace(kbuffer
[size
]))
119 /* no space to terminate */
120 if (size
== kbuffer_size
)
123 kbuffer
[size
+ 1] = 0;
128 proc_copyout_string(char *ubuffer
, int ubuffer_size
,
129 const char *kbuffer
, char *append
)
131 /* NB if 'append' != NULL, it's a single character to append to the
132 * copied out string - usually "\n", for /proc entries and
133 * (i.e. a terminating zero byte) for sysctl entries
135 int size
= MIN(strlen(kbuffer
), ubuffer_size
);
137 if (copy_to_user(ubuffer
, kbuffer
, size
))
140 if (append
!= NULL
&& size
< ubuffer_size
) {
141 if (copy_to_user(ubuffer
+ size
, append
, 1))
151 proc_dobitmasks(struct ctl_table
*table
, int write
, struct file
*filp
,
152 void __user
*buffer
, size_t *lenp
, loff_t
*ppos
)
154 unsigned long *mask
= table
->data
;
155 int is_subsys
= (mask
== &spl_debug_subsys
) ? 1 : 0;
156 int is_printk
= (mask
== &spl_debug_printk
) ? 1 : 0;
161 str
= kmem_alloc(size
, KM_SLEEP
);
166 rc
= proc_copyin_string(str
, size
, buffer
, *lenp
);
170 rc
= spl_debug_str2mask(mask
, str
, is_subsys
);
171 /* Always print BUG/ASSERT to console, so keep this mask */
177 rc
= spl_debug_mask2str(str
, size
, *mask
, is_subsys
);
181 rc
= proc_copyout_string(buffer
, *lenp
,
189 kmem_free(str
, size
);
194 proc_debug_mb(struct ctl_table
*table
, int write
, struct file
*filp
,
195 void __user
*buffer
, size_t *lenp
, loff_t
*ppos
)
202 rc
= proc_copyin_string(str
, sizeof(str
), buffer
, *lenp
);
206 rc
= spl_debug_set_mb(simple_strtoul(str
, NULL
, 0));
209 len
= snprintf(str
, sizeof(str
), "%d", spl_debug_get_mb());
213 rc
= proc_copyout_string(buffer
, *lenp
, str
+ *ppos
, "\n");
225 proc_dump_kernel(struct ctl_table
*table
, int write
, struct file
*filp
,
226 void __user
*buffer
, size_t *lenp
, loff_t
*ppos
)
231 spl_debug_dumplog(0);
241 proc_force_bug(struct ctl_table
*table
, int write
, struct file
*filp
,
242 void __user
*buffer
, size_t *lenp
, loff_t
*ppos
)
247 CERROR("Crashing due to forced SBUG\n");
258 proc_console_max_delay_cs(struct ctl_table
*table
, int write
, struct file
*filp
,
259 void __user
*buffer
, size_t *lenp
, loff_t
*ppos
)
261 int rc
, max_delay_cs
;
262 struct ctl_table dummy
= *table
;
266 dummy
.data
= &max_delay_cs
;
267 dummy
.proc_handler
= &proc_dointvec
;
271 rc
= proc_dointvec(&dummy
, write
, filp
, buffer
, lenp
, ppos
);
275 if (max_delay_cs
<= 0)
278 d
= (max_delay_cs
* HZ
) / 100;
279 if (d
== 0 || d
< spl_console_min_delay
)
282 spl_console_max_delay
= d
;
284 max_delay_cs
= (spl_console_max_delay
* 100) / HZ
;
285 rc
= proc_dointvec(&dummy
, write
, filp
, buffer
, lenp
, ppos
);
292 proc_console_min_delay_cs(struct ctl_table
*table
, int write
, struct file
*filp
,
293 void __user
*buffer
, size_t *lenp
, loff_t
*ppos
)
295 int rc
, min_delay_cs
;
296 struct ctl_table dummy
= *table
;
300 dummy
.data
= &min_delay_cs
;
301 dummy
.proc_handler
= &proc_dointvec
;
305 rc
= proc_dointvec(&dummy
, write
, filp
, buffer
, lenp
, ppos
);
309 if (min_delay_cs
<= 0)
312 d
= (min_delay_cs
* HZ
) / 100;
313 if (d
== 0 || d
> spl_console_max_delay
)
316 spl_console_min_delay
= d
;
318 min_delay_cs
= (spl_console_min_delay
* 100) / HZ
;
319 rc
= proc_dointvec(&dummy
, write
, filp
, buffer
, lenp
, ppos
);
326 proc_console_backoff(struct ctl_table
*table
, int write
, struct file
*filp
,
327 void __user
*buffer
, size_t *lenp
, loff_t
*ppos
)
330 struct ctl_table dummy
= *table
;
333 dummy
.data
= &backoff
;
334 dummy
.proc_handler
= &proc_dointvec
;
338 rc
= proc_dointvec(&dummy
, write
, filp
, buffer
, lenp
, ppos
);
345 spl_console_backoff
= backoff
;
347 backoff
= spl_console_backoff
;
348 rc
= proc_dointvec(&dummy
, write
, filp
, buffer
, lenp
, ppos
);
356 proc_doatomic64(struct ctl_table
*table
, int write
, struct file
*filp
,
357 void __user
*buffer
, size_t *lenp
, loff_t
*ppos
)
360 unsigned long min
= 0, max
= ~0, val
;
361 struct ctl_table dummy
= *table
;
365 dummy
.proc_handler
= &proc_dointvec
;
372 val
= atomic_read((atomic64_t
*)table
->data
);
373 rc
= proc_doulongvec_minmax(&dummy
, write
, filp
,
379 #endif /* DEBUG_KMEM */
382 proc_dohostid(struct ctl_table
*table
, int write
, struct file
*filp
,
383 void __user
*buffer
, size_t *lenp
, loff_t
*ppos
)
391 /* We can't use proc_doulongvec_minmax() in the write
392 * case hear because hostid while a hex value has no
393 * leading 0x which confuses the helper function. */
394 rc
= proc_copyin_string(str
, sizeof(str
), buffer
, *lenp
);
398 val
= simple_strtol(str
, &end
, 16);
402 spl_hostid
= (long)val
;
403 sprintf(hw_serial
, "%u", (val
>= 0) ? val
: -val
);
406 len
= snprintf(str
, sizeof(str
), "%lx", spl_hostid
);
410 rc
= proc_copyout_string(buffer
, *lenp
, str
+ *ppos
, "\n");
423 mutex_seq_show_headers(struct seq_file
*f
)
425 seq_printf(f
, "%-36s %-4s %-16s\t"
426 "e_tot\te_nh\te_sp\te_sl\tte_tot\tte_nh\n",
427 "name", "type", "owner");
431 mutex_seq_show(struct seq_file
*f
, void *p
)
437 ASSERT(mp
->km_magic
== KM_MAGIC
);
439 switch (mp
->km_type
) {
440 case MUTEX_DEFAULT
: t
= 'D'; break;
441 case MUTEX_SPIN
: t
= 'S'; break;
442 case MUTEX_ADAPTIVE
: t
= 'A'; break;
446 seq_printf(f
, "%-36s %c ", mp
->km_name
, t
);
448 seq_printf(f
, "%p\t", mp
->km_owner
);
450 seq_printf(f
, "%-16s\t", "<not held>");
452 for (i
= 0; i
< MUTEX_STATS_SIZE
; i
++)
453 seq_printf(f
, "%d%c", mp
->km_stats
[i
],
454 (i
+ 1 == MUTEX_STATS_SIZE
) ? '\n' : '\t');
460 mutex_seq_start(struct seq_file
*f
, loff_t
*pos
)
466 spin_lock(&mutex_stats_lock
);
468 mutex_seq_show_headers(f
);
470 p
= mutex_stats_list
.next
;
473 if (p
== &mutex_stats_list
)
477 RETURN(list_entry(p
, kmutex_t
, km_list
));
481 mutex_seq_next(struct seq_file
*f
, void *p
, loff_t
*pos
)
487 RETURN((mp
->km_list
.next
== &mutex_stats_list
) ?
488 NULL
: list_entry(mp
->km_list
.next
, kmutex_t
, km_list
));
492 mutex_seq_stop(struct seq_file
*f
, void *v
)
494 spin_unlock(&mutex_stats_lock
);
497 static struct seq_operations mutex_seq_ops
= {
498 .show
= mutex_seq_show
,
499 .start
= mutex_seq_start
,
500 .next
= mutex_seq_next
,
501 .stop
= mutex_seq_stop
,
505 proc_mutex_open(struct inode
*inode
, struct file
*filp
)
507 return seq_open(filp
, &mutex_seq_ops
);
510 static struct file_operations proc_mutex_operations
= {
511 .open
= proc_mutex_open
,
514 .release
= seq_release
,
516 #endif /* DEBUG_MUTEX */
518 static struct ctl_table spl_debug_table
[] = {
520 .ctl_name
= CTL_DEBUG_SUBSYS
,
521 .procname
= "subsystem",
522 .data
= &spl_debug_subsys
,
523 .maxlen
= sizeof(unsigned long),
525 .proc_handler
= &proc_dobitmasks
528 .ctl_name
= CTL_DEBUG_MASK
,
530 .data
= &spl_debug_mask
,
531 .maxlen
= sizeof(unsigned long),
533 .proc_handler
= &proc_dobitmasks
536 .ctl_name
= CTL_DEBUG_PRINTK
,
537 .procname
= "printk",
538 .data
= &spl_debug_printk
,
539 .maxlen
= sizeof(unsigned long),
541 .proc_handler
= &proc_dobitmasks
544 .ctl_name
= CTL_DEBUG_MB
,
547 .proc_handler
= &proc_debug_mb
,
550 .ctl_name
= CTL_DEBUG_BINARY
,
551 .procname
= "binary",
552 .data
= &spl_debug_binary
,
553 .maxlen
= sizeof(int),
555 .proc_handler
= &proc_dointvec
,
558 .ctl_name
= CTL_DEBUG_CATASTROPHE
,
559 .procname
= "catastrophe",
560 .data
= &spl_debug_catastrophe
,
561 .maxlen
= sizeof(int),
563 .proc_handler
= &proc_dointvec
,
566 .ctl_name
= CTL_DEBUG_PANIC_ON_BUG
,
567 .procname
= "panic_on_bug",
568 .data
= &spl_debug_panic_on_bug
,
569 .maxlen
= sizeof(int),
571 .proc_handler
= &proc_dointvec
574 .ctl_name
= CTL_DEBUG_PATH
,
576 .data
= spl_debug_file_path
,
577 .maxlen
= sizeof(spl_debug_file_path
),
579 .proc_handler
= &proc_dostring
,
582 .ctl_name
= CTL_DEBUG_DUMP
,
585 .proc_handler
= &proc_dump_kernel
,
587 { .ctl_name
= CTL_DEBUG_FORCE_BUG
,
588 .procname
= "force_bug",
590 .proc_handler
= &proc_force_bug
,
593 .ctl_name
= CTL_CONSOLE_RATELIMIT
,
594 .procname
= "console_ratelimit",
595 .data
= &spl_console_ratelimit
,
596 .maxlen
= sizeof(int),
598 .proc_handler
= &proc_dointvec
,
601 .ctl_name
= CTL_CONSOLE_MAX_DELAY_CS
,
602 .procname
= "console_max_delay_centisecs",
603 .maxlen
= sizeof(int),
605 .proc_handler
= &proc_console_max_delay_cs
,
608 .ctl_name
= CTL_CONSOLE_MIN_DELAY_CS
,
609 .procname
= "console_min_delay_centisecs",
610 .maxlen
= sizeof(int),
612 .proc_handler
= &proc_console_min_delay_cs
,
615 .ctl_name
= CTL_CONSOLE_BACKOFF
,
616 .procname
= "console_backoff",
617 .maxlen
= sizeof(int),
619 .proc_handler
= &proc_console_backoff
,
622 .ctl_name
= CTL_DEBUG_STACK_SIZE
,
623 .procname
= "stack_max",
624 .data
= &spl_debug_stack
,
625 .maxlen
= sizeof(int),
627 .proc_handler
= &proc_dointvec
,
633 static struct ctl_table spl_mutex_table
[] = {
635 .ctl_name
= CTL_MUTEX_STATS
,
637 .data
= &mutex_stats
,
638 .maxlen
= sizeof(int) * MUTEX_STATS_SIZE
,
640 .proc_handler
= &proc_dointvec
,
643 .ctl_name
= CTL_MUTEX_SPIN_MAX
,
644 .procname
= "spin_max",
645 .data
= &mutex_spin_max
,
646 .maxlen
= sizeof(int),
648 .proc_handler
= &proc_dointvec
,
652 #endif /* DEBUG_MUTEX */
655 static struct ctl_table spl_kmem_table
[] = {
657 .ctl_name
= CTL_KMEM_KMEMUSED
,
658 .procname
= "kmem_used",
659 .data
= &kmem_alloc_used
,
660 .maxlen
= sizeof(atomic64_t
),
662 .proc_handler
= &proc_doatomic64
,
665 .ctl_name
= CTL_KMEM_KMEMMAX
,
666 .procname
= "kmem_max",
667 .data
= &kmem_alloc_max
,
668 .maxlen
= sizeof(unsigned long),
669 .extra1
= &table_min
,
670 .extra2
= &table_max
,
672 .proc_handler
= &proc_doulongvec_minmax
,
675 .ctl_name
= CTL_KMEM_VMEMUSED
,
676 .procname
= "vmem_used",
677 .data
= &vmem_alloc_used
,
678 .maxlen
= sizeof(atomic64_t
),
680 .proc_handler
= &proc_doatomic64
,
683 .ctl_name
= CTL_KMEM_VMEMMAX
,
684 .procname
= "vmem_max",
685 .data
= &vmem_alloc_max
,
686 .maxlen
= sizeof(unsigned long),
687 .extra1
= &table_min
,
688 .extra2
= &table_max
,
690 .proc_handler
= &proc_doulongvec_minmax
,
693 .ctl_name
= CTL_KMEM_ALLOC_FAILED
,
694 .procname
= "kmem_alloc_failed",
695 .data
= &kmem_cache_alloc_failed
,
696 .maxlen
= sizeof(atomic64_t
),
698 .proc_handler
= &proc_doatomic64
,
702 #endif /* DEBUG_KMEM */
705 static struct ctl_table spl_kstat_table
[] = {
708 #endif /* DEBUG_KSTAT */
710 static struct ctl_table spl_table
[] = {
711 /* NB No .strategy entries have been provided since
712 * sysctl(8) prefers to go via /proc for portability.
715 .ctl_name
= CTL_VERSION
,
716 .procname
= "version",
718 .maxlen
= sizeof(spl_version
),
720 .proc_handler
= &proc_dostring
,
723 .ctl_name
= CTL_HOSTID
,
724 .procname
= "hostid",
726 .maxlen
= sizeof(unsigned long),
728 .proc_handler
= &proc_dohostid
,
731 .ctl_name
= CTL_HW_SERIAL
,
732 .procname
= "hw_serial",
734 .maxlen
= sizeof(hw_serial
),
736 .proc_handler
= &proc_dostring
,
739 .ctl_name
= CTL_SPL_DEBUG
,
742 .child
= spl_debug_table
,
746 .ctl_name
= CTL_SPL_MUTEX
,
749 .child
= spl_mutex_table
,
754 .ctl_name
= CTL_SPL_KMEM
,
757 .child
= spl_kmem_table
,
762 .ctl_name
= CTL_SPL_KSTAT
,
765 .child
= spl_kstat_table
,
771 static struct ctl_table spl_dir
[] = {
782 proc_dir_entry_match(int len
, const char *name
, struct proc_dir_entry
*de
)
784 if (de
->namelen
!= len
)
787 return !memcmp(name
, de
->name
, len
);
790 struct proc_dir_entry
*
791 proc_dir_entry_find(struct proc_dir_entry
*root
, const char *str
)
793 struct proc_dir_entry
*de
;
795 for (de
= root
->subdir
; de
; de
= de
->next
)
796 if (proc_dir_entry_match(strlen(str
), str
, de
))
803 proc_dir_entries(struct proc_dir_entry
*root
)
805 struct proc_dir_entry
*de
;
808 for (de
= root
->subdir
; de
; de
= de
->next
)
821 spl_header
= register_sysctl_table(spl_dir
, 0);
822 if (spl_header
== NULL
)
825 proc_sys
= proc_dir_entry_find(&proc_root
, "sys");
826 if (proc_sys
== NULL
)
827 GOTO(out
, rc
= -EUNATCH
);
829 proc_sys_spl
= proc_dir_entry_find(proc_sys
, "spl");
830 if (proc_sys_spl
== NULL
)
831 GOTO(out
, rc
= -EUNATCH
);
834 proc_sys_spl_mutex
= proc_dir_entry_find(proc_sys_spl
, "mutex");
835 if (proc_sys_spl_mutex
== NULL
)
836 GOTO(out
, rc
= -EUNATCH
);
838 proc_sys_spl_mutex_stats
= create_proc_entry("stats_per", 0444,
840 if (proc_sys_spl_mutex_stats
== NULL
)
841 GOTO(out
, rc
= -EUNATCH
);
843 proc_sys_spl_mutex_stats
->proc_fops
= &proc_mutex_operations
;
844 #endif /* DEBUG_MUTEX */
847 proc_sys_spl_kmem
= proc_dir_entry_find(proc_sys_spl
, "kmem");
848 if (proc_sys_spl_kmem
== NULL
)
849 GOTO(out2
, rc
= -EUNATCH
);
850 #endif /* DEBUG_KMEM */
853 proc_sys_spl_kstat
= proc_dir_entry_find(proc_sys_spl
, "kstat");
854 if (proc_sys_spl_kstat
== NULL
)
855 GOTO(out2
, rc
= -EUNATCH
);
856 #endif /* DEBUG_KSTAT */
859 #if defined(DEBUG_KMEM) || defined(DEBUG_KSTAT)
863 remove_proc_entry("stats_per", proc_sys_spl_mutex
);
864 #endif /* DEBUG_MUTEX */
866 unregister_sysctl_table(spl_header
);
867 #endif /* CONFIG_SYSCTL */
877 ASSERT(spl_header
!= NULL
);
879 remove_proc_entry("stats_per", proc_sys_spl_mutex
);
880 #endif /* DEBUG_MUTEX */
881 unregister_sysctl_table(spl_header
);