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>.
8 * This file is part of the SPL, Solaris Porting Layer.
10 * The SPL is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
15 * The SPL is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * You should have received a copy of the GNU General Public License along
21 * with the SPL. If not, see <http://www.gnu.org/licenses/>.
23 * Solaris Porting Layer (SPL) Kstat Implementation.
25 * Links to Illumos.org for more information on kstat function:
26 * [1] https://illumos.org/man/1M/kstat
27 * [2] https://illumos.org/man/9f/kstat_create
30 #include <linux/seq_file.h>
31 #include <sys/kstat.h>
33 #include <sys/cmn_err.h>
34 #include <sys/sysmacros.h>
35 #include <sys/string.h>
37 static kmutex_t kstat_module_lock
;
38 static struct list_head kstat_module_list
;
39 static kid_t kstat_id
;
42 kstat_resize_raw(kstat_t
*ksp
)
44 if (ksp
->ks_raw_bufsize
== KSTAT_RAW_MAX
)
47 vmem_free(ksp
->ks_raw_buf
, ksp
->ks_raw_bufsize
);
48 ksp
->ks_raw_bufsize
= MIN(ksp
->ks_raw_bufsize
* 2, KSTAT_RAW_MAX
);
49 ksp
->ks_raw_buf
= vmem_alloc(ksp
->ks_raw_bufsize
, KM_SLEEP
);
55 kstat_seq_show_headers(struct seq_file
*f
)
57 kstat_t
*ksp
= (kstat_t
*)f
->private;
60 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
62 seq_printf(f
, "%d %d 0x%02x %d %d %lld %lld\n",
63 ksp
->ks_kid
, ksp
->ks_type
, ksp
->ks_flags
,
64 ksp
->ks_ndata
, (int)ksp
->ks_data_size
,
65 ksp
->ks_crtime
, ksp
->ks_snaptime
);
67 switch (ksp
->ks_type
) {
70 if (ksp
->ks_raw_ops
.headers
) {
71 rc
= ksp
->ks_raw_ops
.headers(
72 ksp
->ks_raw_buf
, ksp
->ks_raw_bufsize
);
73 if (rc
== ENOMEM
&& !kstat_resize_raw(ksp
))
76 seq_puts(f
, ksp
->ks_raw_buf
);
78 seq_printf(f
, "raw data\n");
81 case KSTAT_TYPE_NAMED
:
82 seq_printf(f
, "%-31s %-4s %s\n",
83 "name", "type", "data");
86 seq_printf(f
, "%-8s %-8s %-8s %-8s %-8s\n",
87 "hard", "soft", "watchdog",
88 "spurious", "multsvc");
92 "%-8s %-8s %-8s %-8s %-8s %-8s "
93 "%-8s %-8s %-8s %-8s %-8s %-8s\n",
94 "nread", "nwritten", "reads", "writes",
95 "wtime", "wlentime", "wupdate",
96 "rtime", "rlentime", "rupdate",
99 case KSTAT_TYPE_TIMER
:
102 "%-8s %-8s %-8s %-8s %-8s\n",
103 "name", "events", "elapsed",
104 "min", "max", "start", "stop");
107 PANIC("Undefined kstat type %d\n", ksp
->ks_type
);
114 kstat_seq_show_raw(struct seq_file
*f
, unsigned char *p
, int l
)
119 seq_printf(f
, "%03x:", i
);
121 for (j
= 0; j
< 16; j
++) {
122 if (i
* 16 + j
>= l
) {
127 seq_printf(f
, " %02x", (unsigned char)p
[i
* 16 + j
]);
136 kstat_seq_show_named(struct seq_file
*f
, kstat_named_t
*knp
)
138 seq_printf(f
, "%-31s %-4d ", knp
->name
, knp
->data_type
);
140 switch (knp
->data_type
) {
141 case KSTAT_DATA_CHAR
:
142 knp
->value
.c
[15] = '\0'; /* NULL terminate */
143 seq_printf(f
, "%-16s", knp
->value
.c
);
146 * NOTE - We need to be more careful able what tokens are
147 * used for each arch, for now this is correct for x86_64.
149 case KSTAT_DATA_INT32
:
150 seq_printf(f
, "%d", knp
->value
.i32
);
152 case KSTAT_DATA_UINT32
:
153 seq_printf(f
, "%u", knp
->value
.ui32
);
155 case KSTAT_DATA_INT64
:
156 seq_printf(f
, "%lld", (signed long long)knp
->value
.i64
);
158 case KSTAT_DATA_UINT64
:
159 seq_printf(f
, "%llu",
160 (unsigned long long)knp
->value
.ui64
);
162 case KSTAT_DATA_LONG
:
163 seq_printf(f
, "%ld", knp
->value
.l
);
165 case KSTAT_DATA_ULONG
:
166 seq_printf(f
, "%lu", knp
->value
.ul
);
168 case KSTAT_DATA_STRING
:
169 KSTAT_NAMED_STR_PTR(knp
)
170 [KSTAT_NAMED_STR_BUFLEN(knp
)-1] = '\0';
171 seq_printf(f
, "%s", KSTAT_NAMED_STR_PTR(knp
));
174 PANIC("Undefined kstat data type %d\n", knp
->data_type
);
183 kstat_seq_show_intr(struct seq_file
*f
, kstat_intr_t
*kip
)
185 seq_printf(f
, "%-8u %-8u %-8u %-8u %-8u\n",
186 kip
->intrs
[KSTAT_INTR_HARD
],
187 kip
->intrs
[KSTAT_INTR_SOFT
],
188 kip
->intrs
[KSTAT_INTR_WATCHDOG
],
189 kip
->intrs
[KSTAT_INTR_SPURIOUS
],
190 kip
->intrs
[KSTAT_INTR_MULTSVC
]);
196 kstat_seq_show_io(struct seq_file
*f
, kstat_io_t
*kip
)
198 /* though wlentime & friends are signed, they will never be negative */
200 "%-8llu %-8llu %-8u %-8u %-8llu %-8llu "
201 "%-8llu %-8llu %-8llu %-8llu %-8u %-8u\n",
202 kip
->nread
, kip
->nwritten
,
203 kip
->reads
, kip
->writes
,
204 kip
->wtime
, kip
->wlentime
, kip
->wlastupdate
,
205 kip
->rtime
, kip
->rlentime
, kip
->rlastupdate
,
206 kip
->wcnt
, kip
->rcnt
);
212 kstat_seq_show_timer(struct seq_file
*f
, kstat_timer_t
*ktp
)
215 "%-31s %-8llu %-8llu %-8llu %-8llu %-8llu %-8llu\n",
216 ktp
->name
, ktp
->num_events
, ktp
->elapsed_time
,
217 ktp
->min_time
, ktp
->max_time
,
218 ktp
->start_time
, ktp
->stop_time
);
224 kstat_seq_show(struct seq_file
*f
, void *p
)
226 kstat_t
*ksp
= (kstat_t
*)f
->private;
229 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
231 switch (ksp
->ks_type
) {
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
))
240 seq_puts(f
, ksp
->ks_raw_buf
);
242 ASSERT(ksp
->ks_ndata
== 1);
243 rc
= kstat_seq_show_raw(f
, ksp
->ks_data
,
247 case KSTAT_TYPE_NAMED
:
248 rc
= kstat_seq_show_named(f
, (kstat_named_t
*)p
);
250 case KSTAT_TYPE_INTR
:
251 rc
= kstat_seq_show_intr(f
, (kstat_intr_t
*)p
);
254 rc
= kstat_seq_show_io(f
, (kstat_io_t
*)p
);
256 case KSTAT_TYPE_TIMER
:
257 rc
= kstat_seq_show_timer(f
, (kstat_timer_t
*)p
);
260 PANIC("Undefined kstat type %d\n", ksp
->ks_type
);
267 kstat_default_update(kstat_t
*ksp
, int rw
)
271 if (rw
== KSTAT_WRITE
)
278 kstat_seq_data_addr(kstat_t
*ksp
, loff_t n
)
282 switch (ksp
->ks_type
) {
284 if (ksp
->ks_raw_ops
.addr
)
285 rc
= ksp
->ks_raw_ops
.addr(ksp
, n
);
289 case KSTAT_TYPE_NAMED
:
290 rc
= ksp
->ks_data
+ n
* sizeof (kstat_named_t
);
292 case KSTAT_TYPE_INTR
:
293 rc
= ksp
->ks_data
+ n
* sizeof (kstat_intr_t
);
296 rc
= ksp
->ks_data
+ n
* sizeof (kstat_io_t
);
298 case KSTAT_TYPE_TIMER
:
299 rc
= ksp
->ks_data
+ n
* sizeof (kstat_timer_t
);
302 PANIC("Undefined kstat type %d\n", ksp
->ks_type
);
309 kstat_seq_start(struct seq_file
*f
, loff_t
*pos
)
312 kstat_t
*ksp
= (kstat_t
*)f
->private;
313 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
315 mutex_enter(ksp
->ks_lock
);
317 if (ksp
->ks_type
== KSTAT_TYPE_RAW
) {
318 ksp
->ks_raw_bufsize
= PAGE_SIZE
;
319 ksp
->ks_raw_buf
= vmem_alloc(ksp
->ks_raw_bufsize
, KM_SLEEP
);
322 /* Dynamically update kstat, on error existing kstats are used */
323 (void) ksp
->ks_update(ksp
, KSTAT_READ
);
325 ksp
->ks_snaptime
= gethrtime();
327 if (!(ksp
->ks_flags
& KSTAT_FLAG_NO_HEADERS
) && !n
&&
328 kstat_seq_show_headers(f
))
331 if (n
>= ksp
->ks_ndata
)
334 return (kstat_seq_data_addr(ksp
, n
));
338 kstat_seq_next(struct seq_file
*f
, void *p
, loff_t
*pos
)
340 kstat_t
*ksp
= (kstat_t
*)f
->private;
341 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
344 if (*pos
>= ksp
->ks_ndata
)
347 return (kstat_seq_data_addr(ksp
, *pos
));
351 kstat_seq_stop(struct seq_file
*f
, void *v
)
353 kstat_t
*ksp
= (kstat_t
*)f
->private;
354 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
356 if (ksp
->ks_type
== KSTAT_TYPE_RAW
)
357 vmem_free(ksp
->ks_raw_buf
, ksp
->ks_raw_bufsize
);
359 mutex_exit(ksp
->ks_lock
);
362 static const struct seq_operations kstat_seq_ops
= {
363 .show
= kstat_seq_show
,
364 .start
= kstat_seq_start
,
365 .next
= kstat_seq_next
,
366 .stop
= kstat_seq_stop
,
369 static kstat_module_t
*
370 kstat_find_module(char *name
)
372 kstat_module_t
*module
= NULL
;
374 list_for_each_entry(module
, &kstat_module_list
, ksm_module_list
) {
375 if (strncmp(name
, module
->ksm_name
, KSTAT_STRLEN
) == 0)
382 static kstat_module_t
*
383 kstat_create_module(char *name
)
385 kstat_module_t
*module
;
386 struct proc_dir_entry
*pde
;
388 pde
= proc_mkdir(name
, proc_spl_kstat
);
392 module
= kmem_alloc(sizeof (kstat_module_t
), KM_SLEEP
);
393 module
->ksm_proc
= pde
;
394 strlcpy(module
->ksm_name
, name
, KSTAT_STRLEN
);
395 INIT_LIST_HEAD(&module
->ksm_kstat_list
);
396 list_add_tail(&module
->ksm_module_list
, &kstat_module_list
);
403 kstat_delete_module(kstat_module_t
*module
)
405 ASSERT(list_empty(&module
->ksm_kstat_list
));
406 remove_proc_entry(module
->ksm_name
, proc_spl_kstat
);
407 list_del(&module
->ksm_module_list
);
408 kmem_free(module
, sizeof (kstat_module_t
));
412 proc_kstat_open(struct inode
*inode
, struct file
*filp
)
417 rc
= seq_open(filp
, &kstat_seq_ops
);
421 f
= filp
->private_data
;
422 f
->private = SPL_PDE_DATA(inode
);
428 proc_kstat_write(struct file
*filp
, const char __user
*buf
, size_t len
,
431 struct seq_file
*f
= filp
->private_data
;
432 kstat_t
*ksp
= f
->private;
435 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
437 mutex_enter(ksp
->ks_lock
);
438 rc
= ksp
->ks_update(ksp
, KSTAT_WRITE
);
439 mutex_exit(ksp
->ks_lock
);
448 static const kstat_proc_op_t proc_kstat_operations
= {
449 #ifdef HAVE_PROC_OPS_STRUCT
450 .proc_open
= proc_kstat_open
,
451 .proc_write
= proc_kstat_write
,
452 .proc_read
= seq_read
,
453 .proc_lseek
= seq_lseek
,
454 .proc_release
= seq_release
,
456 .open
= proc_kstat_open
,
457 .write
= proc_kstat_write
,
460 .release
= seq_release
,
465 __kstat_set_raw_ops(kstat_t
*ksp
,
466 int (*headers
)(char *buf
, size_t size
),
467 int (*data
)(char *buf
, size_t size
, void *data
),
468 void *(*addr
)(kstat_t
*ksp
, loff_t index
))
470 ksp
->ks_raw_ops
.headers
= headers
;
471 ksp
->ks_raw_ops
.data
= data
;
472 ksp
->ks_raw_ops
.addr
= addr
;
474 EXPORT_SYMBOL(__kstat_set_raw_ops
);
477 kstat_proc_entry_init(kstat_proc_entry_t
*kpep
, const char *module
,
480 kpep
->kpe_owner
= NULL
;
481 kpep
->kpe_proc
= NULL
;
482 INIT_LIST_HEAD(&kpep
->kpe_list
);
483 strlcpy(kpep
->kpe_module
, module
, sizeof (kpep
->kpe_module
));
484 strlcpy(kpep
->kpe_name
, name
, sizeof (kpep
->kpe_name
));
486 EXPORT_SYMBOL(kstat_proc_entry_init
);
489 __kstat_create(const char *ks_module
, int ks_instance
, const char *ks_name
,
490 const char *ks_class
, uchar_t ks_type
, uint_t ks_ndata
,
496 ASSERT(ks_instance
== 0);
499 if ((ks_type
== KSTAT_TYPE_INTR
) || (ks_type
== KSTAT_TYPE_IO
))
500 ASSERT(ks_ndata
== 1);
502 ksp
= kmem_zalloc(sizeof (*ksp
), KM_SLEEP
);
506 mutex_enter(&kstat_module_lock
);
507 ksp
->ks_kid
= kstat_id
;
509 mutex_exit(&kstat_module_lock
);
511 ksp
->ks_magic
= KS_MAGIC
;
512 mutex_init(&ksp
->ks_private_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
513 ksp
->ks_lock
= &ksp
->ks_private_lock
;
515 ksp
->ks_crtime
= gethrtime();
516 ksp
->ks_snaptime
= ksp
->ks_crtime
;
517 ksp
->ks_instance
= ks_instance
;
518 strlcpy(ksp
->ks_class
, ks_class
, sizeof (ksp
->ks_class
));
519 ksp
->ks_type
= ks_type
;
520 ksp
->ks_flags
= ks_flags
;
521 ksp
->ks_update
= kstat_default_update
;
522 ksp
->ks_private
= NULL
;
523 ksp
->ks_raw_ops
.headers
= NULL
;
524 ksp
->ks_raw_ops
.data
= NULL
;
525 ksp
->ks_raw_ops
.addr
= NULL
;
526 ksp
->ks_raw_buf
= NULL
;
527 ksp
->ks_raw_bufsize
= 0;
528 kstat_proc_entry_init(&ksp
->ks_proc
, ks_module
, ks_name
);
530 switch (ksp
->ks_type
) {
533 ksp
->ks_data_size
= ks_ndata
;
535 case KSTAT_TYPE_NAMED
:
536 ksp
->ks_ndata
= ks_ndata
;
537 ksp
->ks_data_size
= ks_ndata
* sizeof (kstat_named_t
);
539 case KSTAT_TYPE_INTR
:
540 ksp
->ks_ndata
= ks_ndata
;
541 ksp
->ks_data_size
= ks_ndata
* sizeof (kstat_intr_t
);
544 ksp
->ks_ndata
= ks_ndata
;
545 ksp
->ks_data_size
= ks_ndata
* sizeof (kstat_io_t
);
547 case KSTAT_TYPE_TIMER
:
548 ksp
->ks_ndata
= ks_ndata
;
549 ksp
->ks_data_size
= ks_ndata
* sizeof (kstat_timer_t
);
552 PANIC("Undefined kstat type %d\n", ksp
->ks_type
);
555 if (ksp
->ks_flags
& KSTAT_FLAG_VIRTUAL
) {
558 ksp
->ks_data
= kmem_zalloc(ksp
->ks_data_size
, KM_SLEEP
);
559 if (ksp
->ks_data
== NULL
) {
560 kmem_free(ksp
, sizeof (*ksp
));
567 EXPORT_SYMBOL(__kstat_create
);
570 kstat_detect_collision(kstat_proc_entry_t
*kpep
)
572 kstat_module_t
*module
;
573 kstat_proc_entry_t
*tmp
= NULL
;
577 parent
= kmem_asprintf("%s", kpep
->kpe_module
);
579 if ((cp
= strrchr(parent
, '/')) == NULL
) {
580 kmem_strfree(parent
);
585 if ((module
= kstat_find_module(parent
)) != NULL
) {
586 list_for_each_entry(tmp
, &module
->ksm_kstat_list
, kpe_list
) {
587 if (strncmp(tmp
->kpe_name
, cp
+1, KSTAT_STRLEN
) == 0) {
588 kmem_strfree(parent
);
594 kmem_strfree(parent
);
599 * Add a file to the proc filesystem under the kstat namespace (i.e.
600 * /proc/spl/kstat/). The file need not necessarily be implemented as a
604 kstat_proc_entry_install(kstat_proc_entry_t
*kpep
, mode_t mode
,
605 const kstat_proc_op_t
*proc_ops
, void *data
)
607 kstat_module_t
*module
;
608 kstat_proc_entry_t
*tmp
= NULL
;
612 mutex_enter(&kstat_module_lock
);
614 module
= kstat_find_module(kpep
->kpe_module
);
615 if (module
== NULL
) {
616 if (kstat_detect_collision(kpep
) != 0) {
617 cmn_err(CE_WARN
, "kstat_create('%s', '%s'): namespace" \
618 " collision", kpep
->kpe_module
, kpep
->kpe_name
);
621 module
= kstat_create_module(kpep
->kpe_module
);
627 * Only one entry by this name per-module, on failure the module
628 * shouldn't be deleted because we know it has at least one entry.
630 list_for_each_entry(tmp
, &module
->ksm_kstat_list
, kpe_list
) {
631 if (strncmp(tmp
->kpe_name
, kpep
->kpe_name
, KSTAT_STRLEN
) == 0)
635 list_add_tail(&kpep
->kpe_list
, &module
->ksm_kstat_list
);
637 kpep
->kpe_owner
= module
;
638 kpep
->kpe_proc
= proc_create_data(kpep
->kpe_name
, mode
,
639 module
->ksm_proc
, proc_ops
, data
);
640 if (kpep
->kpe_proc
== NULL
) {
641 list_del_init(&kpep
->kpe_list
);
642 if (list_empty(&module
->ksm_kstat_list
))
643 kstat_delete_module(module
);
646 mutex_exit(&kstat_module_lock
);
649 EXPORT_SYMBOL(kstat_proc_entry_install
);
652 __kstat_install(kstat_t
*ksp
)
656 /* Specify permission modes for different kstats */
657 if (strncmp(ksp
->ks_proc
.kpe_name
, "dbufs", KSTAT_STRLEN
) == 0) {
662 kstat_proc_entry_install(
663 &ksp
->ks_proc
, mode
, &proc_kstat_operations
, ksp
);
665 EXPORT_SYMBOL(__kstat_install
);
668 kstat_proc_entry_delete(kstat_proc_entry_t
*kpep
)
670 kstat_module_t
*module
= kpep
->kpe_owner
;
672 remove_proc_entry(kpep
->kpe_name
, module
->ksm_proc
);
674 mutex_enter(&kstat_module_lock
);
675 list_del_init(&kpep
->kpe_list
);
678 * Remove top level module directory if it wasn't empty before, but now
681 if (kpep
->kpe_proc
&& list_empty(&module
->ksm_kstat_list
))
682 kstat_delete_module(module
);
683 mutex_exit(&kstat_module_lock
);
686 EXPORT_SYMBOL(kstat_proc_entry_delete
);
689 __kstat_delete(kstat_t
*ksp
)
691 kstat_proc_entry_delete(&ksp
->ks_proc
);
693 if (!(ksp
->ks_flags
& KSTAT_FLAG_VIRTUAL
))
694 kmem_free(ksp
->ks_data
, ksp
->ks_data_size
);
697 mutex_destroy(&ksp
->ks_private_lock
);
698 kmem_free(ksp
, sizeof (*ksp
));
700 EXPORT_SYMBOL(__kstat_delete
);
705 mutex_init(&kstat_module_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
706 INIT_LIST_HEAD(&kstat_module_list
);
714 ASSERT(list_empty(&kstat_module_list
));
715 mutex_destroy(&kstat_module_lock
);