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