1 /*****************************************************************************\
2 * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
3 * Copyright (C) 2007 The Regents of the University of California.
4 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
5 * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
8 * This file is part of the SPL, Solaris Porting Layer.
9 * For details, see <http://zfsonlinux.org/>.
11 * The SPL is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
16 * The SPL is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * You should have received a copy of the GNU General Public License along
22 * with the SPL. If not, see <http://www.gnu.org/licenses/>.
23 *****************************************************************************
24 * Solaris Porting Layer (SPL) Proc Implementation.
25 \*****************************************************************************/
27 #include <sys/systeminfo.h>
28 #include <sys/kstat.h>
29 #include <linux/kmod.h>
30 #include <linux/seq_file.h>
31 #include <linux/proc_compat.h>
32 #include <linux/version.h>
33 #include <spl-debug.h>
35 #ifdef SS_DEBUG_SUBSYS
36 #undef SS_DEBUG_SUBSYS
39 #define SS_DEBUG_SUBSYS SS_PROC
41 #if defined(CONSTIFY_PLUGIN) && LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
42 typedef struct ctl_table __no_const spl_ctl_table
;
44 typedef struct ctl_table spl_ctl_table
;
48 static unsigned long table_min
= 0;
49 static unsigned long table_max
= ~0;
52 static struct ctl_table_header
*spl_header
= NULL
;
53 static struct proc_dir_entry
*proc_spl
= NULL
;
55 static struct proc_dir_entry
*proc_spl_kmem
= NULL
;
56 static struct proc_dir_entry
*proc_spl_kmem_slab
= NULL
;
57 #endif /* DEBUG_KMEM */
58 struct proc_dir_entry
*proc_spl_kstat
= NULL
;
61 proc_copyin_string(char *kbuffer
, int kbuffer_size
,
62 const char *ubuffer
, int ubuffer_size
)
66 if (ubuffer_size
> kbuffer_size
)
69 if (copy_from_user((void *)kbuffer
, (void *)ubuffer
, ubuffer_size
))
72 /* strip trailing whitespace */
73 size
= strnlen(kbuffer
, ubuffer_size
);
75 if (!isspace(kbuffer
[size
]))
82 /* no space to terminate */
83 if (size
== kbuffer_size
)
86 kbuffer
[size
+ 1] = 0;
91 proc_copyout_string(char *ubuffer
, int ubuffer_size
,
92 const char *kbuffer
, char *append
)
94 /* NB if 'append' != NULL, it's a single character to append to the
95 * copied out string - usually "\n", for /proc entries and
96 * (i.e. a terminating zero byte) for sysctl entries
98 int size
= MIN(strlen(kbuffer
), ubuffer_size
);
100 if (copy_to_user(ubuffer
, kbuffer
, size
))
103 if (append
!= NULL
&& size
< ubuffer_size
) {
104 if (copy_to_user(ubuffer
+ size
, append
, 1))
114 SPL_PROC_HANDLER(proc_dobitmasks
)
116 unsigned long *mask
= table
->data
;
117 int is_subsys
= (mask
== &spl_debug_subsys
) ? 1 : 0;
118 int is_printk
= (mask
== &spl_debug_printk
) ? 1 : 0;
123 str
= kmem_alloc(size
, KM_SLEEP
);
128 rc
= proc_copyin_string(str
, size
, buffer
, *lenp
);
132 rc
= spl_debug_str2mask(mask
, str
, is_subsys
);
133 /* Always print BUG/ASSERT to console, so keep this mask */
139 rc
= spl_debug_mask2str(str
, size
, *mask
, is_subsys
);
143 rc
= proc_copyout_string(buffer
, *lenp
,
151 kmem_free(str
, size
);
155 SPL_PROC_HANDLER(proc_debug_mb
)
162 rc
= proc_copyin_string(str
, sizeof(str
), buffer
, *lenp
);
166 rc
= spl_debug_set_mb(simple_strtoul(str
, NULL
, 0));
169 len
= snprintf(str
, sizeof(str
), "%d", spl_debug_get_mb());
173 rc
= proc_copyout_string(buffer
,*lenp
,str
+*ppos
,"\n");
184 SPL_PROC_HANDLER(proc_dump_kernel
)
189 spl_debug_dumplog(0);
198 SPL_PROC_HANDLER(proc_force_bug
)
203 PANIC("Crashing due to forced panic\n");
210 SPL_PROC_HANDLER(proc_console_max_delay_cs
)
212 int rc
, max_delay_cs
;
213 spl_ctl_table dummy
= *table
;
217 dummy
.data
= &max_delay_cs
;
218 dummy
.proc_handler
= &proc_dointvec
;
222 rc
= spl_proc_dointvec(&dummy
,write
,filp
,buffer
,lenp
,ppos
);
226 if (max_delay_cs
<= 0)
229 d
= (max_delay_cs
* HZ
) / 100;
230 if (d
== 0 || d
< spl_console_min_delay
)
233 spl_console_max_delay
= d
;
235 max_delay_cs
= (spl_console_max_delay
* 100) / HZ
;
236 rc
= spl_proc_dointvec(&dummy
,write
,filp
,buffer
,lenp
,ppos
);
242 SPL_PROC_HANDLER(proc_console_min_delay_cs
)
244 int rc
, min_delay_cs
;
245 spl_ctl_table dummy
= *table
;
249 dummy
.data
= &min_delay_cs
;
250 dummy
.proc_handler
= &proc_dointvec
;
254 rc
= spl_proc_dointvec(&dummy
,write
,filp
,buffer
,lenp
,ppos
);
258 if (min_delay_cs
<= 0)
261 d
= (min_delay_cs
* HZ
) / 100;
262 if (d
== 0 || d
> spl_console_max_delay
)
265 spl_console_min_delay
= d
;
267 min_delay_cs
= (spl_console_min_delay
* 100) / HZ
;
268 rc
= spl_proc_dointvec(&dummy
,write
,filp
,buffer
,lenp
,ppos
);
274 SPL_PROC_HANDLER(proc_console_backoff
)
277 spl_ctl_table dummy
= *table
;
280 dummy
.data
= &backoff
;
281 dummy
.proc_handler
= &proc_dointvec
;
285 rc
= spl_proc_dointvec(&dummy
,write
,filp
,buffer
,lenp
,ppos
);
292 spl_console_backoff
= backoff
;
294 backoff
= spl_console_backoff
;
295 rc
= spl_proc_dointvec(&dummy
,write
,filp
,buffer
,lenp
,ppos
);
300 #endif /* DEBUG_LOG */
303 SPL_PROC_HANDLER(proc_domemused
)
306 unsigned long min
= 0, max
= ~0, val
;
307 spl_ctl_table dummy
= *table
;
311 dummy
.proc_handler
= &proc_dointvec
;
318 # ifdef HAVE_ATOMIC64_T
319 val
= atomic64_read((atomic64_t
*)table
->data
);
321 val
= atomic_read((atomic_t
*)table
->data
);
322 # endif /* HAVE_ATOMIC64_T */
323 rc
= spl_proc_doulongvec_minmax(&dummy
, write
, filp
,
330 SPL_PROC_HANDLER(proc_doslab
)
333 unsigned long min
= 0, max
= ~0, val
= 0, mask
;
334 spl_ctl_table dummy
= *table
;
335 spl_kmem_cache_t
*skc
;
339 dummy
.proc_handler
= &proc_dointvec
;
346 down_read(&spl_kmem_cache_sem
);
347 mask
= (unsigned long)table
->data
;
349 list_for_each_entry(skc
, &spl_kmem_cache_list
, skc_list
) {
351 /* Only use slabs of the correct kmem/vmem type */
352 if (!(skc
->skc_flags
& mask
))
355 /* Sum the specified field for selected slabs */
356 switch (mask
& (KMC_TOTAL
| KMC_ALLOC
| KMC_MAX
)) {
358 val
+= skc
->skc_slab_size
* skc
->skc_slab_total
;
361 val
+= skc
->skc_obj_size
* skc
->skc_obj_alloc
;
364 val
+= skc
->skc_obj_size
* skc
->skc_obj_max
;
369 up_read(&spl_kmem_cache_sem
);
370 rc
= spl_proc_doulongvec_minmax(&dummy
, write
, filp
,
376 #endif /* DEBUG_KMEM */
378 SPL_PROC_HANDLER(proc_dohostid
)
385 /* We can't use spl_proc_doulongvec_minmax() in the write
386 * case here because hostid while a hex value has no
387 * leading 0x which confuses the helper function. */
388 rc
= proc_copyin_string(str
, sizeof(str
), buffer
, *lenp
);
392 spl_hostid
= simple_strtoul(str
, &end
, 16);
397 len
= snprintf(str
, sizeof(str
), "%lx", spl_hostid
);
401 rc
= proc_copyout_string(buffer
,*lenp
,str
+*ppos
,"\n");
412 #ifndef HAVE_KALLSYMS_LOOKUP_NAME
413 SPL_PROC_HANDLER(proc_dokallsyms_lookup_name
)
420 /* This may only be set once at module load time */
421 if (spl_kallsyms_lookup_name_fn
!= SYMBOL_POISON
)
424 /* We can't use spl_proc_doulongvec_minmax() in the write
425 * case here because the address while a hex value has no
426 * leading 0x which confuses the helper function. */
427 rc
= proc_copyin_string(str
, sizeof(str
), buffer
, *lenp
);
431 spl_kallsyms_lookup_name_fn
=
432 (kallsyms_lookup_name_t
)simple_strtoul(str
, &end
, 16);
433 wake_up(&spl_kallsyms_lookup_name_waitq
);
440 len
= snprintf(str
, sizeof(str
), "%lx",
441 (unsigned long)spl_kallsyms_lookup_name_fn
);
445 rc
= proc_copyout_string(buffer
,*lenp
,str
+*ppos
,"\n");
455 #endif /* HAVE_KALLSYMS_LOOKUP_NAME */
457 SPL_PROC_HANDLER(proc_doavailrmem
)
466 len
= snprintf(str
, sizeof(str
), "%lu",
467 (unsigned long)availrmem
);
471 rc
= proc_copyout_string(buffer
,*lenp
,str
+*ppos
,"\n");
482 SPL_PROC_HANDLER(proc_dofreemem
)
491 len
= snprintf(str
, sizeof(str
), "%lu", (unsigned long)freemem
);
495 rc
= proc_copyout_string(buffer
,*lenp
,str
+*ppos
,"\n");
508 slab_seq_show_headers(struct seq_file
*f
)
511 "--------------------- cache ----------"
512 "--------------------------------------------- "
515 "--- emergency ---\n");
518 " flags size alloc slabsize objsize "
521 "dlock alloc max\n");
525 slab_seq_show(struct seq_file
*f
, void *p
)
527 spl_kmem_cache_t
*skc
= p
;
529 ASSERT(skc
->skc_magic
== SKC_MAGIC
);
532 * Backed by Linux slab see /proc/slabinfo.
534 if (skc
->skc_flags
& KMC_SLAB
)
537 spin_lock(&skc
->skc_lock
);
538 seq_printf(f
, "%-36s ", skc
->skc_name
);
539 seq_printf(f
, "0x%05lx %9lu %9lu %8u %8u "
540 "%5lu %5lu %5lu %5lu %5lu %5lu %5lu %5lu %5lu\n",
541 (long unsigned)skc
->skc_flags
,
542 (long unsigned)(skc
->skc_slab_size
* skc
->skc_slab_total
),
543 (long unsigned)(skc
->skc_obj_size
* skc
->skc_obj_alloc
),
544 (unsigned)skc
->skc_slab_size
,
545 (unsigned)skc
->skc_obj_size
,
546 (long unsigned)skc
->skc_slab_total
,
547 (long unsigned)skc
->skc_slab_alloc
,
548 (long unsigned)skc
->skc_slab_max
,
549 (long unsigned)skc
->skc_obj_total
,
550 (long unsigned)skc
->skc_obj_alloc
,
551 (long unsigned)skc
->skc_obj_max
,
552 (long unsigned)skc
->skc_obj_deadlock
,
553 (long unsigned)skc
->skc_obj_emergency
,
554 (long unsigned)skc
->skc_obj_emergency_max
);
556 spin_unlock(&skc
->skc_lock
);
562 slab_seq_start(struct seq_file
*f
, loff_t
*pos
)
568 down_read(&spl_kmem_cache_sem
);
570 slab_seq_show_headers(f
);
572 p
= spl_kmem_cache_list
.next
;
575 if (p
== &spl_kmem_cache_list
)
579 SRETURN(list_entry(p
, spl_kmem_cache_t
, skc_list
));
583 slab_seq_next(struct seq_file
*f
, void *p
, loff_t
*pos
)
585 spl_kmem_cache_t
*skc
= p
;
589 SRETURN((skc
->skc_list
.next
== &spl_kmem_cache_list
) ?
590 NULL
: list_entry(skc
->skc_list
.next
,spl_kmem_cache_t
,skc_list
));
594 slab_seq_stop(struct seq_file
*f
, void *v
)
596 up_read(&spl_kmem_cache_sem
);
599 static struct seq_operations slab_seq_ops
= {
600 .show
= slab_seq_show
,
601 .start
= slab_seq_start
,
602 .next
= slab_seq_next
,
603 .stop
= slab_seq_stop
,
607 proc_slab_open(struct inode
*inode
, struct file
*filp
)
609 return seq_open(filp
, &slab_seq_ops
);
612 static struct file_operations proc_slab_operations
= {
613 .open
= proc_slab_open
,
616 .release
= seq_release
,
618 #endif /* DEBUG_KMEM */
621 static struct ctl_table spl_debug_table
[] = {
623 .procname
= "subsystem",
624 .data
= &spl_debug_subsys
,
625 .maxlen
= sizeof(unsigned long),
627 .proc_handler
= &proc_dobitmasks
631 .data
= &spl_debug_mask
,
632 .maxlen
= sizeof(unsigned long),
634 .proc_handler
= &proc_dobitmasks
637 .procname
= "printk",
638 .data
= &spl_debug_printk
,
639 .maxlen
= sizeof(unsigned long),
641 .proc_handler
= &proc_dobitmasks
646 .proc_handler
= &proc_debug_mb
,
649 .procname
= "binary",
650 .data
= &spl_debug_binary
,
651 .maxlen
= sizeof(int),
653 .proc_handler
= &proc_dointvec
,
656 .procname
= "catastrophe",
657 .data
= &spl_debug_catastrophe
,
658 .maxlen
= sizeof(int),
660 .proc_handler
= &proc_dointvec
,
663 .procname
= "panic_on_bug",
664 .data
= &spl_debug_panic_on_bug
,
665 .maxlen
= sizeof(int),
667 .proc_handler
= &proc_dointvec
671 .data
= spl_debug_file_path
,
672 .maxlen
= sizeof(spl_debug_file_path
),
674 .proc_handler
= &proc_dostring
,
679 .proc_handler
= &proc_dump_kernel
,
682 .procname
= "force_bug",
684 .proc_handler
= &proc_force_bug
,
687 .procname
= "console_ratelimit",
688 .data
= &spl_console_ratelimit
,
689 .maxlen
= sizeof(int),
691 .proc_handler
= &proc_dointvec
,
694 .procname
= "console_max_delay_centisecs",
695 .maxlen
= sizeof(int),
697 .proc_handler
= &proc_console_max_delay_cs
,
700 .procname
= "console_min_delay_centisecs",
701 .maxlen
= sizeof(int),
703 .proc_handler
= &proc_console_min_delay_cs
,
706 .procname
= "console_backoff",
707 .maxlen
= sizeof(int),
709 .proc_handler
= &proc_console_backoff
,
712 .procname
= "stack_max",
713 .data
= &spl_debug_stack
,
714 .maxlen
= sizeof(int),
716 .proc_handler
= &proc_dointvec
,
720 #endif /* DEBUG_LOG */
722 static struct ctl_table spl_vm_table
[] = {
724 .procname
= "minfree",
726 .maxlen
= sizeof(int),
728 .proc_handler
= &proc_dointvec
,
731 .procname
= "desfree",
733 .maxlen
= sizeof(int),
735 .proc_handler
= &proc_dointvec
,
738 .procname
= "lotsfree",
740 .maxlen
= sizeof(int),
742 .proc_handler
= &proc_dointvec
,
745 .procname
= "needfree",
747 .maxlen
= sizeof(int),
749 .proc_handler
= &proc_dointvec
,
752 .procname
= "swapfs_minfree",
753 .data
= &swapfs_minfree
,
754 .maxlen
= sizeof(int),
756 .proc_handler
= &proc_dointvec
,
759 .procname
= "swapfs_reserve",
760 .data
= &swapfs_reserve
,
761 .maxlen
= sizeof(int),
763 .proc_handler
= &proc_dointvec
,
766 .procname
= "availrmem",
768 .proc_handler
= &proc_doavailrmem
,
771 .procname
= "freemem",
773 .maxlen
= sizeof(int),
775 .proc_handler
= &proc_dofreemem
,
778 .procname
= "physmem",
780 .maxlen
= sizeof(int),
782 .proc_handler
= &proc_dointvec
,
788 static struct ctl_table spl_kmem_table
[] = {
790 .procname
= "kmem_used",
791 .data
= &kmem_alloc_used
,
792 # ifdef HAVE_ATOMIC64_T
793 .maxlen
= sizeof(atomic64_t
),
795 .maxlen
= sizeof(atomic_t
),
796 # endif /* HAVE_ATOMIC64_T */
798 .proc_handler
= &proc_domemused
,
801 .procname
= "kmem_max",
802 .data
= &kmem_alloc_max
,
803 .maxlen
= sizeof(unsigned long),
804 .extra1
= &table_min
,
805 .extra2
= &table_max
,
807 .proc_handler
= &proc_doulongvec_minmax
,
810 .procname
= "vmem_used",
811 .data
= &vmem_alloc_used
,
812 # ifdef HAVE_ATOMIC64_T
813 .maxlen
= sizeof(atomic64_t
),
815 .maxlen
= sizeof(atomic_t
),
816 # endif /* HAVE_ATOMIC64_T */
818 .proc_handler
= &proc_domemused
,
821 .procname
= "vmem_max",
822 .data
= &vmem_alloc_max
,
823 .maxlen
= sizeof(unsigned long),
824 .extra1
= &table_min
,
825 .extra2
= &table_max
,
827 .proc_handler
= &proc_doulongvec_minmax
,
830 .procname
= "slab_kmem_total",
831 .data
= (void *)(KMC_KMEM
| KMC_TOTAL
),
832 .maxlen
= sizeof(unsigned long),
833 .extra1
= &table_min
,
834 .extra2
= &table_max
,
836 .proc_handler
= &proc_doslab
,
839 .procname
= "slab_kmem_alloc",
840 .data
= (void *)(KMC_KMEM
| KMC_ALLOC
),
841 .maxlen
= sizeof(unsigned long),
842 .extra1
= &table_min
,
843 .extra2
= &table_max
,
845 .proc_handler
= &proc_doslab
,
848 .procname
= "slab_kmem_max",
849 .data
= (void *)(KMC_KMEM
| KMC_MAX
),
850 .maxlen
= sizeof(unsigned long),
851 .extra1
= &table_min
,
852 .extra2
= &table_max
,
854 .proc_handler
= &proc_doslab
,
857 .procname
= "slab_vmem_total",
858 .data
= (void *)(KMC_VMEM
| KMC_TOTAL
),
859 .maxlen
= sizeof(unsigned long),
860 .extra1
= &table_min
,
861 .extra2
= &table_max
,
863 .proc_handler
= &proc_doslab
,
866 .procname
= "slab_vmem_alloc",
867 .data
= (void *)(KMC_VMEM
| KMC_ALLOC
),
868 .maxlen
= sizeof(unsigned long),
869 .extra1
= &table_min
,
870 .extra2
= &table_max
,
872 .proc_handler
= &proc_doslab
,
875 .procname
= "slab_vmem_max",
876 .data
= (void *)(KMC_VMEM
| KMC_MAX
),
877 .maxlen
= sizeof(unsigned long),
878 .extra1
= &table_min
,
879 .extra2
= &table_max
,
881 .proc_handler
= &proc_doslab
,
885 #endif /* DEBUG_KMEM */
887 static struct ctl_table spl_kstat_table
[] = {
891 static struct ctl_table spl_table
[] = {
892 /* NB No .strategy entries have been provided since
893 * sysctl(8) prefers to go via /proc for portability.
896 .procname
= "version",
898 .maxlen
= sizeof(spl_version
),
900 .proc_handler
= &proc_dostring
,
903 .procname
= "hostid",
905 .maxlen
= sizeof(unsigned long),
907 .proc_handler
= &proc_dohostid
,
909 #ifndef HAVE_KALLSYMS_LOOKUP_NAME
911 .procname
= "kallsyms_lookup_name",
912 .data
= &spl_kallsyms_lookup_name_fn
,
913 .maxlen
= sizeof(unsigned long),
915 .proc_handler
= &proc_dokallsyms_lookup_name
,
922 .child
= spl_debug_table
,
928 .child
= spl_vm_table
,
934 .child
= spl_kmem_table
,
940 .child
= spl_kstat_table
,
945 static struct ctl_table spl_dir
[] = {
954 static struct ctl_table spl_root
[] = {
957 .ctl_name
= CTL_KERN
,
959 .procname
= "kernel",
972 spl_header
= register_sysctl_table(spl_root
);
973 if (spl_header
== NULL
)
976 proc_spl
= proc_mkdir("spl", NULL
);
977 if (proc_spl
== NULL
)
978 SGOTO(out
, rc
= -EUNATCH
);
981 proc_spl_kmem
= proc_mkdir("kmem", proc_spl
);
982 if (proc_spl_kmem
== NULL
)
983 SGOTO(out
, rc
= -EUNATCH
);
985 proc_spl_kmem_slab
= proc_create_data("slab", 0444,
986 proc_spl_kmem
, &proc_slab_operations
, NULL
);
987 if (proc_spl_kmem_slab
== NULL
)
988 SGOTO(out
, rc
= -EUNATCH
);
990 #endif /* DEBUG_KMEM */
992 proc_spl_kstat
= proc_mkdir("kstat", proc_spl
);
993 if (proc_spl_kstat
== NULL
)
994 SGOTO(out
, rc
= -EUNATCH
);
997 remove_proc_entry("kstat", proc_spl
);
999 remove_proc_entry("slab", proc_spl_kmem
);
1000 remove_proc_entry("kmem", proc_spl
);
1002 remove_proc_entry("spl", NULL
);
1003 unregister_sysctl_table(spl_header
);
1014 remove_proc_entry("kstat", proc_spl
);
1016 remove_proc_entry("slab", proc_spl_kmem
);
1017 remove_proc_entry("kmem", proc_spl
);
1019 remove_proc_entry("spl", NULL
);
1021 ASSERT(spl_header
!= NULL
);
1022 unregister_sysctl_table(spl_header
);