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