7 #define DEBUG_SUBSYSTEM S_PROC
10 static unsigned long table_min = 0;
11 static unsigned long table_max = ~0;
15 static struct ctl_table_header *spl_header = NULL;
16 static struct proc_dir_entry *proc_sys = NULL;
17 static struct proc_dir_entry *proc_sys_spl = NULL;
19 static struct proc_dir_entry *proc_sys_spl_mutex = NULL;
20 static struct proc_dir_entry *proc_sys_spl_mutex_stats = NULL;
23 static struct proc_dir_entry *proc_sys_spl_kmem = NULL;
26 struct proc_dir_entry *proc_sys_spl_kstat = NULL;
31 #define CTL_SPL_DEBUG 0x88
32 #define CTL_SPL_MUTEX 0x89
33 #define CTL_SPL_KMEM 0x90
34 #define CTL_SPL_KSTAT 0x91
37 CTL_VERSION = 1, /* Version */
38 CTL_HOSTID, /* Host id reported by /usr/bin/hostid */
39 CTL_HW_SERIAL, /* Hardware serial number from hostid */
41 CTL_DEBUG_SUBSYS, /* Debug subsystem */
42 CTL_DEBUG_MASK, /* Debug mask */
43 CTL_DEBUG_PRINTK, /* Force all messages to console */
44 CTL_DEBUG_MB, /* Debug buffer size */
45 CTL_DEBUG_BINARY, /* Include binary data in buffer */
46 CTL_DEBUG_CATASTROPHE, /* Set if we have BUG'd or panic'd */
47 CTL_DEBUG_PANIC_ON_BUG, /* Set if we should panic on BUG */
48 CTL_DEBUG_PATH, /* Dump log location */
49 CTL_DEBUG_DUMP, /* Dump debug buffer to file */
50 CTL_DEBUG_FORCE_BUG, /* Hook to force a BUG */
51 CTL_DEBUG_STACK_SIZE, /* Max observed stack size */
53 CTL_CONSOLE_RATELIMIT, /* Ratelimit console messages */
54 CTL_CONSOLE_MAX_DELAY_CS, /* Max delay at which we skip messages */
55 CTL_CONSOLE_MIN_DELAY_CS, /* Init delay at which we skip messages */
56 CTL_CONSOLE_BACKOFF, /* Delay increase factor */
59 CTL_KMEM_KMEMUSED, /* Crrently alloc'd kmem bytes */
60 CTL_KMEM_KMEMMAX, /* Max alloc'd by kmem bytes */
61 CTL_KMEM_VMEMUSED, /* Currently alloc'd vmem bytes */
62 CTL_KMEM_VMEMMAX, /* Max alloc'd by vmem bytes */
63 CTL_KMEM_ALLOC_FAILED, /* Cache allocation failed */
66 CTL_MUTEX_STATS, /* Global mutex statistics */
67 CTL_MUTEX_STATS_PER, /* Per mutex statistics */
68 CTL_MUTEX_SPIN_MAX, /* Maximum mutex spin iterations */
72 proc_copyin_string(char *kbuffer, int kbuffer_size,
73 const char *ubuffer, int ubuffer_size)
77 if (ubuffer_size > kbuffer_size)
80 if (copy_from_user((void *)kbuffer, (void *)ubuffer, ubuffer_size))
83 /* strip trailing whitespace */
84 size = strnlen(kbuffer, ubuffer_size);
86 if (!isspace(kbuffer[size]))
93 /* no space to terminate */
94 if (size == kbuffer_size)
97 kbuffer[size + 1] = 0;
102 proc_copyout_string(char *ubuffer, int ubuffer_size,
103 const char *kbuffer, char *append)
105 /* NB if 'append' != NULL, it's a single character to append to the
106 * copied out string - usually "\n", for /proc entries and
107 * (i.e. a terminating zero byte) for sysctl entries
109 int size = MIN(strlen(kbuffer), ubuffer_size);
111 if (copy_to_user(ubuffer, kbuffer, size))
114 if (append != NULL && size < ubuffer_size) {
115 if (copy_to_user(ubuffer + size, append, 1))
125 proc_dobitmasks(struct ctl_table *table, int write, struct file *filp,
126 void __user *buffer, size_t *lenp, loff_t *ppos)
128 unsigned long *mask = table->data;
129 int is_subsys = (mask == &spl_debug_subsys) ? 1 : 0;
130 int is_printk = (mask == &spl_debug_printk) ? 1 : 0;
135 str = kmem_alloc(size, KM_SLEEP);
140 rc = proc_copyin_string(str, size, buffer, *lenp);
144 rc = spl_debug_str2mask(mask, str, is_subsys);
145 /* Always print BUG/ASSERT to console, so keep this mask */
151 rc = spl_debug_mask2str(str, size, *mask, is_subsys);
155 rc = proc_copyout_string(buffer, *lenp,
163 kmem_free(str, size);
168 proc_debug_mb(struct ctl_table *table, int write, struct file *filp,
169 void __user *buffer, size_t *lenp, loff_t *ppos)
176 rc = proc_copyin_string(str, sizeof(str), buffer, *lenp);
180 rc = spl_debug_set_mb(simple_strtoul(str, NULL, 0));
183 len = snprintf(str, sizeof(str), "%d", spl_debug_get_mb());
187 rc = proc_copyout_string(buffer, *lenp, str + *ppos, "\n");
199 proc_dump_kernel(struct ctl_table *table, int write, struct file *filp,
200 void __user *buffer, size_t *lenp, loff_t *ppos)
205 spl_debug_dumplog(0);
215 proc_force_bug(struct ctl_table *table, int write, struct file *filp,
216 void __user *buffer, size_t *lenp, loff_t *ppos)
221 CERROR("Crashing due to forced SBUG\n");
232 proc_console_max_delay_cs(struct ctl_table *table, int write, struct file *filp,
233 void __user *buffer, size_t *lenp, loff_t *ppos)
235 int rc, max_delay_cs;
236 struct ctl_table dummy = *table;
240 dummy.data = &max_delay_cs;
241 dummy.proc_handler = &proc_dointvec;
245 rc = proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
249 if (max_delay_cs <= 0)
252 d = (max_delay_cs * HZ) / 100;
253 if (d == 0 || d < spl_console_min_delay)
256 spl_console_max_delay = d;
258 max_delay_cs = (spl_console_max_delay * 100) / HZ;
259 rc = proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
266 proc_console_min_delay_cs(struct ctl_table *table, int write, struct file *filp,
267 void __user *buffer, size_t *lenp, loff_t *ppos)
269 int rc, min_delay_cs;
270 struct ctl_table dummy = *table;
274 dummy.data = &min_delay_cs;
275 dummy.proc_handler = &proc_dointvec;
279 rc = proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
283 if (min_delay_cs <= 0)
286 d = (min_delay_cs * HZ) / 100;
287 if (d == 0 || d > spl_console_max_delay)
290 spl_console_min_delay = d;
292 min_delay_cs = (spl_console_min_delay * 100) / HZ;
293 rc = proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
300 proc_console_backoff(struct ctl_table *table, int write, struct file *filp,
301 void __user *buffer, size_t *lenp, loff_t *ppos)
304 struct ctl_table dummy = *table;
307 dummy.data = &backoff;
308 dummy.proc_handler = &proc_dointvec;
312 rc = proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
319 spl_console_backoff = backoff;
321 backoff = spl_console_backoff;
322 rc = proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
329 proc_doatomic64(struct ctl_table *table, int write, struct file *filp,
330 void __user *buffer, size_t *lenp, loff_t *ppos)
333 unsigned long min = 0, max = ~0, val;
334 struct ctl_table dummy = *table;
338 dummy.proc_handler = &proc_dointvec;
345 val = atomic_read((atomic64_t *)table->data);
346 rc = proc_doulongvec_minmax(&dummy, write, filp,
354 proc_dohostid(struct ctl_table *table, int write, struct file *filp,
355 void __user *buffer, size_t *lenp, loff_t *ppos)
363 /* We can't use proc_doulongvec_minmax() in the write
364 * case hear because hostid while a hex value has no
365 * leading 0x which confuses the helper function. */
366 rc = proc_copyin_string(str, sizeof(str), buffer, *lenp);
370 val = simple_strtol(str, &end, 16);
374 spl_hostid = (long)val;
375 sprintf(hw_serial, "%u", (val >= 0) ? val : -val);
378 len = snprintf(str, sizeof(str), "%lx", spl_hostid);
382 rc = proc_copyout_string(buffer, *lenp, str + *ppos, "\n");
395 mutex_seq_show_headers(struct seq_file *f)
397 seq_printf(f, "%-36s %-4s %-16s\t"
398 "e_tot\te_nh\te_sp\te_sl\tte_tot\tte_nh\n",
399 "name", "type", "owner");
403 mutex_seq_show(struct seq_file *f, void *p)
409 ASSERT(mp->km_magic == KM_MAGIC);
411 switch (mp->km_type) {
412 case MUTEX_DEFAULT: t = 'D'; break;
413 case MUTEX_SPIN: t = 'S'; break;
414 case MUTEX_ADAPTIVE: t = 'A'; break;
418 seq_printf(f, "%-36s %c ", mp->km_name, t);
420 seq_printf(f, "%p\t", mp->km_owner);
422 seq_printf(f, "%-16s\t", "<not held>");
424 for (i = 0; i < MUTEX_STATS_SIZE; i++)
425 seq_printf(f, "%d%c", mp->km_stats[i],
426 (i + 1 == MUTEX_STATS_SIZE) ? '\n' : '\t');
432 mutex_seq_start(struct seq_file *f, loff_t *pos)
438 spin_lock(&mutex_stats_lock);
440 mutex_seq_show_headers(f);
442 p = mutex_stats_list.next;
445 if (p == &mutex_stats_list)
449 RETURN(list_entry(p, kmutex_t, km_list));
453 mutex_seq_next(struct seq_file *f, void *p, loff_t *pos)
459 RETURN((mp->km_list.next == &mutex_stats_list) ?
460 NULL : list_entry(mp->km_list.next, kmutex_t, km_list));
464 mutex_seq_stop(struct seq_file *f, void *v)
466 spin_unlock(&mutex_stats_lock);
469 static struct seq_operations mutex_seq_ops = {
470 .show = mutex_seq_show,
471 .start = mutex_seq_start,
472 .next = mutex_seq_next,
473 .stop = mutex_seq_stop,
477 proc_mutex_open(struct inode *inode, struct file *filp)
479 return seq_open(filp, &mutex_seq_ops);
482 static struct file_operations proc_mutex_operations = {
483 .open = proc_mutex_open,
486 .release = seq_release,
488 #endif /* DEBUG_MUTEX */
490 static struct ctl_table spl_debug_table[] = {
492 .ctl_name = CTL_DEBUG_SUBSYS,
493 .procname = "subsystem",
494 .data = &spl_debug_subsys,
495 .maxlen = sizeof(unsigned long),
497 .proc_handler = &proc_dobitmasks
500 .ctl_name = CTL_DEBUG_MASK,
502 .data = &spl_debug_mask,
503 .maxlen = sizeof(unsigned long),
505 .proc_handler = &proc_dobitmasks
508 .ctl_name = CTL_DEBUG_PRINTK,
509 .procname = "printk",
510 .data = &spl_debug_printk,
511 .maxlen = sizeof(unsigned long),
513 .proc_handler = &proc_dobitmasks
516 .ctl_name = CTL_DEBUG_MB,
519 .proc_handler = &proc_debug_mb,
522 .ctl_name = CTL_DEBUG_BINARY,
523 .procname = "binary",
524 .data = &spl_debug_binary,
525 .maxlen = sizeof(int),
527 .proc_handler = &proc_dointvec,
530 .ctl_name = CTL_DEBUG_CATASTROPHE,
531 .procname = "catastrophe",
532 .data = &spl_debug_catastrophe,
533 .maxlen = sizeof(int),
535 .proc_handler = &proc_dointvec,
538 .ctl_name = CTL_DEBUG_PANIC_ON_BUG,
539 .procname = "panic_on_bug",
540 .data = &spl_debug_panic_on_bug,
541 .maxlen = sizeof(int),
543 .proc_handler = &proc_dointvec
546 .ctl_name = CTL_DEBUG_PATH,
548 .data = spl_debug_file_path,
549 .maxlen = sizeof(spl_debug_file_path),
551 .proc_handler = &proc_dostring,
554 .ctl_name = CTL_DEBUG_DUMP,
557 .proc_handler = &proc_dump_kernel,
559 { .ctl_name = CTL_DEBUG_FORCE_BUG,
560 .procname = "force_bug",
562 .proc_handler = &proc_force_bug,
565 .ctl_name = CTL_CONSOLE_RATELIMIT,
566 .procname = "console_ratelimit",
567 .data = &spl_console_ratelimit,
568 .maxlen = sizeof(int),
570 .proc_handler = &proc_dointvec,
573 .ctl_name = CTL_CONSOLE_MAX_DELAY_CS,
574 .procname = "console_max_delay_centisecs",
575 .maxlen = sizeof(int),
577 .proc_handler = &proc_console_max_delay_cs,
580 .ctl_name = CTL_CONSOLE_MIN_DELAY_CS,
581 .procname = "console_min_delay_centisecs",
582 .maxlen = sizeof(int),
584 .proc_handler = &proc_console_min_delay_cs,
587 .ctl_name = CTL_CONSOLE_BACKOFF,
588 .procname = "console_backoff",
589 .maxlen = sizeof(int),
591 .proc_handler = &proc_console_backoff,
594 .ctl_name = CTL_DEBUG_STACK_SIZE,
595 .procname = "stack_max",
596 .data = &spl_debug_stack,
597 .maxlen = sizeof(int),
599 .proc_handler = &proc_dointvec,
605 static struct ctl_table spl_mutex_table[] = {
607 .ctl_name = CTL_MUTEX_STATS,
609 .data = &mutex_stats,
610 .maxlen = sizeof(int) * MUTEX_STATS_SIZE,
612 .proc_handler = &proc_dointvec,
615 .ctl_name = CTL_MUTEX_SPIN_MAX,
616 .procname = "spin_max",
617 .data = &mutex_spin_max,
618 .maxlen = sizeof(int),
620 .proc_handler = &proc_dointvec,
624 #endif /* DEBUG_MUTEX */
627 static struct ctl_table spl_kmem_table[] = {
629 .ctl_name = CTL_KMEM_KMEMUSED,
630 .procname = "kmem_used",
631 .data = &kmem_alloc_used,
632 .maxlen = sizeof(atomic64_t),
634 .proc_handler = &proc_doatomic64,
637 .ctl_name = CTL_KMEM_KMEMMAX,
638 .procname = "kmem_max",
639 .data = &kmem_alloc_max,
640 .maxlen = sizeof(unsigned long),
641 .extra1 = &table_min,
642 .extra2 = &table_max,
644 .proc_handler = &proc_doulongvec_minmax,
647 .ctl_name = CTL_KMEM_VMEMUSED,
648 .procname = "vmem_used",
649 .data = &vmem_alloc_used,
650 .maxlen = sizeof(atomic64_t),
652 .proc_handler = &proc_doatomic64,
655 .ctl_name = CTL_KMEM_VMEMMAX,
656 .procname = "vmem_max",
657 .data = &vmem_alloc_max,
658 .maxlen = sizeof(unsigned long),
659 .extra1 = &table_min,
660 .extra2 = &table_max,
662 .proc_handler = &proc_doulongvec_minmax,
665 .ctl_name = CTL_KMEM_ALLOC_FAILED,
666 .procname = "kmem_alloc_failed",
667 .data = &kmem_cache_alloc_failed,
668 .maxlen = sizeof(atomic64_t),
670 .proc_handler = &proc_doatomic64,
674 #endif /* DEBUG_KMEM */
677 static struct ctl_table spl_kstat_table[] = {
680 #endif /* DEBUG_KSTAT */
682 static struct ctl_table spl_table[] = {
683 /* NB No .strategy entries have been provided since
684 * sysctl(8) prefers to go via /proc for portability.
687 .ctl_name = CTL_VERSION,
688 .procname = "version",
690 .maxlen = sizeof(spl_version),
692 .proc_handler = &proc_dostring,
695 .ctl_name = CTL_HOSTID,
696 .procname = "hostid",
698 .maxlen = sizeof(unsigned long),
700 .proc_handler = &proc_dohostid,
703 .ctl_name = CTL_HW_SERIAL,
704 .procname = "hw_serial",
706 .maxlen = sizeof(hw_serial),
708 .proc_handler = &proc_dostring,
711 .ctl_name = CTL_SPL_DEBUG,
714 .child = spl_debug_table,
718 .ctl_name = CTL_SPL_MUTEX,
721 .child = spl_mutex_table,
726 .ctl_name = CTL_SPL_KMEM,
729 .child = spl_kmem_table,
734 .ctl_name = CTL_SPL_KSTAT,
737 .child = spl_kstat_table,
743 static struct ctl_table spl_dir[] = {
754 proc_dir_entry_match(int len, const char *name, struct proc_dir_entry *de)
756 if (de->namelen != len)
759 return !memcmp(name, de->name, len);
762 struct proc_dir_entry *
763 proc_dir_entry_find(struct proc_dir_entry *root, const char *str)
765 struct proc_dir_entry *de;
767 for (de = root->subdir; de; de = de->next)
768 if (proc_dir_entry_match(strlen(str), str, de))
775 proc_dir_entries(struct proc_dir_entry *root)
777 struct proc_dir_entry *de;
780 for (de = root->subdir; de; de = de->next)
793 spl_header = register_sysctl_table(spl_dir, 0);
794 if (spl_header == NULL)
797 proc_sys = proc_dir_entry_find(&proc_root, "sys");
798 if (proc_sys == NULL)
799 GOTO(out, rc = -EUNATCH);
801 proc_sys_spl = proc_dir_entry_find(proc_sys, "spl");
802 if (proc_sys_spl == NULL)
803 GOTO(out, rc = -EUNATCH);
806 proc_sys_spl_mutex = proc_dir_entry_find(proc_sys_spl, "mutex");
807 if (proc_sys_spl_mutex == NULL)
808 GOTO(out, rc = -EUNATCH);
810 proc_sys_spl_mutex_stats = create_proc_entry("stats_per", 0444,
812 if (proc_sys_spl_mutex_stats == NULL)
813 GOTO(out, rc = -EUNATCH);
815 proc_sys_spl_mutex_stats->proc_fops = &proc_mutex_operations;
816 #endif /* DEBUG_MUTEX */
819 proc_sys_spl_kmem = proc_dir_entry_find(proc_sys_spl, "kmem");
820 if (proc_sys_spl_kmem == NULL)
821 GOTO(out2, rc = -EUNATCH);
822 #endif /* DEBUG_KMEM */
825 proc_sys_spl_kstat = proc_dir_entry_find(proc_sys_spl, "kstat");
826 if (proc_sys_spl_kstat == NULL)
827 GOTO(out2, rc = -EUNATCH);
828 #endif /* DEBUG_KSTAT */
832 remove_proc_entry("stats_per", proc_sys_spl_mutex);
834 unregister_sysctl_table(spl_header);
835 #endif /* CONFIG_SYSCTL */
845 ASSERT(spl_header != NULL);
846 remove_proc_entry("stats_per", proc_sys_spl_mutex);
847 unregister_sysctl_table(spl_header);