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