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://github.com/behlendorf/spl/>.
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 <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));