]> git.proxmox.com Git - mirror_zfs.git/blame - module/spl/spl-kstat.c
Revert "Add KSTAT_TYPE_TXG type"
[mirror_zfs.git] / module / spl / spl-kstat.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
BB
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
BB
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) Kstat Implementation.
25\*****************************************************************************/
715f6251 26
ae4c36ad 27#include <linux/seq_file.h>
55abb092
BB
28#include <sys/kstat.h>
29#include <spl-debug.h>
04a479f7 30
b17edc10
BB
31#ifdef SS_DEBUG_SUBSYS
32#undef SS_DEBUG_SUBSYS
33#endif
34
35#define SS_DEBUG_SUBSYS SS_KSTAT
1ddf9722
YS
36#ifndef HAVE_PDE_DATA
37#define PDE_DATA(x) (PDE(x)->data)
38#endif
b17edc10 39
f2a745c4
RY
40static kmutex_t kstat_module_lock;
41static struct list_head kstat_module_list;
04a479f7
BB
42static kid_t kstat_id;
43
56d40a68
PS
44static int
45kstat_resize_raw(kstat_t *ksp)
46{
47 if (ksp->ks_raw_bufsize == KSTAT_RAW_MAX)
48 return ENOMEM;
49
50 vmem_free(ksp->ks_raw_buf, ksp->ks_raw_bufsize);
51 ksp->ks_raw_bufsize = MIN(ksp->ks_raw_bufsize * 2, KSTAT_RAW_MAX);
52 ksp->ks_raw_buf = vmem_alloc(ksp->ks_raw_bufsize, KM_SLEEP);
53
54 return 0;
55}
56
57static int
04a479f7
BB
58kstat_seq_show_headers(struct seq_file *f)
59{
60 kstat_t *ksp = (kstat_t *)f->private;
56d40a68
PS
61 int rc = 0;
62
04a479f7
BB
63 ASSERT(ksp->ks_magic == KS_MAGIC);
64
65 seq_printf(f, "%d %d 0x%02x %d %d %lld %lld\n",
66 ksp->ks_kid, ksp->ks_type, ksp->ks_flags,
67 ksp->ks_ndata, (int)ksp->ks_data_size,
68 ksp->ks_crtime, ksp->ks_snaptime);
69
70 switch (ksp->ks_type) {
71 case KSTAT_TYPE_RAW:
56d40a68
PS
72restart:
73 if (ksp->ks_raw_ops.headers) {
74 rc = ksp->ks_raw_ops.headers(
75 ksp->ks_raw_buf, ksp->ks_raw_bufsize);
76 if (rc == ENOMEM && !kstat_resize_raw(ksp))
77 goto restart;
78 if (!rc)
79 seq_puts(f, ksp->ks_raw_buf);
80 } else {
81 seq_printf(f, "raw data\n");
82 }
04a479f7
BB
83 break;
84 case KSTAT_TYPE_NAMED:
85 seq_printf(f, "%-31s %-4s %s\n",
86 "name", "type", "data");
87 break;
88 case KSTAT_TYPE_INTR:
89 seq_printf(f, "%-8s %-8s %-8s %-8s %-8s\n",
90 "hard", "soft", "watchdog",
91 "spurious", "multsvc");
92 break;
93 case KSTAT_TYPE_IO:
94 seq_printf(f,
95 "%-8s %-8s %-8s %-8s %-8s %-8s "
96 "%-8s %-8s %-8s %-8s %-8s %-8s\n",
97 "nread", "nwritten", "reads", "writes",
98 "wtime", "wlentime", "wupdate",
99 "rtime", "rlentime", "rupdate",
100 "wcnt", "rcnt");
101 break;
102 case KSTAT_TYPE_TIMER:
103 seq_printf(f,
104 "%-31s %-8s "
105 "%-8s %-8s %-8s %-8s %-8s\n",
106 "name", "events", "elapsed",
107 "min", "max", "start", "stop");
108 break;
109 default:
55abb092 110 PANIC("Undefined kstat type %d\n", ksp->ks_type);
04a479f7 111 }
56d40a68
PS
112
113 return -rc;
04a479f7
BB
114}
115
116static int
117kstat_seq_show_raw(struct seq_file *f, unsigned char *p, int l)
118{
119 int i, j;
120
121 for (i = 0; ; i++) {
122 seq_printf(f, "%03x:", i);
123
124 for (j = 0; j < 16; j++) {
125 if (i * 16 + j >= l) {
126 seq_printf(f, "\n");
127 goto out;
128 }
129
130 seq_printf(f, " %02x", (unsigned char)p[i * 16 + j]);
131 }
132 seq_printf(f, "\n");
133 }
134out:
135 return 0;
136}
137
138static int
139kstat_seq_show_named(struct seq_file *f, kstat_named_t *knp)
140{
141 seq_printf(f, "%-31s %-4d ", knp->name, knp->data_type);
142
143 switch (knp->data_type) {
144 case KSTAT_DATA_CHAR:
145 knp->value.c[15] = '\0'; /* NULL terminate */
146 seq_printf(f, "%-16s", knp->value.c);
147 break;
148 /* XXX - We need to be more careful able what tokens are
149 * used for each arch, for now this is correct for x86_64.
150 */
151 case KSTAT_DATA_INT32:
152 seq_printf(f, "%d", knp->value.i32);
153 break;
154 case KSTAT_DATA_UINT32:
155 seq_printf(f, "%u", knp->value.ui32);
156 break;
157 case KSTAT_DATA_INT64:
cfe57499 158 seq_printf(f, "%lld", (signed long long)knp->value.i64);
04a479f7
BB
159 break;
160 case KSTAT_DATA_UINT64:
cfe57499 161 seq_printf(f, "%llu", (unsigned long long)knp->value.ui64);
04a479f7
BB
162 break;
163 case KSTAT_DATA_LONG:
164 seq_printf(f, "%ld", knp->value.l);
165 break;
166 case KSTAT_DATA_ULONG:
cfe57499 167 seq_printf(f, "%lu", knp->value.ul);
04a479f7
BB
168 break;
169 case KSTAT_DATA_STRING:
170 KSTAT_NAMED_STR_PTR(knp)
171 [KSTAT_NAMED_STR_BUFLEN(knp)-1] = '\0';
172 seq_printf(f, "%s", KSTAT_NAMED_STR_PTR(knp));
173 break;
174 default:
55abb092 175 PANIC("Undefined kstat data type %d\n", knp->data_type);
04a479f7
BB
176 }
177
178 seq_printf(f, "\n");
179
180 return 0;
181}
182
183static int
184kstat_seq_show_intr(struct seq_file *f, kstat_intr_t *kip)
185{
186 seq_printf(f, "%-8u %-8u %-8u %-8u %-8u\n",
187 kip->intrs[KSTAT_INTR_HARD],
188 kip->intrs[KSTAT_INTR_SOFT],
189 kip->intrs[KSTAT_INTR_WATCHDOG],
190 kip->intrs[KSTAT_INTR_SPURIOUS],
191 kip->intrs[KSTAT_INTR_MULTSVC]);
192
193 return 0;
194}
195
196static int
197kstat_seq_show_io(struct seq_file *f, kstat_io_t *kip)
198{
199 seq_printf(f,
200 "%-8llu %-8llu %-8u %-8u %-8lld %-8lld "
201 "%-8lld %-8lld %-8lld %-8lld %-8u %-8u\n",
202 kip->nread, kip->nwritten,
203 kip->reads, kip->writes,
204 kip->wtime, kip->wlentime, kip->wlastupdate,
205 kip->rtime, kip->wlentime, kip->rlastupdate,
206 kip->wcnt, kip->rcnt);
207
208 return 0;
209}
210
211static int
212kstat_seq_show_timer(struct seq_file *f, kstat_timer_t *ktp)
213{
214 seq_printf(f,
215 "%-31s %-8llu %-8lld %-8lld %-8lld %-8lld %-8lld\n",
216 ktp->name, ktp->num_events, ktp->elapsed_time,
217 ktp->min_time, ktp->max_time,
218 ktp->start_time, ktp->stop_time);
219
220 return 0;
221}
222
223static int
224kstat_seq_show(struct seq_file *f, void *p)
225{
226 kstat_t *ksp = (kstat_t *)f->private;
227 int rc = 0;
228
229 ASSERT(ksp->ks_magic == KS_MAGIC);
230
231 switch (ksp->ks_type) {
232 case KSTAT_TYPE_RAW:
56d40a68
PS
233restart:
234 if (ksp->ks_raw_ops.data) {
235 rc = ksp->ks_raw_ops.data(
236 ksp->ks_raw_buf, ksp->ks_raw_bufsize, p);
237 if (rc == ENOMEM && !kstat_resize_raw(ksp))
238 goto restart;
239 if (!rc)
240 seq_puts(f, ksp->ks_raw_buf);
241 } else {
242 ASSERT(ksp->ks_ndata == 1);
243 rc = kstat_seq_show_raw(f, ksp->ks_data,
244 ksp->ks_data_size);
245 }
04a479f7
BB
246 break;
247 case KSTAT_TYPE_NAMED:
248 rc = kstat_seq_show_named(f, (kstat_named_t *)p);
249 break;
250 case KSTAT_TYPE_INTR:
251 rc = kstat_seq_show_intr(f, (kstat_intr_t *)p);
252 break;
253 case KSTAT_TYPE_IO:
254 rc = kstat_seq_show_io(f, (kstat_io_t *)p);
255 break;
256 case KSTAT_TYPE_TIMER:
257 rc = kstat_seq_show_timer(f, (kstat_timer_t *)p);
258 break;
259 default:
55abb092 260 PANIC("Undefined kstat type %d\n", ksp->ks_type);
04a479f7
BB
261 }
262
56d40a68 263 return -rc;
04a479f7
BB
264}
265
9a8b7a74
BB
266int
267kstat_default_update(kstat_t *ksp, int rw)
268{
269 ASSERT(ksp != NULL);
56d40a68
PS
270
271 if (rw == KSTAT_WRITE)
272 return (EACCES);
273
9a8b7a74
BB
274 return 0;
275}
276
04a479f7
BB
277static void *
278kstat_seq_data_addr(kstat_t *ksp, loff_t n)
279{
280 void *rc = NULL;
b17edc10 281 SENTRY;
04a479f7
BB
282
283 switch (ksp->ks_type) {
284 case KSTAT_TYPE_RAW:
56d40a68
PS
285 if (ksp->ks_raw_ops.addr)
286 rc = ksp->ks_raw_ops.addr(ksp, n);
287 else
288 rc = ksp->ks_data;
04a479f7
BB
289 break;
290 case KSTAT_TYPE_NAMED:
291 rc = ksp->ks_data + n * sizeof(kstat_named_t);
292 break;
293 case KSTAT_TYPE_INTR:
294 rc = ksp->ks_data + n * sizeof(kstat_intr_t);
295 break;
296 case KSTAT_TYPE_IO:
297 rc = ksp->ks_data + n * sizeof(kstat_io_t);
298 break;
299 case KSTAT_TYPE_TIMER:
300 rc = ksp->ks_data + n * sizeof(kstat_timer_t);
301 break;
302 default:
55abb092 303 PANIC("Undefined kstat type %d\n", ksp->ks_type);
04a479f7
BB
304 }
305
b17edc10 306 SRETURN(rc);
04a479f7
BB
307}
308
309static void *
310kstat_seq_start(struct seq_file *f, loff_t *pos)
311{
312 loff_t n = *pos;
313 kstat_t *ksp = (kstat_t *)f->private;
314 ASSERT(ksp->ks_magic == KS_MAGIC);
b17edc10 315 SENTRY;
04a479f7 316
71c9f0b0
BB
317 mutex_enter(&ksp->ks_lock);
318
56d40a68
PS
319 if (ksp->ks_type == KSTAT_TYPE_RAW) {
320 ksp->ks_raw_bufsize = PAGE_SIZE;
321 ksp->ks_raw_buf = vmem_alloc(ksp->ks_raw_bufsize, KM_SLEEP);
322 }
323
9a8b7a74
BB
324 /* Dynamically update kstat, on error existing kstats are used */
325 (void) ksp->ks_update(ksp, KSTAT_READ);
326
04a479f7
BB
327 ksp->ks_snaptime = gethrtime();
328
56d40a68
PS
329 if (!n && kstat_seq_show_headers(f))
330 SRETURN(NULL);
04a479f7
BB
331
332 if (n >= ksp->ks_ndata)
b17edc10 333 SRETURN(NULL);
04a479f7 334
b17edc10 335 SRETURN(kstat_seq_data_addr(ksp, n));
04a479f7
BB
336}
337
338static void *
339kstat_seq_next(struct seq_file *f, void *p, loff_t *pos)
340{
341 kstat_t *ksp = (kstat_t *)f->private;
342 ASSERT(ksp->ks_magic == KS_MAGIC);
b17edc10 343 SENTRY;
04a479f7
BB
344
345 ++*pos;
346 if (*pos >= ksp->ks_ndata)
b17edc10 347 SRETURN(NULL);
04a479f7 348
b17edc10 349 SRETURN(kstat_seq_data_addr(ksp, *pos));
04a479f7
BB
350}
351
352static void
353kstat_seq_stop(struct seq_file *f, void *v)
354{
355 kstat_t *ksp = (kstat_t *)f->private;
356 ASSERT(ksp->ks_magic == KS_MAGIC);
357
56d40a68
PS
358 if (ksp->ks_type == KSTAT_TYPE_RAW)
359 vmem_free(ksp->ks_raw_buf, ksp->ks_raw_bufsize);
360
71c9f0b0 361 mutex_exit(&ksp->ks_lock);
04a479f7
BB
362}
363
364static struct seq_operations kstat_seq_ops = {
365 .show = kstat_seq_show,
366 .start = kstat_seq_start,
367 .next = kstat_seq_next,
368 .stop = kstat_seq_stop,
369};
370
f2a745c4
RY
371static kstat_module_t *
372kstat_find_module(char *name)
373{
374 kstat_module_t *module;
375
376 list_for_each_entry(module, &kstat_module_list, ksm_module_list)
377 if (strncmp(name, module->ksm_name, KSTAT_STRLEN) == 0)
378 return (module);
379
380 return (NULL);
381}
382
383static kstat_module_t *
384kstat_create_module(char *name)
385{
386 kstat_module_t *module;
387 struct proc_dir_entry *pde;
388
389 pde = proc_mkdir(name, proc_spl_kstat);
390 if (pde == NULL)
391 return (NULL);
392
393 module = kmem_alloc(sizeof (kstat_module_t), KM_SLEEP);
394 module->ksm_proc = pde;
395 strlcpy(module->ksm_name, name, KSTAT_STRLEN+1);
396 INIT_LIST_HEAD(&module->ksm_kstat_list);
397 list_add_tail(&module->ksm_module_list, &kstat_module_list);
398
399 return (module);
400
401}
402
403static void
404kstat_delete_module(kstat_module_t *module)
405{
406 ASSERT(list_empty(&module->ksm_kstat_list));
407 remove_proc_entry(module->ksm_name, proc_spl_kstat);
408 list_del(&module->ksm_module_list);
409 kmem_free(module, sizeof(kstat_module_t));
410}
411
04a479f7
BB
412static int
413proc_kstat_open(struct inode *inode, struct file *filp)
414{
415 struct seq_file *f;
416 int rc;
417
418 rc = seq_open(filp, &kstat_seq_ops);
419 if (rc)
420 return rc;
421
422 f = filp->private_data;
1ddf9722 423 f->private = PDE_DATA(inode);
04a479f7
BB
424
425 return rc;
426}
427
56d40a68
PS
428static ssize_t
429proc_kstat_write(struct file *filp, const char __user *buf,
430 size_t len, loff_t *ppos)
431{
432 struct seq_file *f = filp->private_data;
433 kstat_t *ksp = f->private;
434 int rc;
435
436 ASSERT(ksp->ks_magic == KS_MAGIC);
437
438 mutex_enter(ksp->ks_lock);
439 rc = ksp->ks_update(ksp, KSTAT_WRITE);
440 mutex_exit(ksp->ks_lock);
441
442 if (rc)
443 return (-rc);
444
445 *ppos += len;
446 return (len);
447}
448
04a479f7 449static struct file_operations proc_kstat_operations = {
56d40a68
PS
450 .open = proc_kstat_open,
451 .write = proc_kstat_write,
452 .read = seq_read,
453 .llseek = seq_lseek,
454 .release = seq_release,
04a479f7
BB
455};
456
56d40a68
PS
457void
458__kstat_set_raw_ops(kstat_t *ksp,
459 int (*headers)(char *buf, size_t size),
460 int (*data)(char *buf, size_t size, void *data),
461 void *(*addr)(kstat_t *ksp, loff_t index))
462{
463 ksp->ks_raw_ops.headers = headers;
464 ksp->ks_raw_ops.data = data;
465 ksp->ks_raw_ops.addr = addr;
466}
467EXPORT_SYMBOL(__kstat_set_raw_ops);
468
04a479f7
BB
469kstat_t *
470__kstat_create(const char *ks_module, int ks_instance, const char *ks_name,
471 const char *ks_class, uchar_t ks_type, uint_t ks_ndata,
472 uchar_t ks_flags)
473{
474 kstat_t *ksp;
475
476 ASSERT(ks_module);
477 ASSERT(ks_instance == 0);
478 ASSERT(ks_name);
479 ASSERT(!(ks_flags & KSTAT_FLAG_UNSUPPORTED));
480
481 if ((ks_type == KSTAT_TYPE_INTR) || (ks_type == KSTAT_TYPE_IO))
482 ASSERT(ks_ndata == 1);
483
484 ksp = kmem_zalloc(sizeof(*ksp), KM_SLEEP);
485 if (ksp == NULL)
486 return ksp;
487
f2a745c4 488 mutex_enter(&kstat_module_lock);
04a479f7
BB
489 ksp->ks_kid = kstat_id;
490 kstat_id++;
f2a745c4 491 mutex_exit(&kstat_module_lock);
04a479f7
BB
492
493 ksp->ks_magic = KS_MAGIC;
71c9f0b0 494 mutex_init(&ksp->ks_lock, NULL, MUTEX_DEFAULT, NULL);
04a479f7
BB
495 INIT_LIST_HEAD(&ksp->ks_list);
496
497 ksp->ks_crtime = gethrtime();
498 ksp->ks_snaptime = ksp->ks_crtime;
499 strncpy(ksp->ks_module, ks_module, KSTAT_STRLEN);
500 ksp->ks_instance = ks_instance;
501 strncpy(ksp->ks_name, ks_name, KSTAT_STRLEN);
502 strncpy(ksp->ks_class, ks_class, KSTAT_STRLEN);
503 ksp->ks_type = ks_type;
504 ksp->ks_flags = ks_flags;
9a8b7a74
BB
505 ksp->ks_update = kstat_default_update;
506 ksp->ks_private = NULL;
56d40a68
PS
507 ksp->ks_raw_ops.headers = NULL;
508 ksp->ks_raw_ops.data = NULL;
509 ksp->ks_raw_ops.addr = NULL;
510 ksp->ks_raw_buf = NULL;
511 ksp->ks_raw_bufsize = 0;
04a479f7
BB
512
513 switch (ksp->ks_type) {
514 case KSTAT_TYPE_RAW:
515 ksp->ks_ndata = 1;
516 ksp->ks_data_size = ks_ndata;
517 break;
518 case KSTAT_TYPE_NAMED:
519 ksp->ks_ndata = ks_ndata;
520 ksp->ks_data_size = ks_ndata * sizeof(kstat_named_t);
521 break;
522 case KSTAT_TYPE_INTR:
523 ksp->ks_ndata = ks_ndata;
524 ksp->ks_data_size = ks_ndata * sizeof(kstat_intr_t);
525 break;
526 case KSTAT_TYPE_IO:
527 ksp->ks_ndata = ks_ndata;
528 ksp->ks_data_size = ks_ndata * sizeof(kstat_io_t);
529 break;
530 case KSTAT_TYPE_TIMER:
531 ksp->ks_ndata = ks_ndata;
532 ksp->ks_data_size = ks_ndata * sizeof(kstat_timer_t);
533 break;
534 default:
55abb092 535 PANIC("Undefined kstat type %d\n", ksp->ks_type);
04a479f7
BB
536 }
537
538 if (ksp->ks_flags & KSTAT_FLAG_VIRTUAL) {
539 ksp->ks_data = NULL;
540 } else {
541 ksp->ks_data = kmem_alloc(ksp->ks_data_size, KM_SLEEP);
542 if (ksp->ks_data == NULL) {
543 kmem_free(ksp, sizeof(*ksp));
544 ksp = NULL;
545 }
546 }
547
548 return ksp;
549}
550EXPORT_SYMBOL(__kstat_create);
551
552void
553__kstat_install(kstat_t *ksp)
554{
f2a745c4 555 kstat_module_t *module;
04a479f7 556 kstat_t *tmp;
04a479f7 557
f2a745c4 558 ASSERT(ksp);
04a479f7 559
f2a745c4 560 mutex_enter(&kstat_module_lock);
04a479f7 561
f2a745c4
RY
562 module = kstat_find_module(ksp->ks_module);
563 if (module == NULL) {
564 module = kstat_create_module(ksp->ks_module);
565 if (module == NULL)
566 goto out;
04a479f7
BB
567 }
568
f2a745c4
RY
569 /*
570 * Only one entry by this name per-module, on failure the module
571 * shouldn't be deleted because we know it has at least one entry.
572 */
573 list_for_each_entry(tmp, &module->ksm_kstat_list, ks_list)
574 if (strncmp(tmp->ks_name, ksp->ks_name, KSTAT_STRLEN) == 0)
575 goto out;
576
577 list_add_tail(&ksp->ks_list, &module->ksm_kstat_list);
04a479f7 578
71c9f0b0 579 mutex_enter(&ksp->ks_lock);
f2a745c4 580 ksp->ks_owner = module;
56d40a68 581 ksp->ks_proc = proc_create_data(ksp->ks_name, 0644,
f2a745c4
RY
582 module->ksm_proc, &proc_kstat_operations, (void *)ksp);
583 if (ksp->ks_proc == NULL) {
584 list_del_init(&ksp->ks_list);
585 if (list_empty(&module->ksm_kstat_list))
586 kstat_delete_module(module);
587 }
71c9f0b0 588 mutex_exit(&ksp->ks_lock);
04a479f7 589out:
f2a745c4 590 mutex_exit(&kstat_module_lock);
04a479f7
BB
591}
592EXPORT_SYMBOL(__kstat_install);
593
594void
595__kstat_delete(kstat_t *ksp)
596{
f2a745c4 597 kstat_module_t *module = ksp->ks_owner;
04a479f7 598
f2a745c4
RY
599 mutex_enter(&kstat_module_lock);
600 list_del_init(&ksp->ks_list);
601 mutex_exit(&kstat_module_lock);
04a479f7 602
f2a745c4
RY
603 if (ksp->ks_proc) {
604 remove_proc_entry(ksp->ks_name, module->ksm_proc);
04a479f7 605
f2a745c4
RY
606 /* Remove top level module directory if it's empty */
607 if (list_empty(&module->ksm_kstat_list))
608 kstat_delete_module(module);
04a479f7
BB
609 }
610
611 if (!(ksp->ks_flags & KSTAT_FLAG_VIRTUAL))
f2a745c4 612 kmem_free(ksp->ks_data, ksp->ks_data_size);
04a479f7 613
71c9f0b0 614 mutex_destroy(&ksp->ks_lock);
04a479f7
BB
615 kmem_free(ksp, sizeof(*ksp));
616
617 return;
618}
619EXPORT_SYMBOL(__kstat_delete);
620
04a479f7 621int
1114ae6a 622spl_kstat_init(void)
04a479f7 623{
b17edc10 624 SENTRY;
f2a745c4
RY
625 mutex_init(&kstat_module_lock, NULL, MUTEX_DEFAULT, NULL);
626 INIT_LIST_HEAD(&kstat_module_list);
04a479f7 627 kstat_id = 0;
b17edc10 628 SRETURN(0);
04a479f7
BB
629}
630
631void
1114ae6a 632spl_kstat_fini(void)
04a479f7 633{
b17edc10 634 SENTRY;
f2a745c4
RY
635 ASSERT(list_empty(&kstat_module_list));
636 mutex_destroy(&kstat_module_lock);
b17edc10 637 SEXIT;
04a479f7
BB
638}
639