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>.
8 * This file is part of the SPL, Solaris Porting Layer.
9 * For details, see <http://zfsonlinux.org/>.
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.
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
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) Kstat Implementation.
25 \*****************************************************************************/
27 #include <linux/seq_file.h>
28 #include <sys/kstat.h>
31 #define PDE_DATA(x) (PDE(x)->data)
34 static kmutex_t kstat_module_lock
;
35 static struct list_head kstat_module_list
;
36 static kid_t kstat_id
;
39 kstat_resize_raw(kstat_t
*ksp
)
41 if (ksp
->ks_raw_bufsize
== KSTAT_RAW_MAX
)
44 vmem_free(ksp
->ks_raw_buf
, ksp
->ks_raw_bufsize
);
45 ksp
->ks_raw_bufsize
= MIN(ksp
->ks_raw_bufsize
* 2, KSTAT_RAW_MAX
);
46 ksp
->ks_raw_buf
= vmem_alloc(ksp
->ks_raw_bufsize
, KM_SLEEP
);
52 kstat_waitq_enter(kstat_io_t
*kiop
)
58 delta
= new - kiop
->wlastupdate
;
59 kiop
->wlastupdate
= new;
62 kiop
->wlentime
+= delta
* wcnt
;
66 EXPORT_SYMBOL(kstat_waitq_enter
);
69 kstat_waitq_exit(kstat_io_t
*kiop
)
75 delta
= new - kiop
->wlastupdate
;
76 kiop
->wlastupdate
= new;
78 ASSERT((int)wcnt
> 0);
79 kiop
->wlentime
+= delta
* wcnt
;
82 EXPORT_SYMBOL(kstat_waitq_exit
);
85 kstat_runq_enter(kstat_io_t
*kiop
)
91 delta
= new - kiop
->rlastupdate
;
92 kiop
->rlastupdate
= new;
95 kiop
->rlentime
+= delta
* rcnt
;
99 EXPORT_SYMBOL(kstat_runq_enter
);
102 kstat_runq_exit(kstat_io_t
*kiop
)
108 delta
= new - kiop
->rlastupdate
;
109 kiop
->rlastupdate
= new;
111 ASSERT((int)rcnt
> 0);
112 kiop
->rlentime
+= delta
* rcnt
;
113 kiop
->rtime
+= delta
;
115 EXPORT_SYMBOL(kstat_runq_exit
);
118 kstat_seq_show_headers(struct seq_file
*f
)
120 kstat_t
*ksp
= (kstat_t
*)f
->private;
123 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
125 seq_printf(f
, "%d %d 0x%02x %d %d %lld %lld\n",
126 ksp
->ks_kid
, ksp
->ks_type
, ksp
->ks_flags
,
127 ksp
->ks_ndata
, (int)ksp
->ks_data_size
,
128 ksp
->ks_crtime
, ksp
->ks_snaptime
);
130 switch (ksp
->ks_type
) {
133 if (ksp
->ks_raw_ops
.headers
) {
134 rc
= ksp
->ks_raw_ops
.headers(
135 ksp
->ks_raw_buf
, ksp
->ks_raw_bufsize
);
136 if (rc
== ENOMEM
&& !kstat_resize_raw(ksp
))
139 seq_puts(f
, ksp
->ks_raw_buf
);
141 seq_printf(f
, "raw data\n");
144 case KSTAT_TYPE_NAMED
:
145 seq_printf(f
, "%-31s %-4s %s\n",
146 "name", "type", "data");
148 case KSTAT_TYPE_INTR
:
149 seq_printf(f
, "%-8s %-8s %-8s %-8s %-8s\n",
150 "hard", "soft", "watchdog",
151 "spurious", "multsvc");
155 "%-8s %-8s %-8s %-8s %-8s %-8s "
156 "%-8s %-8s %-8s %-8s %-8s %-8s\n",
157 "nread", "nwritten", "reads", "writes",
158 "wtime", "wlentime", "wupdate",
159 "rtime", "rlentime", "rupdate",
162 case KSTAT_TYPE_TIMER
:
165 "%-8s %-8s %-8s %-8s %-8s\n",
166 "name", "events", "elapsed",
167 "min", "max", "start", "stop");
170 PANIC("Undefined kstat type %d\n", ksp
->ks_type
);
177 kstat_seq_show_raw(struct seq_file
*f
, unsigned char *p
, int l
)
182 seq_printf(f
, "%03x:", i
);
184 for (j
= 0; j
< 16; j
++) {
185 if (i
* 16 + j
>= l
) {
190 seq_printf(f
, " %02x", (unsigned char)p
[i
* 16 + j
]);
199 kstat_seq_show_named(struct seq_file
*f
, kstat_named_t
*knp
)
201 seq_printf(f
, "%-31s %-4d ", knp
->name
, knp
->data_type
);
203 switch (knp
->data_type
) {
204 case KSTAT_DATA_CHAR
:
205 knp
->value
.c
[15] = '\0'; /* NULL terminate */
206 seq_printf(f
, "%-16s", knp
->value
.c
);
208 /* XXX - We need to be more careful able what tokens are
209 * used for each arch, for now this is correct for x86_64.
211 case KSTAT_DATA_INT32
:
212 seq_printf(f
, "%d", knp
->value
.i32
);
214 case KSTAT_DATA_UINT32
:
215 seq_printf(f
, "%u", knp
->value
.ui32
);
217 case KSTAT_DATA_INT64
:
218 seq_printf(f
, "%lld", (signed long long)knp
->value
.i64
);
220 case KSTAT_DATA_UINT64
:
221 seq_printf(f
, "%llu", (unsigned long long)knp
->value
.ui64
);
223 case KSTAT_DATA_LONG
:
224 seq_printf(f
, "%ld", knp
->value
.l
);
226 case KSTAT_DATA_ULONG
:
227 seq_printf(f
, "%lu", knp
->value
.ul
);
229 case KSTAT_DATA_STRING
:
230 KSTAT_NAMED_STR_PTR(knp
)
231 [KSTAT_NAMED_STR_BUFLEN(knp
)-1] = '\0';
232 seq_printf(f
, "%s", KSTAT_NAMED_STR_PTR(knp
));
235 PANIC("Undefined kstat data type %d\n", knp
->data_type
);
244 kstat_seq_show_intr(struct seq_file
*f
, kstat_intr_t
*kip
)
246 seq_printf(f
, "%-8u %-8u %-8u %-8u %-8u\n",
247 kip
->intrs
[KSTAT_INTR_HARD
],
248 kip
->intrs
[KSTAT_INTR_SOFT
],
249 kip
->intrs
[KSTAT_INTR_WATCHDOG
],
250 kip
->intrs
[KSTAT_INTR_SPURIOUS
],
251 kip
->intrs
[KSTAT_INTR_MULTSVC
]);
257 kstat_seq_show_io(struct seq_file
*f
, kstat_io_t
*kip
)
260 "%-8llu %-8llu %-8u %-8u %-8lld %-8lld "
261 "%-8lld %-8lld %-8lld %-8lld %-8u %-8u\n",
262 kip
->nread
, kip
->nwritten
,
263 kip
->reads
, kip
->writes
,
264 kip
->wtime
, kip
->wlentime
, kip
->wlastupdate
,
265 kip
->rtime
, kip
->wlentime
, kip
->rlastupdate
,
266 kip
->wcnt
, kip
->rcnt
);
272 kstat_seq_show_timer(struct seq_file
*f
, kstat_timer_t
*ktp
)
275 "%-31s %-8llu %-8lld %-8lld %-8lld %-8lld %-8lld\n",
276 ktp
->name
, ktp
->num_events
, ktp
->elapsed_time
,
277 ktp
->min_time
, ktp
->max_time
,
278 ktp
->start_time
, ktp
->stop_time
);
284 kstat_seq_show(struct seq_file
*f
, void *p
)
286 kstat_t
*ksp
= (kstat_t
*)f
->private;
289 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
291 switch (ksp
->ks_type
) {
294 if (ksp
->ks_raw_ops
.data
) {
295 rc
= ksp
->ks_raw_ops
.data(
296 ksp
->ks_raw_buf
, ksp
->ks_raw_bufsize
, p
);
297 if (rc
== ENOMEM
&& !kstat_resize_raw(ksp
))
300 seq_puts(f
, ksp
->ks_raw_buf
);
302 ASSERT(ksp
->ks_ndata
== 1);
303 rc
= kstat_seq_show_raw(f
, ksp
->ks_data
,
307 case KSTAT_TYPE_NAMED
:
308 rc
= kstat_seq_show_named(f
, (kstat_named_t
*)p
);
310 case KSTAT_TYPE_INTR
:
311 rc
= kstat_seq_show_intr(f
, (kstat_intr_t
*)p
);
314 rc
= kstat_seq_show_io(f
, (kstat_io_t
*)p
);
316 case KSTAT_TYPE_TIMER
:
317 rc
= kstat_seq_show_timer(f
, (kstat_timer_t
*)p
);
320 PANIC("Undefined kstat type %d\n", ksp
->ks_type
);
327 kstat_default_update(kstat_t
*ksp
, int rw
)
331 if (rw
== KSTAT_WRITE
)
338 kstat_seq_data_addr(kstat_t
*ksp
, loff_t n
)
342 switch (ksp
->ks_type
) {
344 if (ksp
->ks_raw_ops
.addr
)
345 rc
= ksp
->ks_raw_ops
.addr(ksp
, n
);
349 case KSTAT_TYPE_NAMED
:
350 rc
= ksp
->ks_data
+ n
* sizeof(kstat_named_t
);
352 case KSTAT_TYPE_INTR
:
353 rc
= ksp
->ks_data
+ n
* sizeof(kstat_intr_t
);
356 rc
= ksp
->ks_data
+ n
* sizeof(kstat_io_t
);
358 case KSTAT_TYPE_TIMER
:
359 rc
= ksp
->ks_data
+ n
* sizeof(kstat_timer_t
);
362 PANIC("Undefined kstat type %d\n", ksp
->ks_type
);
369 kstat_seq_start(struct seq_file
*f
, loff_t
*pos
)
372 kstat_t
*ksp
= (kstat_t
*)f
->private;
373 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
375 mutex_enter(ksp
->ks_lock
);
377 if (ksp
->ks_type
== KSTAT_TYPE_RAW
) {
378 ksp
->ks_raw_bufsize
= PAGE_SIZE
;
379 ksp
->ks_raw_buf
= vmem_alloc(ksp
->ks_raw_bufsize
, KM_SLEEP
);
382 /* Dynamically update kstat, on error existing kstats are used */
383 (void) ksp
->ks_update(ksp
, KSTAT_READ
);
385 ksp
->ks_snaptime
= gethrtime();
387 if (!n
&& kstat_seq_show_headers(f
))
390 if (n
>= ksp
->ks_ndata
)
393 return (kstat_seq_data_addr(ksp
, n
));
397 kstat_seq_next(struct seq_file
*f
, void *p
, loff_t
*pos
)
399 kstat_t
*ksp
= (kstat_t
*)f
->private;
400 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
403 if (*pos
>= ksp
->ks_ndata
)
406 return (kstat_seq_data_addr(ksp
, *pos
));
410 kstat_seq_stop(struct seq_file
*f
, void *v
)
412 kstat_t
*ksp
= (kstat_t
*)f
->private;
413 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
415 if (ksp
->ks_type
== KSTAT_TYPE_RAW
)
416 vmem_free(ksp
->ks_raw_buf
, ksp
->ks_raw_bufsize
);
418 mutex_exit(ksp
->ks_lock
);
421 static struct seq_operations kstat_seq_ops
= {
422 .show
= kstat_seq_show
,
423 .start
= kstat_seq_start
,
424 .next
= kstat_seq_next
,
425 .stop
= kstat_seq_stop
,
428 static kstat_module_t
*
429 kstat_find_module(char *name
)
431 kstat_module_t
*module
;
433 list_for_each_entry(module
, &kstat_module_list
, ksm_module_list
)
434 if (strncmp(name
, module
->ksm_name
, KSTAT_STRLEN
) == 0)
440 static kstat_module_t
*
441 kstat_create_module(char *name
)
443 kstat_module_t
*module
;
444 struct proc_dir_entry
*pde
;
446 pde
= proc_mkdir(name
, proc_spl_kstat
);
450 module
= kmem_alloc(sizeof (kstat_module_t
), KM_SLEEP
);
451 module
->ksm_proc
= pde
;
452 strlcpy(module
->ksm_name
, name
, KSTAT_STRLEN
+1);
453 INIT_LIST_HEAD(&module
->ksm_kstat_list
);
454 list_add_tail(&module
->ksm_module_list
, &kstat_module_list
);
461 kstat_delete_module(kstat_module_t
*module
)
463 ASSERT(list_empty(&module
->ksm_kstat_list
));
464 remove_proc_entry(module
->ksm_name
, proc_spl_kstat
);
465 list_del(&module
->ksm_module_list
);
466 kmem_free(module
, sizeof(kstat_module_t
));
470 proc_kstat_open(struct inode
*inode
, struct file
*filp
)
475 rc
= seq_open(filp
, &kstat_seq_ops
);
479 f
= filp
->private_data
;
480 f
->private = PDE_DATA(inode
);
486 proc_kstat_write(struct file
*filp
, const char __user
*buf
,
487 size_t len
, loff_t
*ppos
)
489 struct seq_file
*f
= filp
->private_data
;
490 kstat_t
*ksp
= f
->private;
493 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
495 mutex_enter(ksp
->ks_lock
);
496 rc
= ksp
->ks_update(ksp
, KSTAT_WRITE
);
497 mutex_exit(ksp
->ks_lock
);
506 static struct file_operations proc_kstat_operations
= {
507 .open
= proc_kstat_open
,
508 .write
= proc_kstat_write
,
511 .release
= seq_release
,
515 __kstat_set_raw_ops(kstat_t
*ksp
,
516 int (*headers
)(char *buf
, size_t size
),
517 int (*data
)(char *buf
, size_t size
, void *data
),
518 void *(*addr
)(kstat_t
*ksp
, loff_t index
))
520 ksp
->ks_raw_ops
.headers
= headers
;
521 ksp
->ks_raw_ops
.data
= data
;
522 ksp
->ks_raw_ops
.addr
= addr
;
524 EXPORT_SYMBOL(__kstat_set_raw_ops
);
527 __kstat_create(const char *ks_module
, int ks_instance
, const char *ks_name
,
528 const char *ks_class
, uchar_t ks_type
, uint_t ks_ndata
,
534 ASSERT(ks_instance
== 0);
536 ASSERT(!(ks_flags
& KSTAT_FLAG_UNSUPPORTED
));
538 if ((ks_type
== KSTAT_TYPE_INTR
) || (ks_type
== KSTAT_TYPE_IO
))
539 ASSERT(ks_ndata
== 1);
541 ksp
= kmem_zalloc(sizeof(*ksp
), KM_SLEEP
);
545 mutex_enter(&kstat_module_lock
);
546 ksp
->ks_kid
= kstat_id
;
548 mutex_exit(&kstat_module_lock
);
550 ksp
->ks_magic
= KS_MAGIC
;
551 mutex_init(&ksp
->ks_private_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
552 ksp
->ks_lock
= &ksp
->ks_private_lock
;
553 INIT_LIST_HEAD(&ksp
->ks_list
);
555 ksp
->ks_crtime
= gethrtime();
556 ksp
->ks_snaptime
= ksp
->ks_crtime
;
557 strncpy(ksp
->ks_module
, ks_module
, KSTAT_STRLEN
);
558 ksp
->ks_instance
= ks_instance
;
559 strncpy(ksp
->ks_name
, ks_name
, KSTAT_STRLEN
);
560 strncpy(ksp
->ks_class
, ks_class
, KSTAT_STRLEN
);
561 ksp
->ks_type
= ks_type
;
562 ksp
->ks_flags
= ks_flags
;
563 ksp
->ks_update
= kstat_default_update
;
564 ksp
->ks_private
= NULL
;
565 ksp
->ks_raw_ops
.headers
= NULL
;
566 ksp
->ks_raw_ops
.data
= NULL
;
567 ksp
->ks_raw_ops
.addr
= NULL
;
568 ksp
->ks_raw_buf
= NULL
;
569 ksp
->ks_raw_bufsize
= 0;
571 switch (ksp
->ks_type
) {
574 ksp
->ks_data_size
= ks_ndata
;
576 case KSTAT_TYPE_NAMED
:
577 ksp
->ks_ndata
= ks_ndata
;
578 ksp
->ks_data_size
= ks_ndata
* sizeof(kstat_named_t
);
580 case KSTAT_TYPE_INTR
:
581 ksp
->ks_ndata
= ks_ndata
;
582 ksp
->ks_data_size
= ks_ndata
* sizeof(kstat_intr_t
);
585 ksp
->ks_ndata
= ks_ndata
;
586 ksp
->ks_data_size
= ks_ndata
* sizeof(kstat_io_t
);
588 case KSTAT_TYPE_TIMER
:
589 ksp
->ks_ndata
= ks_ndata
;
590 ksp
->ks_data_size
= ks_ndata
* sizeof(kstat_timer_t
);
593 PANIC("Undefined kstat type %d\n", ksp
->ks_type
);
596 if (ksp
->ks_flags
& KSTAT_FLAG_VIRTUAL
) {
599 ksp
->ks_data
= kmem_zalloc(ksp
->ks_data_size
, KM_SLEEP
);
600 if (ksp
->ks_data
== NULL
) {
601 kmem_free(ksp
, sizeof(*ksp
));
608 EXPORT_SYMBOL(__kstat_create
);
611 __kstat_install(kstat_t
*ksp
)
613 kstat_module_t
*module
;
618 mutex_enter(&kstat_module_lock
);
620 module
= kstat_find_module(ksp
->ks_module
);
621 if (module
== NULL
) {
622 module
= kstat_create_module(ksp
->ks_module
);
628 * Only one entry by this name per-module, on failure the module
629 * shouldn't be deleted because we know it has at least one entry.
631 list_for_each_entry(tmp
, &module
->ksm_kstat_list
, ks_list
)
632 if (strncmp(tmp
->ks_name
, ksp
->ks_name
, KSTAT_STRLEN
) == 0)
635 list_add_tail(&ksp
->ks_list
, &module
->ksm_kstat_list
);
637 mutex_enter(ksp
->ks_lock
);
638 ksp
->ks_owner
= module
;
639 ksp
->ks_proc
= proc_create_data(ksp
->ks_name
, 0644,
640 module
->ksm_proc
, &proc_kstat_operations
, (void *)ksp
);
641 if (ksp
->ks_proc
== NULL
) {
642 list_del_init(&ksp
->ks_list
);
643 if (list_empty(&module
->ksm_kstat_list
))
644 kstat_delete_module(module
);
646 mutex_exit(ksp
->ks_lock
);
648 mutex_exit(&kstat_module_lock
);
650 EXPORT_SYMBOL(__kstat_install
);
653 __kstat_delete(kstat_t
*ksp
)
655 kstat_module_t
*module
= ksp
->ks_owner
;
657 mutex_enter(&kstat_module_lock
);
658 list_del_init(&ksp
->ks_list
);
659 mutex_exit(&kstat_module_lock
);
662 remove_proc_entry(ksp
->ks_name
, module
->ksm_proc
);
664 /* Remove top level module directory if it's empty */
665 if (list_empty(&module
->ksm_kstat_list
))
666 kstat_delete_module(module
);
669 if (!(ksp
->ks_flags
& KSTAT_FLAG_VIRTUAL
))
670 kmem_free(ksp
->ks_data
, ksp
->ks_data_size
);
673 mutex_destroy(&ksp
->ks_private_lock
);
674 kmem_free(ksp
, sizeof(*ksp
));
678 EXPORT_SYMBOL(__kstat_delete
);
683 mutex_init(&kstat_module_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
684 INIT_LIST_HEAD(&kstat_module_list
);
692 ASSERT(list_empty(&kstat_module_list
));
693 mutex_destroy(&kstat_module_lock
);