~ubuntu-branches/ubuntu/wily/spl-linux/wily

« back to all changes in this revision

Viewing changes to module/spl/spl-proc.c

  • Committer: Package Import Robot
  • Author(s): Aron Xu
  • Date: 2013-04-02 01:03:05 UTC
  • Revision ID: package-import@ubuntu.com-20130402010305-bt9to0tn48joen5q
Tags: upstream-0.6.1
ImportĀ upstreamĀ versionĀ 0.6.1

Show diffs side-by-side

added added

removed removed

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