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/>.
24 * Solaris Porting Layer (SPL) Proc Implementation.
27 #include <sys/systeminfo.h>
28 #include <sys/kstat.h>
30 #include <sys/kmem_cache.h>
32 #include <sys/taskq.h>
34 #include <linux/ctype.h>
35 #include <linux/kmod.h>
36 #include <linux/seq_file.h>
37 #include <linux/uaccess.h>
38 #include <linux/version.h>
40 #if defined(CONSTIFY_PLUGIN) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
41 typedef struct ctl_table __no_const spl_ctl_table;
43 typedef struct ctl_table spl_ctl_table;
46 static unsigned long table_min = 0;
47 static unsigned long table_max = ~0;
49 static struct ctl_table_header *spl_header = NULL;
50 static struct proc_dir_entry *proc_spl = NULL;
51 static struct proc_dir_entry *proc_spl_kmem = NULL;
52 static struct proc_dir_entry *proc_spl_kmem_slab = NULL;
53 static struct proc_dir_entry *proc_spl_taskq_all = NULL;
54 static struct proc_dir_entry *proc_spl_taskq = NULL;
55 struct proc_dir_entry *proc_spl_kstat = NULL;
58 proc_copyin_string(char *kbuffer, int kbuffer_size, const char *ubuffer,
63 if (ubuffer_size > kbuffer_size)
66 if (copy_from_user((void *)kbuffer, (void *)ubuffer, ubuffer_size))
69 /* strip trailing whitespace */
70 size = strnlen(kbuffer, ubuffer_size);
72 if (!isspace(kbuffer[size]))
79 /* no space to terminate */
80 if (size == kbuffer_size)
83 kbuffer[size + 1] = 0;
88 proc_copyout_string(char *ubuffer, int ubuffer_size, const char *kbuffer,
92 * NB if 'append' != NULL, it's a single character to append to the
93 * copied out string - usually "\n", for /proc entries and
94 * (i.e. a terminating zero byte) for sysctl entries
96 int size = MIN(strlen(kbuffer), ubuffer_size);
98 if (copy_to_user(ubuffer, kbuffer, size))
101 if (append != NULL && size < ubuffer_size) {
102 if (copy_to_user(ubuffer + size, append, 1))
113 proc_domemused(struct ctl_table *table, int write,
114 void __user *buffer, size_t *lenp, loff_t *ppos)
117 unsigned long min = 0, max = ~0, val;
118 spl_ctl_table dummy = *table;
121 dummy.proc_handler = &proc_dointvec;
128 #ifdef HAVE_ATOMIC64_T
129 val = atomic64_read((atomic64_t *)table->data);
131 val = atomic_read((atomic_t *)table->data);
132 #endif /* HAVE_ATOMIC64_T */
133 rc = proc_doulongvec_minmax(&dummy, write, buffer, lenp, ppos);
138 #endif /* DEBUG_KMEM */
141 proc_doslab(struct ctl_table *table, int write,
142 void __user *buffer, size_t *lenp, loff_t *ppos)
145 unsigned long min = 0, max = ~0, val = 0, mask;
146 spl_ctl_table dummy = *table;
147 spl_kmem_cache_t *skc = NULL;
150 dummy.proc_handler = &proc_dointvec;
157 down_read(&spl_kmem_cache_sem);
158 mask = (unsigned long)table->data;
160 list_for_each_entry(skc, &spl_kmem_cache_list, skc_list) {
162 /* Only use slabs of the correct kmem/vmem type */
163 if (!(skc->skc_flags & mask))
166 /* Sum the specified field for selected slabs */
167 switch (mask & (KMC_TOTAL | KMC_ALLOC | KMC_MAX)) {
169 val += skc->skc_slab_size * skc->skc_slab_total;
172 val += skc->skc_obj_size * skc->skc_obj_alloc;
175 val += skc->skc_obj_size * skc->skc_obj_max;
180 up_read(&spl_kmem_cache_sem);
181 rc = proc_doulongvec_minmax(&dummy, write, buffer, lenp, ppos);
188 proc_dohostid(struct ctl_table *table, int write,
189 void __user *buffer, size_t *lenp, loff_t *ppos)
196 * We can't use proc_doulongvec_minmax() in the write
197 * case here because hostid while a hex value has no
198 * leading 0x which confuses the helper function.
200 rc = proc_copyin_string(str, sizeof (str), buffer, *lenp);
204 spl_hostid = simple_strtoul(str, &end, 16);
209 len = snprintf(str, sizeof (str), "%lx",
210 (unsigned long) zone_get_hostid(NULL));
214 rc = proc_copyout_string(buffer,
215 *lenp, str + *ppos, "\n");
227 taskq_seq_show_headers(struct seq_file *f)
229 seq_printf(f, "%-25s %5s %5s %5s %5s %5s %5s %12s %5s %10s\n",
230 "taskq", "act", "nthr", "spwn", "maxt", "pri",
231 "mina", "maxa", "cura", "flags");
234 /* indices into the lheads array below */
237 #define LHEAD_DELAY 2
239 #define LHEAD_ACTIVE 4
243 static unsigned int spl_max_show_tasks = 512;
244 module_param(spl_max_show_tasks, uint, 0644);
245 MODULE_PARM_DESC(spl_max_show_tasks, "Max number of tasks shown in taskq proc");
249 taskq_seq_show_impl(struct seq_file *f, void *p, boolean_t allflag)
252 taskq_thread_t *tqt = NULL;
253 spl_wait_queue_entry_t *wq;
254 struct task_struct *tsk;
257 struct list_head *lheads[LHEAD_SIZE], *lh;
258 static char *list_names[LHEAD_SIZE] =
259 {"pend", "prio", "delay", "wait", "active" };
260 int i, j, have_lheads = 0;
261 unsigned long wflags, flags;
263 spin_lock_irqsave_nested(&tq->tq_lock, flags, tq->tq_lock_class);
264 spin_lock_irqsave(&tq->tq_wait_waitq.lock, wflags);
266 /* get the various lists and check whether they're empty */
267 lheads[LHEAD_PEND] = &tq->tq_pend_list;
268 lheads[LHEAD_PRIO] = &tq->tq_prio_list;
269 lheads[LHEAD_DELAY] = &tq->tq_delay_list;
270 #ifdef HAVE_WAIT_QUEUE_HEAD_ENTRY
271 lheads[LHEAD_WAIT] = &tq->tq_wait_waitq.head;
273 lheads[LHEAD_WAIT] = &tq->tq_wait_waitq.task_list;
275 lheads[LHEAD_ACTIVE] = &tq->tq_active_list;
277 for (i = 0; i < LHEAD_SIZE; ++i) {
278 if (list_empty(lheads[i]))
284 /* early return in non-"all" mode if lists are all empty */
285 if (!allflag && !have_lheads) {
286 spin_unlock_irqrestore(&tq->tq_wait_waitq.lock, wflags);
287 spin_unlock_irqrestore(&tq->tq_lock, flags);
291 /* unlock the waitq quickly */
292 if (!lheads[LHEAD_WAIT])
293 spin_unlock_irqrestore(&tq->tq_wait_waitq.lock, wflags);
295 /* show the base taskq contents */
296 snprintf(name, sizeof (name), "%s/%d", tq->tq_name, tq->tq_instance);
297 seq_printf(f, "%-25s ", name);
298 seq_printf(f, "%5d %5d %5d %5d %5d %5d %12d %5d %10x\n",
299 tq->tq_nactive, tq->tq_nthreads, tq->tq_nspawn,
300 tq->tq_maxthreads, tq->tq_pri, tq->tq_minalloc, tq->tq_maxalloc,
301 tq->tq_nalloc, tq->tq_flags);
303 /* show the active list */
304 if (lheads[LHEAD_ACTIVE]) {
306 list_for_each_entry(tqt, &tq->tq_active_list, tqt_active_list) {
308 seq_printf(f, "\t%s:",
309 list_names[LHEAD_ACTIVE]);
311 seq_printf(f, "\n\t ");
314 seq_printf(f, " [%d]%pf(%ps)",
315 tqt->tqt_thread->pid,
316 tqt->tqt_task->tqent_func,
317 tqt->tqt_task->tqent_arg);
323 for (i = LHEAD_PEND; i <= LHEAD_WAIT; ++i)
326 list_for_each(lh, lheads[i]) {
327 if (spl_max_show_tasks != 0 &&
328 j >= spl_max_show_tasks) {
329 seq_printf(f, "\n\t(truncated)");
332 /* show the wait waitq list */
333 if (i == LHEAD_WAIT) {
334 #ifdef HAVE_WAIT_QUEUE_HEAD_ENTRY
336 spl_wait_queue_entry_t, entry);
339 spl_wait_queue_entry_t, task_list);
342 seq_printf(f, "\t%s:",
345 seq_printf(f, "\n\t ");
348 seq_printf(f, " %d", tsk->pid);
349 /* pend, prio and delay lists */
351 tqe = list_entry(lh, taskq_ent_t,
354 seq_printf(f, "\t%s:",
357 seq_printf(f, "\n\t ");
359 seq_printf(f, " %pf(%ps)",
367 if (lheads[LHEAD_WAIT])
368 spin_unlock_irqrestore(&tq->tq_wait_waitq.lock, wflags);
369 spin_unlock_irqrestore(&tq->tq_lock, flags);
375 taskq_all_seq_show(struct seq_file *f, void *p)
377 return (taskq_seq_show_impl(f, p, B_TRUE));
381 taskq_seq_show(struct seq_file *f, void *p)
383 return (taskq_seq_show_impl(f, p, B_FALSE));
387 taskq_seq_start(struct seq_file *f, loff_t *pos)
392 down_read(&tq_list_sem);
394 taskq_seq_show_headers(f);
403 return (list_entry(p, taskq_t, tq_taskqs));
407 taskq_seq_next(struct seq_file *f, void *p, loff_t *pos)
412 return ((tq->tq_taskqs.next == &tq_list) ?
413 NULL : list_entry(tq->tq_taskqs.next, taskq_t, tq_taskqs));
417 slab_seq_show_headers(struct seq_file *f)
420 "--------------------- cache ----------"
421 "--------------------------------------------- "
424 "--- emergency ---\n");
427 " flags size alloc slabsize objsize "
430 "dlock alloc max\n");
434 slab_seq_show(struct seq_file *f, void *p)
436 spl_kmem_cache_t *skc = p;
438 ASSERT(skc->skc_magic == SKC_MAGIC);
440 if (skc->skc_flags & KMC_SLAB) {
442 * This cache is backed by a generic Linux kmem cache which
443 * has its own accounting. For these caches we only track
444 * the number of active allocated objects that exist within
445 * the underlying Linux slabs. For the overall statistics of
446 * the underlying Linux cache please refer to /proc/slabinfo.
448 spin_lock(&skc->skc_lock);
449 uint64_t objs_allocated =
450 percpu_counter_sum(&skc->skc_linux_alloc);
451 seq_printf(f, "%-36s ", skc->skc_name);
452 seq_printf(f, "0x%05lx %9s %9lu %8s %8u "
453 "%5s %5s %5s %5s %5lu %5s %5s %5s %5s\n",
454 (long unsigned)skc->skc_flags,
456 (long unsigned)(skc->skc_obj_size * objs_allocated),
458 (unsigned)skc->skc_obj_size,
460 (long unsigned)objs_allocated,
462 spin_unlock(&skc->skc_lock);
466 spin_lock(&skc->skc_lock);
467 seq_printf(f, "%-36s ", skc->skc_name);
468 seq_printf(f, "0x%05lx %9lu %9lu %8u %8u "
469 "%5lu %5lu %5lu %5lu %5lu %5lu %5lu %5lu %5lu\n",
470 (long unsigned)skc->skc_flags,
471 (long unsigned)(skc->skc_slab_size * skc->skc_slab_total),
472 (long unsigned)(skc->skc_obj_size * skc->skc_obj_alloc),
473 (unsigned)skc->skc_slab_size,
474 (unsigned)skc->skc_obj_size,
475 (long unsigned)skc->skc_slab_total,
476 (long unsigned)skc->skc_slab_alloc,
477 (long unsigned)skc->skc_slab_max,
478 (long unsigned)skc->skc_obj_total,
479 (long unsigned)skc->skc_obj_alloc,
480 (long unsigned)skc->skc_obj_max,
481 (long unsigned)skc->skc_obj_deadlock,
482 (long unsigned)skc->skc_obj_emergency,
483 (long unsigned)skc->skc_obj_emergency_max);
484 spin_unlock(&skc->skc_lock);
489 slab_seq_start(struct seq_file *f, loff_t *pos)
494 down_read(&spl_kmem_cache_sem);
496 slab_seq_show_headers(f);
498 p = spl_kmem_cache_list.next;
501 if (p == &spl_kmem_cache_list)
505 return (list_entry(p, spl_kmem_cache_t, skc_list));
509 slab_seq_next(struct seq_file *f, void *p, loff_t *pos)
511 spl_kmem_cache_t *skc = p;
514 return ((skc->skc_list.next == &spl_kmem_cache_list) ?
515 NULL : list_entry(skc->skc_list.next, spl_kmem_cache_t, skc_list));
519 slab_seq_stop(struct seq_file *f, void *v)
521 up_read(&spl_kmem_cache_sem);
524 static struct seq_operations slab_seq_ops = {
525 .show = slab_seq_show,
526 .start = slab_seq_start,
527 .next = slab_seq_next,
528 .stop = slab_seq_stop,
532 proc_slab_open(struct inode *inode, struct file *filp)
534 return (seq_open(filp, &slab_seq_ops));
537 static const kstat_proc_op_t proc_slab_operations = {
538 #ifdef HAVE_PROC_OPS_STRUCT
539 .proc_open = proc_slab_open,
540 .proc_read = seq_read,
541 .proc_lseek = seq_lseek,
542 .proc_release = seq_release,
544 .open = proc_slab_open,
547 .release = seq_release,
552 taskq_seq_stop(struct seq_file *f, void *v)
554 up_read(&tq_list_sem);
557 static struct seq_operations taskq_all_seq_ops = {
558 .show = taskq_all_seq_show,
559 .start = taskq_seq_start,
560 .next = taskq_seq_next,
561 .stop = taskq_seq_stop,
564 static struct seq_operations taskq_seq_ops = {
565 .show = taskq_seq_show,
566 .start = taskq_seq_start,
567 .next = taskq_seq_next,
568 .stop = taskq_seq_stop,
572 proc_taskq_all_open(struct inode *inode, struct file *filp)
574 return (seq_open(filp, &taskq_all_seq_ops));
578 proc_taskq_open(struct inode *inode, struct file *filp)
580 return (seq_open(filp, &taskq_seq_ops));
583 static const kstat_proc_op_t proc_taskq_all_operations = {
584 #ifdef HAVE_PROC_OPS_STRUCT
585 .proc_open = proc_taskq_all_open,
586 .proc_read = seq_read,
587 .proc_lseek = seq_lseek,
588 .proc_release = seq_release,
590 .open = proc_taskq_all_open,
593 .release = seq_release,
597 static const kstat_proc_op_t proc_taskq_operations = {
598 #ifdef HAVE_PROC_OPS_STRUCT
599 .proc_open = proc_taskq_open,
600 .proc_read = seq_read,
601 .proc_lseek = seq_lseek,
602 .proc_release = seq_release,
604 .open = proc_taskq_open,
607 .release = seq_release,
611 static struct ctl_table spl_kmem_table[] = {
614 .procname = "kmem_used",
615 .data = &kmem_alloc_used,
616 #ifdef HAVE_ATOMIC64_T
617 .maxlen = sizeof (atomic64_t),
619 .maxlen = sizeof (atomic_t),
620 #endif /* HAVE_ATOMIC64_T */
622 .proc_handler = &proc_domemused,
625 .procname = "kmem_max",
626 .data = &kmem_alloc_max,
627 .maxlen = sizeof (unsigned long),
628 .extra1 = &table_min,
629 .extra2 = &table_max,
631 .proc_handler = &proc_doulongvec_minmax,
633 #endif /* DEBUG_KMEM */
635 .procname = "slab_kvmem_total",
636 .data = (void *)(KMC_KVMEM | KMC_TOTAL),
637 .maxlen = sizeof (unsigned long),
638 .extra1 = &table_min,
639 .extra2 = &table_max,
641 .proc_handler = &proc_doslab,
644 .procname = "slab_kvmem_alloc",
645 .data = (void *)(KMC_KVMEM | KMC_ALLOC),
646 .maxlen = sizeof (unsigned long),
647 .extra1 = &table_min,
648 .extra2 = &table_max,
650 .proc_handler = &proc_doslab,
653 .procname = "slab_kvmem_max",
654 .data = (void *)(KMC_KVMEM | KMC_MAX),
655 .maxlen = sizeof (unsigned long),
656 .extra1 = &table_min,
657 .extra2 = &table_max,
659 .proc_handler = &proc_doslab,
664 static struct ctl_table spl_kstat_table[] = {
668 static struct ctl_table spl_table[] = {
670 * NB No .strategy entries have been provided since
671 * sysctl(8) prefers to go via /proc for portability.
674 .procname = "gitrev",
676 .maxlen = sizeof (spl_gitrev),
678 .proc_handler = &proc_dostring,
681 .procname = "hostid",
683 .maxlen = sizeof (unsigned long),
685 .proc_handler = &proc_dohostid,
690 .child = spl_kmem_table,
695 .child = spl_kstat_table,
700 static struct ctl_table spl_dir[] = {
709 static struct ctl_table spl_root[] = {
711 .procname = "kernel",
723 spl_header = register_sysctl_table(spl_root);
724 if (spl_header == NULL)
727 proc_spl = proc_mkdir("spl", NULL);
728 if (proc_spl == NULL) {
733 proc_spl_taskq_all = proc_create_data("taskq-all", 0444, proc_spl,
734 &proc_taskq_all_operations, NULL);
735 if (proc_spl_taskq_all == NULL) {
740 proc_spl_taskq = proc_create_data("taskq", 0444, proc_spl,
741 &proc_taskq_operations, NULL);
742 if (proc_spl_taskq == NULL) {
747 proc_spl_kmem = proc_mkdir("kmem", proc_spl);
748 if (proc_spl_kmem == NULL) {
753 proc_spl_kmem_slab = proc_create_data("slab", 0444, proc_spl_kmem,
754 &proc_slab_operations, NULL);
755 if (proc_spl_kmem_slab == NULL) {
760 proc_spl_kstat = proc_mkdir("kstat", proc_spl);
761 if (proc_spl_kstat == NULL) {
767 remove_proc_entry("kstat", proc_spl);
768 remove_proc_entry("slab", proc_spl_kmem);
769 remove_proc_entry("kmem", proc_spl);
770 remove_proc_entry("taskq-all", proc_spl);
771 remove_proc_entry("taskq", proc_spl);
772 remove_proc_entry("spl", NULL);
773 unregister_sysctl_table(spl_header);
782 remove_proc_entry("kstat", proc_spl);
783 remove_proc_entry("slab", proc_spl_kmem);
784 remove_proc_entry("kmem", proc_spl);
785 remove_proc_entry("taskq-all", proc_spl);
786 remove_proc_entry("taskq", proc_spl);
787 remove_proc_entry("spl", NULL);
789 ASSERT(spl_header != NULL);
790 unregister_sysctl_table(spl_header);