]> git.proxmox.com Git - mirror_spl.git/blob - module/spl/spl-kstat.c
Rename modules to module and update references
[mirror_spl.git] / module / spl / spl-kstat.c
1 /*
2 * This file is part of the SPL: Solaris Porting Layer.
3 *
4 * Copyright (c) 2008 Lawrence Livermore National Security, LLC.
5 * Produced at Lawrence Livermore National Laboratory
6 * Written by:
7 * Brian Behlendorf <behlendorf1@llnl.gov>,
8 * Herb Wartens <wartens2@llnl.gov>,
9 * Jim Garlick <garlick@llnl.gov>
10 * UCRL-CODE-235197
11 *
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.
16 *
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
20 * for more details.
21 *
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.
25 */
26
27 #include <sys/kstat.h>
28
29 #ifdef DEBUG_KSTAT
30
31 static spinlock_t kstat_lock;
32 static struct list_head kstat_list;
33 static kid_t kstat_id;
34
35 static void
36 kstat_seq_show_headers(struct seq_file *f)
37 {
38 kstat_t *ksp = (kstat_t *)f->private;
39 ASSERT(ksp->ks_magic == KS_MAGIC);
40
41 seq_printf(f, "%d %d 0x%02x %d %d %lld %lld\n",
42 ksp->ks_kid, ksp->ks_type, ksp->ks_flags,
43 ksp->ks_ndata, (int)ksp->ks_data_size,
44 ksp->ks_crtime, ksp->ks_snaptime);
45
46 switch (ksp->ks_type) {
47 case KSTAT_TYPE_RAW:
48 seq_printf(f, "raw data");
49 break;
50 case KSTAT_TYPE_NAMED:
51 seq_printf(f, "%-31s %-4s %s\n",
52 "name", "type", "data");
53 break;
54 case KSTAT_TYPE_INTR:
55 seq_printf(f, "%-8s %-8s %-8s %-8s %-8s\n",
56 "hard", "soft", "watchdog",
57 "spurious", "multsvc");
58 break;
59 case KSTAT_TYPE_IO:
60 seq_printf(f,
61 "%-8s %-8s %-8s %-8s %-8s %-8s "
62 "%-8s %-8s %-8s %-8s %-8s %-8s\n",
63 "nread", "nwritten", "reads", "writes",
64 "wtime", "wlentime", "wupdate",
65 "rtime", "rlentime", "rupdate",
66 "wcnt", "rcnt");
67 break;
68 case KSTAT_TYPE_TIMER:
69 seq_printf(f,
70 "%-31s %-8s "
71 "%-8s %-8s %-8s %-8s %-8s\n",
72 "name", "events", "elapsed",
73 "min", "max", "start", "stop");
74 break;
75 default:
76 SBUG(); /* Unreachable */
77 }
78 }
79
80 static int
81 kstat_seq_show_raw(struct seq_file *f, unsigned char *p, int l)
82 {
83 int i, j;
84
85 for (i = 0; ; i++) {
86 seq_printf(f, "%03x:", i);
87
88 for (j = 0; j < 16; j++) {
89 if (i * 16 + j >= l) {
90 seq_printf(f, "\n");
91 goto out;
92 }
93
94 seq_printf(f, " %02x", (unsigned char)p[i * 16 + j]);
95 }
96 seq_printf(f, "\n");
97 }
98 out:
99 return 0;
100 }
101
102 static int
103 kstat_seq_show_named(struct seq_file *f, kstat_named_t *knp)
104 {
105 seq_printf(f, "%-31s %-4d ", knp->name, knp->data_type);
106
107 switch (knp->data_type) {
108 case KSTAT_DATA_CHAR:
109 knp->value.c[15] = '\0'; /* NULL terminate */
110 seq_printf(f, "%-16s", knp->value.c);
111 break;
112 /* XXX - We need to be more careful able what tokens are
113 * used for each arch, for now this is correct for x86_64.
114 */
115 case KSTAT_DATA_INT32:
116 seq_printf(f, "%d", knp->value.i32);
117 break;
118 case KSTAT_DATA_UINT32:
119 seq_printf(f, "%u", knp->value.ui32);
120 break;
121 case KSTAT_DATA_INT64:
122 seq_printf(f, "%lld", (signed long long)knp->value.i64);
123 break;
124 case KSTAT_DATA_UINT64:
125 seq_printf(f, "%llu", (unsigned long long)knp->value.ui64);
126 break;
127 case KSTAT_DATA_LONG:
128 seq_printf(f, "%ld", knp->value.l);
129 break;
130 case KSTAT_DATA_ULONG:
131 seq_printf(f, "%lu", knp->value.ul);
132 break;
133 case KSTAT_DATA_STRING:
134 KSTAT_NAMED_STR_PTR(knp)
135 [KSTAT_NAMED_STR_BUFLEN(knp)-1] = '\0';
136 seq_printf(f, "%s", KSTAT_NAMED_STR_PTR(knp));
137 break;
138 default:
139 SBUG(); /* Unreachable */
140 }
141
142 seq_printf(f, "\n");
143
144 return 0;
145 }
146
147 static int
148 kstat_seq_show_intr(struct seq_file *f, kstat_intr_t *kip)
149 {
150 seq_printf(f, "%-8u %-8u %-8u %-8u %-8u\n",
151 kip->intrs[KSTAT_INTR_HARD],
152 kip->intrs[KSTAT_INTR_SOFT],
153 kip->intrs[KSTAT_INTR_WATCHDOG],
154 kip->intrs[KSTAT_INTR_SPURIOUS],
155 kip->intrs[KSTAT_INTR_MULTSVC]);
156
157 return 0;
158 }
159
160 static int
161 kstat_seq_show_io(struct seq_file *f, kstat_io_t *kip)
162 {
163 seq_printf(f,
164 "%-8llu %-8llu %-8u %-8u %-8lld %-8lld "
165 "%-8lld %-8lld %-8lld %-8lld %-8u %-8u\n",
166 kip->nread, kip->nwritten,
167 kip->reads, kip->writes,
168 kip->wtime, kip->wlentime, kip->wlastupdate,
169 kip->rtime, kip->wlentime, kip->rlastupdate,
170 kip->wcnt, kip->rcnt);
171
172 return 0;
173 }
174
175 static int
176 kstat_seq_show_timer(struct seq_file *f, kstat_timer_t *ktp)
177 {
178 seq_printf(f,
179 "%-31s %-8llu %-8lld %-8lld %-8lld %-8lld %-8lld\n",
180 ktp->name, ktp->num_events, ktp->elapsed_time,
181 ktp->min_time, ktp->max_time,
182 ktp->start_time, ktp->stop_time);
183
184 return 0;
185 }
186
187 static int
188 kstat_seq_show(struct seq_file *f, void *p)
189 {
190 kstat_t *ksp = (kstat_t *)f->private;
191 int rc = 0;
192
193 ASSERT(ksp->ks_magic == KS_MAGIC);
194
195 switch (ksp->ks_type) {
196 case KSTAT_TYPE_RAW:
197 ASSERT(ksp->ks_ndata == 1);
198 rc = kstat_seq_show_raw(f, ksp->ks_data,
199 ksp->ks_data_size);
200 break;
201 case KSTAT_TYPE_NAMED:
202 rc = kstat_seq_show_named(f, (kstat_named_t *)p);
203 break;
204 case KSTAT_TYPE_INTR:
205 rc = kstat_seq_show_intr(f, (kstat_intr_t *)p);
206 break;
207 case KSTAT_TYPE_IO:
208 rc = kstat_seq_show_io(f, (kstat_io_t *)p);
209 break;
210 case KSTAT_TYPE_TIMER:
211 rc = kstat_seq_show_timer(f, (kstat_timer_t *)p);
212 break;
213 default:
214 SBUG(); /* Unreachable */
215 }
216
217 return rc;
218 }
219
220 static void *
221 kstat_seq_data_addr(kstat_t *ksp, loff_t n)
222 {
223 void *rc = NULL;
224 ENTRY;
225
226 switch (ksp->ks_type) {
227 case KSTAT_TYPE_RAW:
228 rc = ksp->ks_data;
229 break;
230 case KSTAT_TYPE_NAMED:
231 rc = ksp->ks_data + n * sizeof(kstat_named_t);
232 break;
233 case KSTAT_TYPE_INTR:
234 rc = ksp->ks_data + n * sizeof(kstat_intr_t);
235 break;
236 case KSTAT_TYPE_IO:
237 rc = ksp->ks_data + n * sizeof(kstat_io_t);
238 break;
239 case KSTAT_TYPE_TIMER:
240 rc = ksp->ks_data + n * sizeof(kstat_timer_t);
241 break;
242 default:
243 SBUG(); /* Unreachable */
244 }
245
246 RETURN(rc);
247 }
248
249 static void *
250 kstat_seq_start(struct seq_file *f, loff_t *pos)
251 {
252 loff_t n = *pos;
253 kstat_t *ksp = (kstat_t *)f->private;
254 ASSERT(ksp->ks_magic == KS_MAGIC);
255 ENTRY;
256
257 spin_lock(&ksp->ks_lock);
258 ksp->ks_snaptime = gethrtime();
259
260 if (!n)
261 kstat_seq_show_headers(f);
262
263 if (n >= ksp->ks_ndata)
264 RETURN(NULL);
265
266 RETURN(kstat_seq_data_addr(ksp, n));
267 }
268
269 static void *
270 kstat_seq_next(struct seq_file *f, void *p, loff_t *pos)
271 {
272 kstat_t *ksp = (kstat_t *)f->private;
273 ASSERT(ksp->ks_magic == KS_MAGIC);
274 ENTRY;
275
276 ++*pos;
277 if (*pos >= ksp->ks_ndata)
278 RETURN(NULL);
279
280 RETURN(kstat_seq_data_addr(ksp, *pos));
281 }
282
283 static void
284 kstat_seq_stop(struct seq_file *f, void *v)
285 {
286 kstat_t *ksp = (kstat_t *)f->private;
287 ASSERT(ksp->ks_magic == KS_MAGIC);
288
289 spin_unlock(&ksp->ks_lock);
290 }
291
292 static struct seq_operations kstat_seq_ops = {
293 .show = kstat_seq_show,
294 .start = kstat_seq_start,
295 .next = kstat_seq_next,
296 .stop = kstat_seq_stop,
297 };
298
299 static int
300 proc_kstat_open(struct inode *inode, struct file *filp)
301 {
302 struct seq_file *f;
303 int rc;
304
305 rc = seq_open(filp, &kstat_seq_ops);
306 if (rc)
307 return rc;
308
309 f = filp->private_data;
310 f->private = PDE(inode)->data;
311
312 return rc;
313 }
314
315 static struct file_operations proc_kstat_operations = {
316 .open = proc_kstat_open,
317 .read = seq_read,
318 .llseek = seq_lseek,
319 .release = seq_release,
320 };
321
322 kstat_t *
323 __kstat_create(const char *ks_module, int ks_instance, const char *ks_name,
324 const char *ks_class, uchar_t ks_type, uint_t ks_ndata,
325 uchar_t ks_flags)
326 {
327 kstat_t *ksp;
328
329 ASSERT(ks_module);
330 ASSERT(ks_instance == 0);
331 ASSERT(ks_name);
332 ASSERT(!(ks_flags & KSTAT_FLAG_UNSUPPORTED));
333
334 if ((ks_type == KSTAT_TYPE_INTR) || (ks_type == KSTAT_TYPE_IO))
335 ASSERT(ks_ndata == 1);
336
337 ksp = kmem_zalloc(sizeof(*ksp), KM_SLEEP);
338 if (ksp == NULL)
339 return ksp;
340
341 spin_lock(&kstat_lock);
342 ksp->ks_kid = kstat_id;
343 kstat_id++;
344 spin_unlock(&kstat_lock);
345
346 ksp->ks_magic = KS_MAGIC;
347 spin_lock_init(&ksp->ks_lock);
348 INIT_LIST_HEAD(&ksp->ks_list);
349
350 ksp->ks_crtime = gethrtime();
351 ksp->ks_snaptime = ksp->ks_crtime;
352 strncpy(ksp->ks_module, ks_module, KSTAT_STRLEN);
353 ksp->ks_instance = ks_instance;
354 strncpy(ksp->ks_name, ks_name, KSTAT_STRLEN);
355 strncpy(ksp->ks_class, ks_class, KSTAT_STRLEN);
356 ksp->ks_type = ks_type;
357 ksp->ks_flags = ks_flags;
358
359 switch (ksp->ks_type) {
360 case KSTAT_TYPE_RAW:
361 ksp->ks_ndata = 1;
362 ksp->ks_data_size = ks_ndata;
363 break;
364 case KSTAT_TYPE_NAMED:
365 ksp->ks_ndata = ks_ndata;
366 ksp->ks_data_size = ks_ndata * sizeof(kstat_named_t);
367 break;
368 case KSTAT_TYPE_INTR:
369 ksp->ks_ndata = ks_ndata;
370 ksp->ks_data_size = ks_ndata * sizeof(kstat_intr_t);
371 break;
372 case KSTAT_TYPE_IO:
373 ksp->ks_ndata = ks_ndata;
374 ksp->ks_data_size = ks_ndata * sizeof(kstat_io_t);
375 break;
376 case KSTAT_TYPE_TIMER:
377 ksp->ks_ndata = ks_ndata;
378 ksp->ks_data_size = ks_ndata * sizeof(kstat_timer_t);
379 break;
380 default:
381 SBUG(); /* Unreachable */
382 }
383
384 if (ksp->ks_flags & KSTAT_FLAG_VIRTUAL) {
385 ksp->ks_data = NULL;
386 } else {
387 ksp->ks_data = kmem_alloc(ksp->ks_data_size, KM_SLEEP);
388 if (ksp->ks_data == NULL) {
389 kmem_free(ksp, sizeof(*ksp));
390 ksp = NULL;
391 }
392 }
393
394 return ksp;
395 }
396 EXPORT_SYMBOL(__kstat_create);
397
398 void
399 __kstat_install(kstat_t *ksp)
400 {
401 struct proc_dir_entry *de_module, *de_name;
402 kstat_t *tmp;
403 int rc = 0;
404 ENTRY;
405
406 spin_lock(&kstat_lock);
407
408 /* Item may only be added to the list once */
409 list_for_each_entry(tmp, &kstat_list, ks_list) {
410 if (tmp == ksp) {
411 spin_unlock(&kstat_lock);
412 GOTO(out, rc = -EEXIST);
413 }
414 }
415
416 list_add_tail(&ksp->ks_list, &kstat_list);
417 spin_unlock(&kstat_lock);
418
419 de_module = proc_dir_entry_find(proc_spl_kstat, ksp->ks_module);
420 if (de_module == NULL) {
421 de_module = proc_mkdir(ksp->ks_module, proc_spl_kstat);
422 if (de_module == NULL)
423 GOTO(out, rc = -EUNATCH);
424 }
425
426 de_name = create_proc_entry(ksp->ks_name, 0444, de_module);
427 if (de_name == NULL)
428 GOTO(out, rc = -EUNATCH);
429
430 spin_lock(&ksp->ks_lock);
431 ksp->ks_proc = de_name;
432 de_name->proc_fops = &proc_kstat_operations;
433 de_name->data = (void *)ksp;
434 spin_unlock(&ksp->ks_lock);
435 out:
436 if (rc) {
437 spin_lock(&kstat_lock);
438 list_del_init(&ksp->ks_list);
439 spin_unlock(&kstat_lock);
440 }
441
442 EXIT;
443 }
444 EXPORT_SYMBOL(__kstat_install);
445
446 void
447 __kstat_delete(kstat_t *ksp)
448 {
449 struct proc_dir_entry *de_module;
450
451 spin_lock(&kstat_lock);
452 list_del_init(&ksp->ks_list);
453 spin_unlock(&kstat_lock);
454
455 if (ksp->ks_proc) {
456 de_module = ksp->ks_proc->parent;
457 remove_proc_entry(ksp->ks_name, de_module);
458
459 /* Remove top level module directory if it's empty */
460 if (proc_dir_entries(de_module) == 0)
461 remove_proc_entry(de_module->name, de_module->parent);
462 }
463
464 if (!(ksp->ks_flags & KSTAT_FLAG_VIRTUAL))
465 kmem_free(ksp->ks_data, ksp->ks_data_size);
466
467 kmem_free(ksp, sizeof(*ksp));
468
469 return;
470 }
471 EXPORT_SYMBOL(__kstat_delete);
472
473 #endif /* DEBUG_KSTAT */
474
475 int
476 kstat_init(void)
477 {
478 ENTRY;
479 #ifdef DEBUG_KSTAT
480 spin_lock_init(&kstat_lock);
481 INIT_LIST_HEAD(&kstat_list);
482 kstat_id = 0;
483 #endif /* DEBUG_KSTAT */
484 RETURN(0);
485 }
486
487 void
488 kstat_fini(void)
489 {
490 ENTRY;
491 #ifdef DEBUG_KSTAT
492 ASSERT(list_empty(&kstat_list));
493 #endif /* DEBUG_KSTAT */
494 EXIT;
495 }
496