2 * This file is part of the SPL: Solaris Porting Layer.
4 * Copyright (c) 2008 Lawrence Livermore National Security, LLC.
5 * Produced at Lawrence Livermore National Laboratory
7 * Brian Behlendorf <behlendorf1@llnl.gov>,
8 * Herb Wartens <wartens2@llnl.gov>,
9 * Jim Garlick <garlick@llnl.gov>
12 * This is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <sys/kstat.h>
29 static spinlock_t kstat_lock
;
30 static struct list_head kstat_list
;
31 static kid_t kstat_id
;
34 kstat_seq_show_headers(struct seq_file
*f
)
36 kstat_t
*ksp
= (kstat_t
*)f
->private;
37 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
39 seq_printf(f
, "%d %d 0x%02x %d %d %lld %lld\n",
40 ksp
->ks_kid
, ksp
->ks_type
, ksp
->ks_flags
,
41 ksp
->ks_ndata
, (int)ksp
->ks_data_size
,
42 ksp
->ks_crtime
, ksp
->ks_snaptime
);
44 switch (ksp
->ks_type
) {
46 seq_printf(f
, "raw data");
48 case KSTAT_TYPE_NAMED
:
49 seq_printf(f
, "%-31s %-4s %s\n",
50 "name", "type", "data");
53 seq_printf(f
, "%-8s %-8s %-8s %-8s %-8s\n",
54 "hard", "soft", "watchdog",
55 "spurious", "multsvc");
59 "%-8s %-8s %-8s %-8s %-8s %-8s "
60 "%-8s %-8s %-8s %-8s %-8s %-8s\n",
61 "nread", "nwritten", "reads", "writes",
62 "wtime", "wlentime", "wupdate",
63 "rtime", "rlentime", "rupdate",
66 case KSTAT_TYPE_TIMER
:
69 "%-8s %-8s %-8s %-8s %-8s\n",
70 "name", "events", "elapsed",
71 "min", "max", "start", "stop");
74 SBUG(); /* Unreachable */
79 kstat_seq_show_raw(struct seq_file
*f
, unsigned char *p
, int l
)
84 seq_printf(f
, "%03x:", i
);
86 for (j
= 0; j
< 16; j
++) {
87 if (i
* 16 + j
>= l
) {
92 seq_printf(f
, " %02x", (unsigned char)p
[i
* 16 + j
]);
101 kstat_seq_show_named(struct seq_file
*f
, kstat_named_t
*knp
)
103 seq_printf(f
, "%-31s %-4d ", knp
->name
, knp
->data_type
);
105 switch (knp
->data_type
) {
106 case KSTAT_DATA_CHAR
:
107 knp
->value
.c
[15] = '\0'; /* NULL terminate */
108 seq_printf(f
, "%-16s", knp
->value
.c
);
110 /* XXX - We need to be more careful able what tokens are
111 * used for each arch, for now this is correct for x86_64.
113 case KSTAT_DATA_INT32
:
114 seq_printf(f
, "%d", knp
->value
.i32
);
116 case KSTAT_DATA_UINT32
:
117 seq_printf(f
, "%u", knp
->value
.ui32
);
119 case KSTAT_DATA_INT64
:
120 seq_printf(f
, "%lld", (signed long long)knp
->value
.i64
);
122 case KSTAT_DATA_UINT64
:
123 seq_printf(f
, "%llu", (unsigned long long)knp
->value
.ui64
);
125 case KSTAT_DATA_LONG
:
126 seq_printf(f
, "%ld", knp
->value
.l
);
128 case KSTAT_DATA_ULONG
:
129 seq_printf(f
, "%lu", knp
->value
.ul
);
131 case KSTAT_DATA_STRING
:
132 KSTAT_NAMED_STR_PTR(knp
)
133 [KSTAT_NAMED_STR_BUFLEN(knp
)-1] = '\0';
134 seq_printf(f
, "%s", KSTAT_NAMED_STR_PTR(knp
));
137 SBUG(); /* Unreachable */
146 kstat_seq_show_intr(struct seq_file
*f
, kstat_intr_t
*kip
)
148 seq_printf(f
, "%-8u %-8u %-8u %-8u %-8u\n",
149 kip
->intrs
[KSTAT_INTR_HARD
],
150 kip
->intrs
[KSTAT_INTR_SOFT
],
151 kip
->intrs
[KSTAT_INTR_WATCHDOG
],
152 kip
->intrs
[KSTAT_INTR_SPURIOUS
],
153 kip
->intrs
[KSTAT_INTR_MULTSVC
]);
159 kstat_seq_show_io(struct seq_file
*f
, kstat_io_t
*kip
)
162 "%-8llu %-8llu %-8u %-8u %-8lld %-8lld "
163 "%-8lld %-8lld %-8lld %-8lld %-8u %-8u\n",
164 kip
->nread
, kip
->nwritten
,
165 kip
->reads
, kip
->writes
,
166 kip
->wtime
, kip
->wlentime
, kip
->wlastupdate
,
167 kip
->rtime
, kip
->wlentime
, kip
->rlastupdate
,
168 kip
->wcnt
, kip
->rcnt
);
174 kstat_seq_show_timer(struct seq_file
*f
, kstat_timer_t
*ktp
)
177 "%-31s %-8llu %-8lld %-8lld %-8lld %-8lld %-8lld\n",
178 ktp
->name
, ktp
->num_events
, ktp
->elapsed_time
,
179 ktp
->min_time
, ktp
->max_time
,
180 ktp
->start_time
, ktp
->stop_time
);
186 kstat_seq_show(struct seq_file
*f
, void *p
)
188 kstat_t
*ksp
= (kstat_t
*)f
->private;
191 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
193 switch (ksp
->ks_type
) {
195 ASSERT(ksp
->ks_ndata
== 1);
196 rc
= kstat_seq_show_raw(f
, ksp
->ks_data
,
199 case KSTAT_TYPE_NAMED
:
200 rc
= kstat_seq_show_named(f
, (kstat_named_t
*)p
);
202 case KSTAT_TYPE_INTR
:
203 rc
= kstat_seq_show_intr(f
, (kstat_intr_t
*)p
);
206 rc
= kstat_seq_show_io(f
, (kstat_io_t
*)p
);
208 case KSTAT_TYPE_TIMER
:
209 rc
= kstat_seq_show_timer(f
, (kstat_timer_t
*)p
);
212 SBUG(); /* Unreachable */
219 kstat_seq_data_addr(kstat_t
*ksp
, loff_t n
)
224 switch (ksp
->ks_type
) {
228 case KSTAT_TYPE_NAMED
:
229 rc
= ksp
->ks_data
+ n
* sizeof(kstat_named_t
);
231 case KSTAT_TYPE_INTR
:
232 rc
= ksp
->ks_data
+ n
* sizeof(kstat_intr_t
);
235 rc
= ksp
->ks_data
+ n
* sizeof(kstat_io_t
);
237 case KSTAT_TYPE_TIMER
:
238 rc
= ksp
->ks_data
+ n
* sizeof(kstat_timer_t
);
241 SBUG(); /* Unreachable */
248 kstat_seq_start(struct seq_file
*f
, loff_t
*pos
)
251 kstat_t
*ksp
= (kstat_t
*)f
->private;
252 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
255 spin_lock(&ksp
->ks_lock
);
256 ksp
->ks_snaptime
= gethrtime();
259 kstat_seq_show_headers(f
);
261 if (n
>= ksp
->ks_ndata
)
264 RETURN(kstat_seq_data_addr(ksp
, n
));
268 kstat_seq_next(struct seq_file
*f
, void *p
, loff_t
*pos
)
270 kstat_t
*ksp
= (kstat_t
*)f
->private;
271 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
275 if (*pos
>= ksp
->ks_ndata
)
278 RETURN(kstat_seq_data_addr(ksp
, *pos
));
282 kstat_seq_stop(struct seq_file
*f
, void *v
)
284 kstat_t
*ksp
= (kstat_t
*)f
->private;
285 ASSERT(ksp
->ks_magic
== KS_MAGIC
);
287 spin_unlock(&ksp
->ks_lock
);
290 static struct seq_operations kstat_seq_ops
= {
291 .show
= kstat_seq_show
,
292 .start
= kstat_seq_start
,
293 .next
= kstat_seq_next
,
294 .stop
= kstat_seq_stop
,
298 proc_kstat_open(struct inode
*inode
, struct file
*filp
)
303 rc
= seq_open(filp
, &kstat_seq_ops
);
307 f
= filp
->private_data
;
308 f
->private = PDE(inode
)->data
;
313 static struct file_operations proc_kstat_operations
= {
314 .open
= proc_kstat_open
,
317 .release
= seq_release
,
321 __kstat_create(const char *ks_module
, int ks_instance
, const char *ks_name
,
322 const char *ks_class
, uchar_t ks_type
, uint_t ks_ndata
,
328 ASSERT(ks_instance
== 0);
330 ASSERT(!(ks_flags
& KSTAT_FLAG_UNSUPPORTED
));
332 if ((ks_type
== KSTAT_TYPE_INTR
) || (ks_type
== KSTAT_TYPE_IO
))
333 ASSERT(ks_ndata
== 1);
335 ksp
= kmem_zalloc(sizeof(*ksp
), KM_SLEEP
);
339 spin_lock(&kstat_lock
);
340 ksp
->ks_kid
= kstat_id
;
342 spin_unlock(&kstat_lock
);
344 ksp
->ks_magic
= KS_MAGIC
;
345 spin_lock_init(&ksp
->ks_lock
);
346 INIT_LIST_HEAD(&ksp
->ks_list
);
348 ksp
->ks_crtime
= gethrtime();
349 ksp
->ks_snaptime
= ksp
->ks_crtime
;
350 strncpy(ksp
->ks_module
, ks_module
, KSTAT_STRLEN
);
351 ksp
->ks_instance
= ks_instance
;
352 strncpy(ksp
->ks_name
, ks_name
, KSTAT_STRLEN
);
353 strncpy(ksp
->ks_class
, ks_class
, KSTAT_STRLEN
);
354 ksp
->ks_type
= ks_type
;
355 ksp
->ks_flags
= ks_flags
;
357 switch (ksp
->ks_type
) {
360 ksp
->ks_data_size
= ks_ndata
;
362 case KSTAT_TYPE_NAMED
:
363 ksp
->ks_ndata
= ks_ndata
;
364 ksp
->ks_data_size
= ks_ndata
* sizeof(kstat_named_t
);
366 case KSTAT_TYPE_INTR
:
367 ksp
->ks_ndata
= ks_ndata
;
368 ksp
->ks_data_size
= ks_ndata
* sizeof(kstat_intr_t
);
371 ksp
->ks_ndata
= ks_ndata
;
372 ksp
->ks_data_size
= ks_ndata
* sizeof(kstat_io_t
);
374 case KSTAT_TYPE_TIMER
:
375 ksp
->ks_ndata
= ks_ndata
;
376 ksp
->ks_data_size
= ks_ndata
* sizeof(kstat_timer_t
);
379 SBUG(); /* Unreachable */
382 if (ksp
->ks_flags
& KSTAT_FLAG_VIRTUAL
) {
385 ksp
->ks_data
= kmem_alloc(ksp
->ks_data_size
, KM_SLEEP
);
386 if (ksp
->ks_data
== NULL
) {
387 kmem_free(ksp
, sizeof(*ksp
));
394 EXPORT_SYMBOL(__kstat_create
);
397 __kstat_install(kstat_t
*ksp
)
399 struct proc_dir_entry
*de_module
, *de_name
;
404 spin_lock(&kstat_lock
);
406 /* Item may only be added to the list once */
407 list_for_each_entry(tmp
, &kstat_list
, ks_list
) {
409 spin_unlock(&kstat_lock
);
410 GOTO(out
, rc
= -EEXIST
);
414 list_add_tail(&ksp
->ks_list
, &kstat_list
);
415 spin_unlock(&kstat_lock
);
417 de_module
= proc_dir_entry_find(proc_spl_kstat
, ksp
->ks_module
);
418 if (de_module
== NULL
) {
419 de_module
= proc_mkdir(ksp
->ks_module
, proc_spl_kstat
);
420 if (de_module
== NULL
)
421 GOTO(out
, rc
= -EUNATCH
);
424 de_name
= create_proc_entry(ksp
->ks_name
, 0444, de_module
);
426 GOTO(out
, rc
= -EUNATCH
);
428 spin_lock(&ksp
->ks_lock
);
429 ksp
->ks_proc
= de_name
;
430 de_name
->proc_fops
= &proc_kstat_operations
;
431 de_name
->data
= (void *)ksp
;
432 spin_unlock(&ksp
->ks_lock
);
435 spin_lock(&kstat_lock
);
436 list_del_init(&ksp
->ks_list
);
437 spin_unlock(&kstat_lock
);
442 EXPORT_SYMBOL(__kstat_install
);
445 __kstat_delete(kstat_t
*ksp
)
447 struct proc_dir_entry
*de_module
;
449 spin_lock(&kstat_lock
);
450 list_del_init(&ksp
->ks_list
);
451 spin_unlock(&kstat_lock
);
454 de_module
= ksp
->ks_proc
->parent
;
455 remove_proc_entry(ksp
->ks_name
, de_module
);
457 /* Remove top level module directory if it's empty */
458 if (proc_dir_entries(de_module
) == 0)
459 remove_proc_entry(de_module
->name
, de_module
->parent
);
462 if (!(ksp
->ks_flags
& KSTAT_FLAG_VIRTUAL
))
463 kmem_free(ksp
->ks_data
, ksp
->ks_data_size
);
465 kmem_free(ksp
, sizeof(*ksp
));
469 EXPORT_SYMBOL(__kstat_delete
);
475 spin_lock_init(&kstat_lock
);
476 INIT_LIST_HEAD(&kstat_list
);
485 ASSERT(list_empty(&kstat_list
));