]> git.proxmox.com Git - mirror_spl.git/blob - module/spl/spl-proc.c
f25239aca9c452f3c7535bfa901ca6cce5a0d466
[mirror_spl.git] / module / spl / spl-proc.c
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>.
6 * UCRL-CODE-235197
7 *
8 * This file is part of the SPL, Solaris Porting Layer.
9 * For details, see <http://zfsonlinux.org/>.
10 *
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.
15 *
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
19 * for more details.
20 *
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 \*****************************************************************************/
26
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>
34
35 #ifdef SS_DEBUG_SUBSYS
36 #undef SS_DEBUG_SUBSYS
37 #endif
38
39 #define SS_DEBUG_SUBSYS SS_PROC
40
41 #if defined(CONSTIFY_PLUGIN) && LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
42 typedef struct ctl_table __no_const spl_ctl_table;
43 #else
44 typedef struct ctl_table spl_ctl_table;
45 #endif
46
47 #ifdef DEBUG_KMEM
48 static unsigned long table_min = 0;
49 static unsigned long table_max = ~0;
50 #endif
51
52 #ifdef CONFIG_SYSCTL
53 static struct ctl_table_header *spl_header = NULL;
54 #endif /* CONFIG_SYSCTL */
55
56 static struct proc_dir_entry *proc_spl = NULL;
57 #ifdef DEBUG_KMEM
58 static struct proc_dir_entry *proc_spl_kmem = NULL;
59 static struct proc_dir_entry *proc_spl_kmem_slab = NULL;
60 #endif /* DEBUG_KMEM */
61 struct proc_dir_entry *proc_spl_kstat = NULL;
62
63 #ifdef HAVE_CTL_NAME
64 #ifdef HAVE_CTL_UNNUMBERED
65
66 #define CTL_SPL CTL_UNNUMBERED
67 #define CTL_SPL_DEBUG CTL_UNNUMBERED
68 #define CTL_SPL_VM CTL_UNNUMBERED
69 #define CTL_SPL_MUTEX CTL_UNNUMBERED
70 #define CTL_SPL_KMEM CTL_UNNUMBERED
71 #define CTL_SPL_KSTAT CTL_UNNUMBERED
72
73 #define CTL_VERSION CTL_UNNUMBERED /* Version */
74 #define CTL_HOSTID CTL_UNNUMBERED /* Host id by /usr/bin/hostid */
75 #define CTL_HW_SERIAL CTL_UNNUMBERED /* HW serial number by hostid */
76 #define CTL_KALLSYMS CTL_UNNUMBERED /* kallsyms_lookup_name addr */
77
78 #define CTL_DEBUG_SUBSYS CTL_UNNUMBERED /* Debug subsystem */
79 #define CTL_DEBUG_MASK CTL_UNNUMBERED /* Debug mask */
80 #define CTL_DEBUG_PRINTK CTL_UNNUMBERED /* All messages to console */
81 #define CTL_DEBUG_MB CTL_UNNUMBERED /* Debug buffer size */
82 #define CTL_DEBUG_BINARY CTL_UNNUMBERED /* Binary data in buffer */
83 #define CTL_DEBUG_CATASTROPHE CTL_UNNUMBERED /* Set if BUG'd or panic'd */
84 #define CTL_DEBUG_PANIC_ON_BUG CTL_UNNUMBERED /* Should panic on BUG */
85 #define CTL_DEBUG_PATH CTL_UNNUMBERED /* Dump log location */
86 #define CTL_DEBUG_DUMP CTL_UNNUMBERED /* Dump debug buffer to file */
87 #define CTL_DEBUG_FORCE_BUG CTL_UNNUMBERED /* Hook to force a BUG */
88 #define CTL_DEBUG_STACK_SIZE CTL_UNNUMBERED /* Max observed stack size */
89
90 #define CTL_CONSOLE_RATELIMIT CTL_UNNUMBERED /* Ratelimit console messages */
91 #define CTL_CONSOLE_MAX_DELAY_CS CTL_UNNUMBERED /* Max delay skip messages */
92 #define CTL_CONSOLE_MIN_DELAY_CS CTL_UNNUMBERED /* Init delay skip messages */
93 #define CTL_CONSOLE_BACKOFF CTL_UNNUMBERED /* Delay increase factor */
94
95 #define CTL_VM_MINFREE CTL_UNNUMBERED /* Minimum free memory */
96 #define CTL_VM_DESFREE CTL_UNNUMBERED /* Desired free memory */
97 #define CTL_VM_LOTSFREE CTL_UNNUMBERED /* Lots of free memory */
98 #define CTL_VM_NEEDFREE CTL_UNNUMBERED /* Need free memory */
99 #define CTL_VM_SWAPFS_MINFREE CTL_UNNUMBERED /* Minimum swapfs memory */
100 #define CTL_VM_SWAPFS_RESERVE CTL_UNNUMBERED /* Reserved swapfs memory */
101 #define CTL_VM_AVAILRMEM CTL_UNNUMBERED /* Easily available memory */
102 #define CTL_VM_FREEMEM CTL_UNNUMBERED /* Free memory */
103 #define CTL_VM_PHYSMEM CTL_UNNUMBERED /* Total physical memory */
104
105 #ifdef DEBUG_KMEM
106 #define CTL_KMEM_KMEMUSED CTL_UNNUMBERED /* Alloc'd kmem bytes */
107 #define CTL_KMEM_KMEMMAX CTL_UNNUMBERED /* Max alloc'd by kmem bytes */
108 #define CTL_KMEM_VMEMUSED CTL_UNNUMBERED /* Alloc'd vmem bytes */
109 #define CTL_KMEM_VMEMMAX CTL_UNNUMBERED /* Max alloc'd by vmem bytes */
110 #define CTL_KMEM_SLAB_KMEMTOTAL CTL_UNNUMBERED /* Total kmem slab size */
111 #define CTL_KMEM_SLAB_KMEMALLOC CTL_UNNUMBERED /* Alloc'd kmem slab size */
112 #define CTL_KMEM_SLAB_KMEMMAX CTL_UNNUMBERED /* Max kmem slab size */
113 #define CTL_KMEM_SLAB_VMEMTOTAL CTL_UNNUMBERED /* Total vmem slab size */
114 #define CTL_KMEM_SLAB_VMEMALLOC CTL_UNNUMBERED /* Alloc'd vmem slab size */
115 #define CTL_KMEM_SLAB_VMEMMAX CTL_UNNUMBERED /* Max vmem slab size */
116 #endif
117
118 #else /* HAVE_CTL_UNNUMBERED */
119
120 enum {
121 CTL_SPL = 0x87,
122 CTL_SPL_DEBUG = 0x88,
123 CTL_SPL_VM = 0x89,
124 CTL_SPL_MUTEX = 0x90,
125 CTL_SPL_KMEM = 0x91,
126 CTL_SPL_KSTAT = 0x92,
127 };
128
129 enum {
130 CTL_VERSION = 1, /* Version */
131 CTL_HOSTID, /* Host id reported by /usr/bin/hostid */
132 CTL_HW_SERIAL, /* Hardware serial number from hostid */
133 CTL_KALLSYMS, /* Address of kallsyms_lookup_name */
134
135 #ifdef DEBUG_LOG
136 CTL_DEBUG_SUBSYS, /* Debug subsystem */
137 CTL_DEBUG_MASK, /* Debug mask */
138 CTL_DEBUG_PRINTK, /* Force all messages to console */
139 CTL_DEBUG_MB, /* Debug buffer size */
140 CTL_DEBUG_BINARY, /* Include binary data in buffer */
141 CTL_DEBUG_CATASTROPHE, /* Set if we have BUG'd or panic'd */
142 CTL_DEBUG_PANIC_ON_BUG, /* Set if we should panic on BUG */
143 CTL_DEBUG_PATH, /* Dump log location */
144 CTL_DEBUG_DUMP, /* Dump debug buffer to file */
145 CTL_DEBUG_FORCE_BUG, /* Hook to force a BUG */
146 CTL_DEBUG_STACK_SIZE, /* Max observed stack size */
147 #endif
148
149 CTL_CONSOLE_RATELIMIT, /* Ratelimit console messages */
150 CTL_CONSOLE_MAX_DELAY_CS, /* Max delay which we skip messages */
151 CTL_CONSOLE_MIN_DELAY_CS, /* Init delay which we skip messages */
152 CTL_CONSOLE_BACKOFF, /* Delay increase factor */
153
154 CTL_VM_MINFREE, /* Minimum free memory threshold */
155 CTL_VM_DESFREE, /* Desired free memory threshold */
156 CTL_VM_LOTSFREE, /* Lots of free memory threshold */
157 CTL_VM_NEEDFREE, /* Need free memory deficit */
158 CTL_VM_SWAPFS_MINFREE, /* Minimum swapfs memory */
159 CTL_VM_SWAPFS_RESERVE, /* Reserved swapfs memory */
160 CTL_VM_AVAILRMEM, /* Easily available memory */
161 CTL_VM_FREEMEM, /* Free memory */
162 CTL_VM_PHYSMEM, /* Total physical memory */
163
164 #ifdef DEBUG_KMEM
165 CTL_KMEM_KMEMUSED, /* Alloc'd kmem bytes */
166 CTL_KMEM_KMEMMAX, /* Max alloc'd by kmem bytes */
167 CTL_KMEM_VMEMUSED, /* Alloc'd vmem bytes */
168 CTL_KMEM_VMEMMAX, /* Max alloc'd by vmem bytes */
169 CTL_KMEM_SLAB_KMEMTOTAL, /* Total kmem slab size */
170 CTL_KMEM_SLAB_KMEMALLOC, /* Alloc'd kmem slab size */
171 CTL_KMEM_SLAB_KMEMMAX, /* Max kmem slab size */
172 CTL_KMEM_SLAB_VMEMTOTAL, /* Total vmem slab size */
173 CTL_KMEM_SLAB_VMEMALLOC, /* Alloc'd vmem slab size */
174 CTL_KMEM_SLAB_VMEMMAX, /* Max vmem slab size */
175 #endif
176 };
177 #endif /* HAVE_CTL_UNNUMBERED */
178 #endif /* HAVE_CTL_NAME */
179
180 static int
181 proc_copyin_string(char *kbuffer, int kbuffer_size,
182 const char *ubuffer, int ubuffer_size)
183 {
184 int size;
185
186 if (ubuffer_size > kbuffer_size)
187 return -EOVERFLOW;
188
189 if (copy_from_user((void *)kbuffer, (void *)ubuffer, ubuffer_size))
190 return -EFAULT;
191
192 /* strip trailing whitespace */
193 size = strnlen(kbuffer, ubuffer_size);
194 while (size-- >= 0)
195 if (!isspace(kbuffer[size]))
196 break;
197
198 /* empty string */
199 if (size < 0)
200 return -EINVAL;
201
202 /* no space to terminate */
203 if (size == kbuffer_size)
204 return -EOVERFLOW;
205
206 kbuffer[size + 1] = 0;
207 return 0;
208 }
209
210 static int
211 proc_copyout_string(char *ubuffer, int ubuffer_size,
212 const char *kbuffer, char *append)
213 {
214 /* NB if 'append' != NULL, it's a single character to append to the
215 * copied out string - usually "\n", for /proc entries and
216 * (i.e. a terminating zero byte) for sysctl entries
217 */
218 int size = MIN(strlen(kbuffer), ubuffer_size);
219
220 if (copy_to_user(ubuffer, kbuffer, size))
221 return -EFAULT;
222
223 if (append != NULL && size < ubuffer_size) {
224 if (copy_to_user(ubuffer + size, append, 1))
225 return -EFAULT;
226
227 size++;
228 }
229
230 return size;
231 }
232
233 #ifdef DEBUG_LOG
234 SPL_PROC_HANDLER(proc_dobitmasks)
235 {
236 unsigned long *mask = table->data;
237 int is_subsys = (mask == &spl_debug_subsys) ? 1 : 0;
238 int is_printk = (mask == &spl_debug_printk) ? 1 : 0;
239 int size = 512, rc;
240 char *str;
241 SENTRY;
242
243 str = kmem_alloc(size, KM_SLEEP);
244 if (str == NULL)
245 SRETURN(-ENOMEM);
246
247 if (write) {
248 rc = proc_copyin_string(str, size, buffer, *lenp);
249 if (rc < 0)
250 SRETURN(rc);
251
252 rc = spl_debug_str2mask(mask, str, is_subsys);
253 /* Always print BUG/ASSERT to console, so keep this mask */
254 if (is_printk)
255 *mask |= SD_EMERG;
256
257 *ppos += *lenp;
258 } else {
259 rc = spl_debug_mask2str(str, size, *mask, is_subsys);
260 if (*ppos >= rc)
261 rc = 0;
262 else
263 rc = proc_copyout_string(buffer, *lenp,
264 str + *ppos, "\n");
265 if (rc >= 0) {
266 *lenp = rc;
267 *ppos += rc;
268 }
269 }
270
271 kmem_free(str, size);
272 SRETURN(rc);
273 }
274
275 SPL_PROC_HANDLER(proc_debug_mb)
276 {
277 char str[32];
278 int rc, len;
279 SENTRY;
280
281 if (write) {
282 rc = proc_copyin_string(str, sizeof(str), buffer, *lenp);
283 if (rc < 0)
284 SRETURN(rc);
285
286 rc = spl_debug_set_mb(simple_strtoul(str, NULL, 0));
287 *ppos += *lenp;
288 } else {
289 len = snprintf(str, sizeof(str), "%d", spl_debug_get_mb());
290 if (*ppos >= len)
291 rc = 0;
292 else
293 rc = proc_copyout_string(buffer,*lenp,str+*ppos,"\n");
294
295 if (rc >= 0) {
296 *lenp = rc;
297 *ppos += rc;
298 }
299 }
300
301 SRETURN(rc);
302 }
303
304 SPL_PROC_HANDLER(proc_dump_kernel)
305 {
306 SENTRY;
307
308 if (write) {
309 spl_debug_dumplog(0);
310 *ppos += *lenp;
311 } else {
312 *lenp = 0;
313 }
314
315 SRETURN(0);
316 }
317
318 SPL_PROC_HANDLER(proc_force_bug)
319 {
320 SENTRY;
321
322 if (write)
323 PANIC("Crashing due to forced panic\n");
324 else
325 *lenp = 0;
326
327 SRETURN(0);
328 }
329
330 SPL_PROC_HANDLER(proc_console_max_delay_cs)
331 {
332 int rc, max_delay_cs;
333 spl_ctl_table dummy = *table;
334 long d;
335 SENTRY;
336
337 dummy.data = &max_delay_cs;
338 dummy.proc_handler = &proc_dointvec;
339
340 if (write) {
341 max_delay_cs = 0;
342 rc = spl_proc_dointvec(&dummy,write,filp,buffer,lenp,ppos);
343 if (rc < 0)
344 SRETURN(rc);
345
346 if (max_delay_cs <= 0)
347 SRETURN(-EINVAL);
348
349 d = (max_delay_cs * HZ) / 100;
350 if (d == 0 || d < spl_console_min_delay)
351 SRETURN(-EINVAL);
352
353 spl_console_max_delay = d;
354 } else {
355 max_delay_cs = (spl_console_max_delay * 100) / HZ;
356 rc = spl_proc_dointvec(&dummy,write,filp,buffer,lenp,ppos);
357 }
358
359 SRETURN(rc);
360 }
361
362 SPL_PROC_HANDLER(proc_console_min_delay_cs)
363 {
364 int rc, min_delay_cs;
365 spl_ctl_table dummy = *table;
366 long d;
367 SENTRY;
368
369 dummy.data = &min_delay_cs;
370 dummy.proc_handler = &proc_dointvec;
371
372 if (write) {
373 min_delay_cs = 0;
374 rc = spl_proc_dointvec(&dummy,write,filp,buffer,lenp,ppos);
375 if (rc < 0)
376 SRETURN(rc);
377
378 if (min_delay_cs <= 0)
379 SRETURN(-EINVAL);
380
381 d = (min_delay_cs * HZ) / 100;
382 if (d == 0 || d > spl_console_max_delay)
383 SRETURN(-EINVAL);
384
385 spl_console_min_delay = d;
386 } else {
387 min_delay_cs = (spl_console_min_delay * 100) / HZ;
388 rc = spl_proc_dointvec(&dummy,write,filp,buffer,lenp,ppos);
389 }
390
391 SRETURN(rc);
392 }
393
394 SPL_PROC_HANDLER(proc_console_backoff)
395 {
396 int rc, backoff;
397 spl_ctl_table dummy = *table;
398 SENTRY;
399
400 dummy.data = &backoff;
401 dummy.proc_handler = &proc_dointvec;
402
403 if (write) {
404 backoff = 0;
405 rc = spl_proc_dointvec(&dummy,write,filp,buffer,lenp,ppos);
406 if (rc < 0)
407 SRETURN(rc);
408
409 if (backoff <= 0)
410 SRETURN(-EINVAL);
411
412 spl_console_backoff = backoff;
413 } else {
414 backoff = spl_console_backoff;
415 rc = spl_proc_dointvec(&dummy,write,filp,buffer,lenp,ppos);
416 }
417
418 SRETURN(rc);
419 }
420 #endif /* DEBUG_LOG */
421
422 #ifdef DEBUG_KMEM
423 SPL_PROC_HANDLER(proc_domemused)
424 {
425 int rc = 0;
426 unsigned long min = 0, max = ~0, val;
427 spl_ctl_table dummy = *table;
428 SENTRY;
429
430 dummy.data = &val;
431 dummy.proc_handler = &proc_dointvec;
432 dummy.extra1 = &min;
433 dummy.extra2 = &max;
434
435 if (write) {
436 *ppos += *lenp;
437 } else {
438 # ifdef HAVE_ATOMIC64_T
439 val = atomic64_read((atomic64_t *)table->data);
440 # else
441 val = atomic_read((atomic_t *)table->data);
442 # endif /* HAVE_ATOMIC64_T */
443 rc = spl_proc_doulongvec_minmax(&dummy, write, filp,
444 buffer, lenp, ppos);
445 }
446
447 SRETURN(rc);
448 }
449
450 SPL_PROC_HANDLER(proc_doslab)
451 {
452 int rc = 0;
453 unsigned long min = 0, max = ~0, val = 0, mask;
454 spl_ctl_table dummy = *table;
455 spl_kmem_cache_t *skc;
456 SENTRY;
457
458 dummy.data = &val;
459 dummy.proc_handler = &proc_dointvec;
460 dummy.extra1 = &min;
461 dummy.extra2 = &max;
462
463 if (write) {
464 *ppos += *lenp;
465 } else {
466 down_read(&spl_kmem_cache_sem);
467 mask = (unsigned long)table->data;
468
469 list_for_each_entry(skc, &spl_kmem_cache_list, skc_list) {
470
471 /* Only use slabs of the correct kmem/vmem type */
472 if (!(skc->skc_flags & mask))
473 continue;
474
475 /* Sum the specified field for selected slabs */
476 switch (mask & (KMC_TOTAL | KMC_ALLOC | KMC_MAX)) {
477 case KMC_TOTAL:
478 val += skc->skc_slab_size * skc->skc_slab_total;
479 break;
480 case KMC_ALLOC:
481 val += skc->skc_obj_size * skc->skc_obj_alloc;
482 break;
483 case KMC_MAX:
484 val += skc->skc_obj_size * skc->skc_obj_max;
485 break;
486 }
487 }
488
489 up_read(&spl_kmem_cache_sem);
490 rc = spl_proc_doulongvec_minmax(&dummy, write, filp,
491 buffer, lenp, ppos);
492 }
493
494 SRETURN(rc);
495 }
496 #endif /* DEBUG_KMEM */
497
498 SPL_PROC_HANDLER(proc_dohostid)
499 {
500 int len, rc = 0;
501 char *end, str[32];
502 SENTRY;
503
504 if (write) {
505 /* We can't use spl_proc_doulongvec_minmax() in the write
506 * case here because hostid while a hex value has no
507 * leading 0x which confuses the helper function. */
508 rc = proc_copyin_string(str, sizeof(str), buffer, *lenp);
509 if (rc < 0)
510 SRETURN(rc);
511
512 spl_hostid = simple_strtoul(str, &end, 16);
513 if (str == end)
514 SRETURN(-EINVAL);
515
516 (void) snprintf(hw_serial, HW_HOSTID_LEN, "%lu", spl_hostid);
517 hw_serial[HW_HOSTID_LEN - 1] = '\0';
518 *ppos += *lenp;
519 } else {
520 len = snprintf(str, sizeof(str), "%lx", spl_hostid);
521 if (*ppos >= len)
522 rc = 0;
523 else
524 rc = proc_copyout_string(buffer,*lenp,str+*ppos,"\n");
525
526 if (rc >= 0) {
527 *lenp = rc;
528 *ppos += rc;
529 }
530 }
531
532 SRETURN(rc);
533 }
534
535 #ifndef HAVE_KALLSYMS_LOOKUP_NAME
536 SPL_PROC_HANDLER(proc_dokallsyms_lookup_name)
537 {
538 int len, rc = 0;
539 char *end, str[32];
540 SENTRY;
541
542 if (write) {
543 /* This may only be set once at module load time */
544 if (spl_kallsyms_lookup_name_fn != SYMBOL_POISON)
545 SRETURN(-EEXIST);
546
547 /* We can't use spl_proc_doulongvec_minmax() in the write
548 * case here because the address while a hex value has no
549 * leading 0x which confuses the helper function. */
550 rc = proc_copyin_string(str, sizeof(str), buffer, *lenp);
551 if (rc < 0)
552 SRETURN(rc);
553
554 spl_kallsyms_lookup_name_fn =
555 (kallsyms_lookup_name_t)simple_strtoul(str, &end, 16);
556 wake_up(&spl_kallsyms_lookup_name_waitq);
557
558 if (str == end)
559 SRETURN(-EINVAL);
560
561 *ppos += *lenp;
562 } else {
563 len = snprintf(str, sizeof(str), "%lx",
564 (unsigned long)spl_kallsyms_lookup_name_fn);
565 if (*ppos >= len)
566 rc = 0;
567 else
568 rc = proc_copyout_string(buffer,*lenp,str+*ppos,"\n");
569
570 if (rc >= 0) {
571 *lenp = rc;
572 *ppos += rc;
573 }
574 }
575
576 SRETURN(rc);
577 }
578 #endif /* HAVE_KALLSYMS_LOOKUP_NAME */
579
580 SPL_PROC_HANDLER(proc_doavailrmem)
581 {
582 int len, rc = 0;
583 char str[32];
584 SENTRY;
585
586 if (write) {
587 *ppos += *lenp;
588 } else {
589 len = snprintf(str, sizeof(str), "%lu",
590 (unsigned long)availrmem);
591 if (*ppos >= len)
592 rc = 0;
593 else
594 rc = proc_copyout_string(buffer,*lenp,str+*ppos,"\n");
595
596 if (rc >= 0) {
597 *lenp = rc;
598 *ppos += rc;
599 }
600 }
601
602 SRETURN(rc);
603 }
604
605 SPL_PROC_HANDLER(proc_dofreemem)
606 {
607 int len, rc = 0;
608 char str[32];
609 SENTRY;
610
611 if (write) {
612 *ppos += *lenp;
613 } else {
614 len = snprintf(str, sizeof(str), "%lu", (unsigned long)freemem);
615 if (*ppos >= len)
616 rc = 0;
617 else
618 rc = proc_copyout_string(buffer,*lenp,str+*ppos,"\n");
619
620 if (rc >= 0) {
621 *lenp = rc;
622 *ppos += rc;
623 }
624 }
625
626 SRETURN(rc);
627 }
628
629 #ifdef DEBUG_KMEM
630 static void
631 slab_seq_show_headers(struct seq_file *f)
632 {
633 seq_printf(f,
634 "--------------------- cache ----------"
635 "--------------------------------------------- "
636 "----- slab ------ "
637 "---- object ----- "
638 "--- emergency ---\n");
639 seq_printf(f,
640 "name "
641 " flags size alloc slabsize objsize "
642 "total alloc max "
643 "total alloc max "
644 "dlock alloc max\n");
645 }
646
647 static int
648 slab_seq_show(struct seq_file *f, void *p)
649 {
650 spl_kmem_cache_t *skc = p;
651
652 ASSERT(skc->skc_magic == SKC_MAGIC);
653
654 spin_lock(&skc->skc_lock);
655 seq_printf(f, "%-36s ", skc->skc_name);
656 seq_printf(f, "0x%05lx %9lu %9lu %8u %8u "
657 "%5lu %5lu %5lu %5lu %5lu %5lu %5lu %5lu %5lu\n",
658 (long unsigned)skc->skc_flags,
659 (long unsigned)(skc->skc_slab_size * skc->skc_slab_total),
660 (long unsigned)(skc->skc_obj_size * skc->skc_obj_alloc),
661 (unsigned)skc->skc_slab_size,
662 (unsigned)skc->skc_obj_size,
663 (long unsigned)skc->skc_slab_total,
664 (long unsigned)skc->skc_slab_alloc,
665 (long unsigned)skc->skc_slab_max,
666 (long unsigned)skc->skc_obj_total,
667 (long unsigned)skc->skc_obj_alloc,
668 (long unsigned)skc->skc_obj_max,
669 (long unsigned)skc->skc_obj_deadlock,
670 (long unsigned)skc->skc_obj_emergency,
671 (long unsigned)skc->skc_obj_emergency_max);
672
673 spin_unlock(&skc->skc_lock);
674
675 return 0;
676 }
677
678 static void *
679 slab_seq_start(struct seq_file *f, loff_t *pos)
680 {
681 struct list_head *p;
682 loff_t n = *pos;
683 SENTRY;
684
685 down_read(&spl_kmem_cache_sem);
686 if (!n)
687 slab_seq_show_headers(f);
688
689 p = spl_kmem_cache_list.next;
690 while (n--) {
691 p = p->next;
692 if (p == &spl_kmem_cache_list)
693 SRETURN(NULL);
694 }
695
696 SRETURN(list_entry(p, spl_kmem_cache_t, skc_list));
697 }
698
699 static void *
700 slab_seq_next(struct seq_file *f, void *p, loff_t *pos)
701 {
702 spl_kmem_cache_t *skc = p;
703 SENTRY;
704
705 ++*pos;
706 SRETURN((skc->skc_list.next == &spl_kmem_cache_list) ?
707 NULL : list_entry(skc->skc_list.next,spl_kmem_cache_t,skc_list));
708 }
709
710 static void
711 slab_seq_stop(struct seq_file *f, void *v)
712 {
713 up_read(&spl_kmem_cache_sem);
714 }
715
716 static struct seq_operations slab_seq_ops = {
717 .show = slab_seq_show,
718 .start = slab_seq_start,
719 .next = slab_seq_next,
720 .stop = slab_seq_stop,
721 };
722
723 static int
724 proc_slab_open(struct inode *inode, struct file *filp)
725 {
726 return seq_open(filp, &slab_seq_ops);
727 }
728
729 static struct file_operations proc_slab_operations = {
730 .open = proc_slab_open,
731 .read = seq_read,
732 .llseek = seq_lseek,
733 .release = seq_release,
734 };
735 #endif /* DEBUG_KMEM */
736
737 #ifdef DEBUG_LOG
738 static struct ctl_table spl_debug_table[] = {
739 {
740 CTL_NAME (CTL_DEBUG_SUBSYS)
741 .procname = "subsystem",
742 .data = &spl_debug_subsys,
743 .maxlen = sizeof(unsigned long),
744 .mode = 0644,
745 .proc_handler = &proc_dobitmasks
746 },
747 {
748 CTL_NAME (CTL_DEBUG_MASK)
749 .procname = "mask",
750 .data = &spl_debug_mask,
751 .maxlen = sizeof(unsigned long),
752 .mode = 0644,
753 .proc_handler = &proc_dobitmasks
754 },
755 {
756 CTL_NAME (CTL_DEBUG_PRINTK)
757 .procname = "printk",
758 .data = &spl_debug_printk,
759 .maxlen = sizeof(unsigned long),
760 .mode = 0644,
761 .proc_handler = &proc_dobitmasks
762 },
763 {
764 CTL_NAME (CTL_DEBUG_MB)
765 .procname = "mb",
766 .mode = 0644,
767 .proc_handler = &proc_debug_mb,
768 },
769 {
770 CTL_NAME (CTL_DEBUG_BINARY)
771 .procname = "binary",
772 .data = &spl_debug_binary,
773 .maxlen = sizeof(int),
774 .mode = 0644,
775 .proc_handler = &proc_dointvec,
776 },
777 {
778 CTL_NAME (CTL_DEBUG_CATASTROPHE)
779 .procname = "catastrophe",
780 .data = &spl_debug_catastrophe,
781 .maxlen = sizeof(int),
782 .mode = 0444,
783 .proc_handler = &proc_dointvec,
784 },
785 {
786 CTL_NAME (CTL_DEBUG_PANIC_ON_BUG)
787 .procname = "panic_on_bug",
788 .data = &spl_debug_panic_on_bug,
789 .maxlen = sizeof(int),
790 .mode = 0644,
791 .proc_handler = &proc_dointvec
792 },
793 {
794 CTL_NAME (CTL_DEBUG_PATH)
795 .procname = "path",
796 .data = spl_debug_file_path,
797 .maxlen = sizeof(spl_debug_file_path),
798 .mode = 0644,
799 .proc_handler = &proc_dostring,
800 },
801 {
802 CTL_NAME (CTL_DEBUG_DUMP)
803 .procname = "dump",
804 .mode = 0200,
805 .proc_handler = &proc_dump_kernel,
806 },
807 { CTL_NAME (CTL_DEBUG_FORCE_BUG)
808 .procname = "force_bug",
809 .mode = 0200,
810 .proc_handler = &proc_force_bug,
811 },
812 {
813 CTL_NAME (CTL_CONSOLE_RATELIMIT)
814 .procname = "console_ratelimit",
815 .data = &spl_console_ratelimit,
816 .maxlen = sizeof(int),
817 .mode = 0644,
818 .proc_handler = &proc_dointvec,
819 },
820 {
821 CTL_NAME (CTL_CONSOLE_MAX_DELAY_CS)
822 .procname = "console_max_delay_centisecs",
823 .maxlen = sizeof(int),
824 .mode = 0644,
825 .proc_handler = &proc_console_max_delay_cs,
826 },
827 {
828 CTL_NAME (CTL_CONSOLE_MIN_DELAY_CS)
829 .procname = "console_min_delay_centisecs",
830 .maxlen = sizeof(int),
831 .mode = 0644,
832 .proc_handler = &proc_console_min_delay_cs,
833 },
834 {
835 CTL_NAME (CTL_CONSOLE_BACKOFF)
836 .procname = "console_backoff",
837 .maxlen = sizeof(int),
838 .mode = 0644,
839 .proc_handler = &proc_console_backoff,
840 },
841 {
842 CTL_NAME (CTL_DEBUG_STACK_SIZE)
843 .procname = "stack_max",
844 .data = &spl_debug_stack,
845 .maxlen = sizeof(int),
846 .mode = 0444,
847 .proc_handler = &proc_dointvec,
848 },
849 {0},
850 };
851 #endif /* DEBUG_LOG */
852
853 static struct ctl_table spl_vm_table[] = {
854 {
855 CTL_NAME (CTL_VM_MINFREE)
856 .procname = "minfree",
857 .data = &minfree,
858 .maxlen = sizeof(int),
859 .mode = 0644,
860 .proc_handler = &proc_dointvec,
861 },
862 {
863 CTL_NAME (CTL_VM_DESFREE)
864 .procname = "desfree",
865 .data = &desfree,
866 .maxlen = sizeof(int),
867 .mode = 0644,
868 .proc_handler = &proc_dointvec,
869 },
870 {
871 CTL_NAME (CTL_VM_LOTSFREE)
872 .procname = "lotsfree",
873 .data = &lotsfree,
874 .maxlen = sizeof(int),
875 .mode = 0644,
876 .proc_handler = &proc_dointvec,
877 },
878 {
879 CTL_NAME (CTL_VM_NEEDFREE)
880 .procname = "needfree",
881 .data = &needfree,
882 .maxlen = sizeof(int),
883 .mode = 0444,
884 .proc_handler = &proc_dointvec,
885 },
886 {
887 CTL_NAME (CTL_VM_SWAPFS_MINFREE)
888 .procname = "swapfs_minfree",
889 .data = &swapfs_minfree,
890 .maxlen = sizeof(int),
891 .mode = 0644,
892 .proc_handler = &proc_dointvec,
893 },
894 {
895 CTL_NAME (CTL_VM_SWAPFS_RESERVE)
896 .procname = "swapfs_reserve",
897 .data = &swapfs_reserve,
898 .maxlen = sizeof(int),
899 .mode = 0644,
900 .proc_handler = &proc_dointvec,
901 },
902 {
903 CTL_NAME (CTL_VM_AVAILRMEM)
904 .procname = "availrmem",
905 .mode = 0444,
906 .proc_handler = &proc_doavailrmem,
907 },
908 {
909 CTL_NAME (CTL_VM_FREEMEM)
910 .procname = "freemem",
911 .data = (void *)2,
912 .maxlen = sizeof(int),
913 .mode = 0444,
914 .proc_handler = &proc_dofreemem,
915 },
916 {
917 CTL_NAME (CTL_VM_PHYSMEM)
918 .procname = "physmem",
919 .data = &physmem,
920 .maxlen = sizeof(int),
921 .mode = 0444,
922 .proc_handler = &proc_dointvec,
923 },
924 {0},
925 };
926
927 #ifdef DEBUG_KMEM
928 static struct ctl_table spl_kmem_table[] = {
929 {
930 CTL_NAME (CTL_KMEM_KMEMUSED)
931 .procname = "kmem_used",
932 .data = &kmem_alloc_used,
933 # ifdef HAVE_ATOMIC64_T
934 .maxlen = sizeof(atomic64_t),
935 # else
936 .maxlen = sizeof(atomic_t),
937 # endif /* HAVE_ATOMIC64_T */
938 .mode = 0444,
939 .proc_handler = &proc_domemused,
940 },
941 {
942 CTL_NAME (CTL_KMEM_KMEMMAX)
943 .procname = "kmem_max",
944 .data = &kmem_alloc_max,
945 .maxlen = sizeof(unsigned long),
946 .extra1 = &table_min,
947 .extra2 = &table_max,
948 .mode = 0444,
949 .proc_handler = &proc_doulongvec_minmax,
950 },
951 {
952 CTL_NAME (CTL_KMEM_VMEMUSED)
953 .procname = "vmem_used",
954 .data = &vmem_alloc_used,
955 # ifdef HAVE_ATOMIC64_T
956 .maxlen = sizeof(atomic64_t),
957 # else
958 .maxlen = sizeof(atomic_t),
959 # endif /* HAVE_ATOMIC64_T */
960 .mode = 0444,
961 .proc_handler = &proc_domemused,
962 },
963 {
964 CTL_NAME (CTL_KMEM_VMEMMAX)
965 .procname = "vmem_max",
966 .data = &vmem_alloc_max,
967 .maxlen = sizeof(unsigned long),
968 .extra1 = &table_min,
969 .extra2 = &table_max,
970 .mode = 0444,
971 .proc_handler = &proc_doulongvec_minmax,
972 },
973 {
974 CTL_NAME (CTL_KMEM_SLAB_KMEMTOTAL)
975 .procname = "slab_kmem_total",
976 .data = (void *)(KMC_KMEM | KMC_TOTAL),
977 .maxlen = sizeof(unsigned long),
978 .extra1 = &table_min,
979 .extra2 = &table_max,
980 .mode = 0444,
981 .proc_handler = &proc_doslab,
982 },
983 {
984 CTL_NAME (CTL_KMEM_SLAB_KMEMALLOC)
985 .procname = "slab_kmem_alloc",
986 .data = (void *)(KMC_KMEM | KMC_ALLOC),
987 .maxlen = sizeof(unsigned long),
988 .extra1 = &table_min,
989 .extra2 = &table_max,
990 .mode = 0444,
991 .proc_handler = &proc_doslab,
992 },
993 {
994 CTL_NAME (CTL_KMEM_SLAB_KMEMMAX)
995 .procname = "slab_kmem_max",
996 .data = (void *)(KMC_KMEM | KMC_MAX),
997 .maxlen = sizeof(unsigned long),
998 .extra1 = &table_min,
999 .extra2 = &table_max,
1000 .mode = 0444,
1001 .proc_handler = &proc_doslab,
1002 },
1003 {
1004 CTL_NAME (CTL_KMEM_SLAB_VMEMTOTAL)
1005 .procname = "slab_vmem_total",
1006 .data = (void *)(KMC_VMEM | KMC_TOTAL),
1007 .maxlen = sizeof(unsigned long),
1008 .extra1 = &table_min,
1009 .extra2 = &table_max,
1010 .mode = 0444,
1011 .proc_handler = &proc_doslab,
1012 },
1013 {
1014 CTL_NAME (CTL_KMEM_SLAB_VMEMALLOC)
1015 .procname = "slab_vmem_alloc",
1016 .data = (void *)(KMC_VMEM | KMC_ALLOC),
1017 .maxlen = sizeof(unsigned long),
1018 .extra1 = &table_min,
1019 .extra2 = &table_max,
1020 .mode = 0444,
1021 .proc_handler = &proc_doslab,
1022 },
1023 {
1024 CTL_NAME (CTL_KMEM_SLAB_VMEMMAX)
1025 .procname = "slab_vmem_max",
1026 .data = (void *)(KMC_VMEM | KMC_MAX),
1027 .maxlen = sizeof(unsigned long),
1028 .extra1 = &table_min,
1029 .extra2 = &table_max,
1030 .mode = 0444,
1031 .proc_handler = &proc_doslab,
1032 },
1033 {0},
1034 };
1035 #endif /* DEBUG_KMEM */
1036
1037 static struct ctl_table spl_kstat_table[] = {
1038 {0},
1039 };
1040
1041 static struct ctl_table spl_table[] = {
1042 /* NB No .strategy entries have been provided since
1043 * sysctl(8) prefers to go via /proc for portability.
1044 */
1045 {
1046 CTL_NAME (CTL_VERSION)
1047 .procname = "version",
1048 .data = spl_version,
1049 .maxlen = sizeof(spl_version),
1050 .mode = 0444,
1051 .proc_handler = &proc_dostring,
1052 },
1053 {
1054 CTL_NAME (CTL_HOSTID)
1055 .procname = "hostid",
1056 .data = &spl_hostid,
1057 .maxlen = sizeof(unsigned long),
1058 .mode = 0644,
1059 .proc_handler = &proc_dohostid,
1060 },
1061 {
1062 CTL_NAME (CTL_HW_SERIAL)
1063 .procname = "hw_serial",
1064 .data = hw_serial,
1065 .maxlen = sizeof(hw_serial),
1066 .mode = 0444,
1067 .proc_handler = &proc_dostring,
1068 },
1069 #ifndef HAVE_KALLSYMS_LOOKUP_NAME
1070 {
1071 CTL_NAME (CTL_KALLSYMS)
1072 .procname = "kallsyms_lookup_name",
1073 .data = &spl_kallsyms_lookup_name_fn,
1074 .maxlen = sizeof(unsigned long),
1075 .mode = 0644,
1076 .proc_handler = &proc_dokallsyms_lookup_name,
1077 },
1078 #endif
1079 #ifdef DEBUG_LOG
1080 {
1081 CTL_NAME (CTL_SPL_DEBUG)
1082 .procname = "debug",
1083 .mode = 0555,
1084 .child = spl_debug_table,
1085 },
1086 #endif
1087 {
1088 CTL_NAME (CTL_SPL_VM)
1089 .procname = "vm",
1090 .mode = 0555,
1091 .child = spl_vm_table,
1092 },
1093 #ifdef DEBUG_KMEM
1094 {
1095 CTL_NAME (CTL_SPL_KMEM)
1096 .procname = "kmem",
1097 .mode = 0555,
1098 .child = spl_kmem_table,
1099 },
1100 #endif
1101 {
1102 CTL_NAME (CTL_SPL_KSTAT)
1103 .procname = "kstat",
1104 .mode = 0555,
1105 .child = spl_kstat_table,
1106 },
1107 { 0 },
1108 };
1109
1110 static struct ctl_table spl_dir[] = {
1111 {
1112 CTL_NAME (CTL_SPL)
1113 .procname = "spl",
1114 .mode = 0555,
1115 .child = spl_table,
1116 },
1117 { 0 }
1118 };
1119
1120 static struct ctl_table spl_root[] = {
1121 {
1122 CTL_NAME (CTL_KERN)
1123 .procname = "kernel",
1124 .mode = 0555,
1125 .child = spl_dir,
1126 },
1127 { 0 }
1128 };
1129
1130 int
1131 spl_proc_init(void)
1132 {
1133 int rc = 0;
1134 SENTRY;
1135
1136 #ifdef CONFIG_SYSCTL
1137 spl_header = spl_register_sysctl_table(spl_root, 0);
1138 if (spl_header == NULL)
1139 SRETURN(-EUNATCH);
1140 #endif /* CONFIG_SYSCTL */
1141
1142 proc_spl = proc_mkdir("spl", NULL);
1143 if (proc_spl == NULL)
1144 SGOTO(out, rc = -EUNATCH);
1145
1146 #ifdef DEBUG_KMEM
1147 proc_spl_kmem = proc_mkdir("kmem", proc_spl);
1148 if (proc_spl_kmem == NULL)
1149 SGOTO(out, rc = -EUNATCH);
1150
1151 proc_spl_kmem_slab = proc_create_data("slab", 0444,
1152 proc_spl_kmem, &proc_slab_operations, NULL);
1153 if (proc_spl_kmem_slab == NULL)
1154 SGOTO(out, rc = -EUNATCH);
1155
1156 #endif /* DEBUG_KMEM */
1157
1158 proc_spl_kstat = proc_mkdir("kstat", proc_spl);
1159 if (proc_spl_kstat == NULL)
1160 SGOTO(out, rc = -EUNATCH);
1161 out:
1162 if (rc) {
1163 remove_proc_entry("kstat", proc_spl);
1164 #ifdef DEBUG_KMEM
1165 remove_proc_entry("slab", proc_spl_kmem);
1166 remove_proc_entry("kmem", proc_spl);
1167 #endif
1168 remove_proc_entry("spl", NULL);
1169 #ifdef CONFIG_SYSCTL
1170 spl_unregister_sysctl_table(spl_header);
1171 #endif /* CONFIG_SYSCTL */
1172 }
1173
1174 SRETURN(rc);
1175 }
1176
1177 void
1178 spl_proc_fini(void)
1179 {
1180 SENTRY;
1181
1182 remove_proc_entry("kstat", proc_spl);
1183 #ifdef DEBUG_KMEM
1184 remove_proc_entry("slab", proc_spl_kmem);
1185 remove_proc_entry("kmem", proc_spl);
1186 #endif
1187 remove_proc_entry("spl", NULL);
1188
1189 #ifdef CONFIG_SYSCTL
1190 ASSERT(spl_header != NULL);
1191 spl_unregister_sysctl_table(spl_header);
1192 #endif /* CONFIG_SYSCTL */
1193
1194 SEXIT;
1195 }