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