xref: /freebsd/sys/contrib/openzfs/module/os/linux/spl/spl-kstat.c (revision c6989859ae9388eeb46a24fe88f9b8d07101c710)
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>.
6  *  UCRL-CODE-235197
7  *
8  *  This file is part of the SPL, Solaris Porting Layer.
9  *  For details, see <http://zfsonlinux.org/>.
10  *
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.
15  *
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
19  *  for more details.
20  *
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  *
26  *  Links to Illumos.org for more information on kstat function:
27  *  [1] https://illumos.org/man/1M/kstat
28  *  [2] https://illumos.org/man/9f/kstat_create
29  */
30 
31 #include <linux/seq_file.h>
32 #include <sys/kstat.h>
33 #include <sys/vmem.h>
34 #include <sys/cmn_err.h>
35 #include <sys/sysmacros.h>
36 
37 static kmutex_t kstat_module_lock;
38 static struct list_head kstat_module_list;
39 static kid_t kstat_id;
40 
41 static int
42 kstat_resize_raw(kstat_t *ksp)
43 {
44 	if (ksp->ks_raw_bufsize == KSTAT_RAW_MAX)
45 		return (ENOMEM);
46 
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);
50 
51 	return (0);
52 }
53 
54 void
55 kstat_waitq_enter(kstat_io_t *kiop)
56 {
57 	hrtime_t new, delta;
58 	ulong_t wcnt;
59 
60 	new = gethrtime();
61 	delta = new - kiop->wlastupdate;
62 	kiop->wlastupdate = new;
63 	wcnt = kiop->wcnt++;
64 	if (wcnt != 0) {
65 		kiop->wlentime += delta * wcnt;
66 		kiop->wtime += delta;
67 	}
68 }
69 EXPORT_SYMBOL(kstat_waitq_enter);
70 
71 void
72 kstat_waitq_exit(kstat_io_t *kiop)
73 {
74 	hrtime_t new, delta;
75 	ulong_t wcnt;
76 
77 	new = gethrtime();
78 	delta = new - kiop->wlastupdate;
79 	kiop->wlastupdate = new;
80 	wcnt = kiop->wcnt--;
81 	ASSERT((int)wcnt > 0);
82 	kiop->wlentime += delta * wcnt;
83 	kiop->wtime += delta;
84 }
85 EXPORT_SYMBOL(kstat_waitq_exit);
86 
87 void
88 kstat_runq_enter(kstat_io_t *kiop)
89 {
90 	hrtime_t new, delta;
91 	ulong_t rcnt;
92 
93 	new = gethrtime();
94 	delta = new - kiop->rlastupdate;
95 	kiop->rlastupdate = new;
96 	rcnt = kiop->rcnt++;
97 	if (rcnt != 0) {
98 		kiop->rlentime += delta * rcnt;
99 		kiop->rtime += delta;
100 	}
101 }
102 EXPORT_SYMBOL(kstat_runq_enter);
103 
104 void
105 kstat_runq_exit(kstat_io_t *kiop)
106 {
107 	hrtime_t new, delta;
108 	ulong_t rcnt;
109 
110 	new = gethrtime();
111 	delta = new - kiop->rlastupdate;
112 	kiop->rlastupdate = new;
113 	rcnt = kiop->rcnt--;
114 	ASSERT((int)rcnt > 0);
115 	kiop->rlentime += delta * rcnt;
116 	kiop->rtime += delta;
117 }
118 EXPORT_SYMBOL(kstat_runq_exit);
119 
120 static int
121 kstat_seq_show_headers(struct seq_file *f)
122 {
123 	kstat_t *ksp = (kstat_t *)f->private;
124 	int rc = 0;
125 
126 	ASSERT(ksp->ks_magic == KS_MAGIC);
127 
128 	seq_printf(f, "%d %d 0x%02x %d %d %lld %lld\n",
129 	    ksp->ks_kid, ksp->ks_type, ksp->ks_flags,
130 	    ksp->ks_ndata, (int)ksp->ks_data_size,
131 	    ksp->ks_crtime, ksp->ks_snaptime);
132 
133 	switch (ksp->ks_type) {
134 		case KSTAT_TYPE_RAW:
135 restart:
136 			if (ksp->ks_raw_ops.headers) {
137 				rc = ksp->ks_raw_ops.headers(
138 				    ksp->ks_raw_buf, ksp->ks_raw_bufsize);
139 				if (rc == ENOMEM && !kstat_resize_raw(ksp))
140 					goto restart;
141 				if (!rc)
142 					seq_puts(f, ksp->ks_raw_buf);
143 			} else {
144 				seq_printf(f, "raw data\n");
145 			}
146 			break;
147 		case KSTAT_TYPE_NAMED:
148 			seq_printf(f, "%-31s %-4s %s\n",
149 			    "name", "type", "data");
150 			break;
151 		case KSTAT_TYPE_INTR:
152 			seq_printf(f, "%-8s %-8s %-8s %-8s %-8s\n",
153 			    "hard", "soft", "watchdog",
154 			    "spurious", "multsvc");
155 			break;
156 		case KSTAT_TYPE_IO:
157 			seq_printf(f,
158 			    "%-8s %-8s %-8s %-8s %-8s %-8s "
159 			    "%-8s %-8s %-8s %-8s %-8s %-8s\n",
160 			    "nread", "nwritten", "reads", "writes",
161 			    "wtime", "wlentime", "wupdate",
162 			    "rtime", "rlentime", "rupdate",
163 			    "wcnt", "rcnt");
164 			break;
165 		case KSTAT_TYPE_TIMER:
166 			seq_printf(f,
167 			    "%-31s %-8s "
168 			    "%-8s %-8s %-8s %-8s %-8s\n",
169 			    "name", "events", "elapsed",
170 			    "min", "max", "start", "stop");
171 			break;
172 		default:
173 			PANIC("Undefined kstat type %d\n", ksp->ks_type);
174 	}
175 
176 	return (-rc);
177 }
178 
179 static int
180 kstat_seq_show_raw(struct seq_file *f, unsigned char *p, int l)
181 {
182 	int i, j;
183 
184 	for (i = 0; ; i++) {
185 		seq_printf(f, "%03x:", i);
186 
187 		for (j = 0; j < 16; j++) {
188 			if (i * 16 + j >= l) {
189 				seq_printf(f, "\n");
190 				goto out;
191 			}
192 
193 			seq_printf(f, " %02x", (unsigned char)p[i * 16 + j]);
194 		}
195 		seq_printf(f, "\n");
196 	}
197 out:
198 	return (0);
199 }
200 
201 static int
202 kstat_seq_show_named(struct seq_file *f, kstat_named_t *knp)
203 {
204 	seq_printf(f, "%-31s %-4d ", knp->name, knp->data_type);
205 
206 	switch (knp->data_type) {
207 		case KSTAT_DATA_CHAR:
208 			knp->value.c[15] = '\0'; /* NULL terminate */
209 			seq_printf(f, "%-16s", knp->value.c);
210 			break;
211 		/*
212 		 * NOTE - We need to be more careful able what tokens are
213 		 * used for each arch, for now this is correct for x86_64.
214 		 */
215 		case KSTAT_DATA_INT32:
216 			seq_printf(f, "%d", knp->value.i32);
217 			break;
218 		case KSTAT_DATA_UINT32:
219 			seq_printf(f, "%u", knp->value.ui32);
220 			break;
221 		case KSTAT_DATA_INT64:
222 			seq_printf(f, "%lld", (signed long long)knp->value.i64);
223 			break;
224 		case KSTAT_DATA_UINT64:
225 			seq_printf(f, "%llu",
226 			    (unsigned long long)knp->value.ui64);
227 			break;
228 		case KSTAT_DATA_LONG:
229 			seq_printf(f, "%ld", knp->value.l);
230 			break;
231 		case KSTAT_DATA_ULONG:
232 			seq_printf(f, "%lu", knp->value.ul);
233 			break;
234 		case KSTAT_DATA_STRING:
235 			KSTAT_NAMED_STR_PTR(knp)
236 				[KSTAT_NAMED_STR_BUFLEN(knp)-1] = '\0';
237 			seq_printf(f, "%s", KSTAT_NAMED_STR_PTR(knp));
238 			break;
239 		default:
240 			PANIC("Undefined kstat data type %d\n", knp->data_type);
241 	}
242 
243 	seq_printf(f, "\n");
244 
245 	return (0);
246 }
247 
248 static int
249 kstat_seq_show_intr(struct seq_file *f, kstat_intr_t *kip)
250 {
251 	seq_printf(f, "%-8u %-8u %-8u %-8u %-8u\n",
252 	    kip->intrs[KSTAT_INTR_HARD],
253 	    kip->intrs[KSTAT_INTR_SOFT],
254 	    kip->intrs[KSTAT_INTR_WATCHDOG],
255 	    kip->intrs[KSTAT_INTR_SPURIOUS],
256 	    kip->intrs[KSTAT_INTR_MULTSVC]);
257 
258 	return (0);
259 }
260 
261 static int
262 kstat_seq_show_io(struct seq_file *f, kstat_io_t *kip)
263 {
264 	/* though wlentime & friends are signed, they will never be negative */
265 	seq_printf(f,
266 	    "%-8llu %-8llu %-8u %-8u %-8llu %-8llu "
267 	    "%-8llu %-8llu %-8llu %-8llu %-8u %-8u\n",
268 	    kip->nread, kip->nwritten,
269 	    kip->reads, kip->writes,
270 	    kip->wtime, kip->wlentime, kip->wlastupdate,
271 	    kip->rtime, kip->rlentime, kip->rlastupdate,
272 	    kip->wcnt,  kip->rcnt);
273 
274 	return (0);
275 }
276 
277 static int
278 kstat_seq_show_timer(struct seq_file *f, kstat_timer_t *ktp)
279 {
280 	seq_printf(f,
281 	    "%-31s %-8llu %-8llu %-8llu %-8llu %-8llu %-8llu\n",
282 	    ktp->name, ktp->num_events, ktp->elapsed_time,
283 	    ktp->min_time, ktp->max_time,
284 	    ktp->start_time, ktp->stop_time);
285 
286 	return (0);
287 }
288 
289 static int
290 kstat_seq_show(struct seq_file *f, void *p)
291 {
292 	kstat_t *ksp = (kstat_t *)f->private;
293 	int rc = 0;
294 
295 	ASSERT(ksp->ks_magic == KS_MAGIC);
296 
297 	switch (ksp->ks_type) {
298 		case KSTAT_TYPE_RAW:
299 restart:
300 			if (ksp->ks_raw_ops.data) {
301 				rc = ksp->ks_raw_ops.data(
302 				    ksp->ks_raw_buf, ksp->ks_raw_bufsize, p);
303 				if (rc == ENOMEM && !kstat_resize_raw(ksp))
304 					goto restart;
305 				if (!rc)
306 					seq_puts(f, ksp->ks_raw_buf);
307 			} else {
308 				ASSERT(ksp->ks_ndata == 1);
309 				rc = kstat_seq_show_raw(f, ksp->ks_data,
310 				    ksp->ks_data_size);
311 			}
312 			break;
313 		case KSTAT_TYPE_NAMED:
314 			rc = kstat_seq_show_named(f, (kstat_named_t *)p);
315 			break;
316 		case KSTAT_TYPE_INTR:
317 			rc = kstat_seq_show_intr(f, (kstat_intr_t *)p);
318 			break;
319 		case KSTAT_TYPE_IO:
320 			rc = kstat_seq_show_io(f, (kstat_io_t *)p);
321 			break;
322 		case KSTAT_TYPE_TIMER:
323 			rc = kstat_seq_show_timer(f, (kstat_timer_t *)p);
324 			break;
325 		default:
326 			PANIC("Undefined kstat type %d\n", ksp->ks_type);
327 	}
328 
329 	return (-rc);
330 }
331 
332 static int
333 kstat_default_update(kstat_t *ksp, int rw)
334 {
335 	ASSERT(ksp != NULL);
336 
337 	if (rw == KSTAT_WRITE)
338 		return (EACCES);
339 
340 	return (0);
341 }
342 
343 static void *
344 kstat_seq_data_addr(kstat_t *ksp, loff_t n)
345 {
346 	void *rc = NULL;
347 
348 	switch (ksp->ks_type) {
349 		case KSTAT_TYPE_RAW:
350 			if (ksp->ks_raw_ops.addr)
351 				rc = ksp->ks_raw_ops.addr(ksp, n);
352 			else
353 				rc = ksp->ks_data;
354 			break;
355 		case KSTAT_TYPE_NAMED:
356 			rc = ksp->ks_data + n * sizeof (kstat_named_t);
357 			break;
358 		case KSTAT_TYPE_INTR:
359 			rc = ksp->ks_data + n * sizeof (kstat_intr_t);
360 			break;
361 		case KSTAT_TYPE_IO:
362 			rc = ksp->ks_data + n * sizeof (kstat_io_t);
363 			break;
364 		case KSTAT_TYPE_TIMER:
365 			rc = ksp->ks_data + n * sizeof (kstat_timer_t);
366 			break;
367 		default:
368 			PANIC("Undefined kstat type %d\n", ksp->ks_type);
369 	}
370 
371 	return (rc);
372 }
373 
374 static void *
375 kstat_seq_start(struct seq_file *f, loff_t *pos)
376 {
377 	loff_t n = *pos;
378 	kstat_t *ksp = (kstat_t *)f->private;
379 	ASSERT(ksp->ks_magic == KS_MAGIC);
380 
381 	mutex_enter(ksp->ks_lock);
382 
383 	if (ksp->ks_type == KSTAT_TYPE_RAW) {
384 		ksp->ks_raw_bufsize = PAGE_SIZE;
385 		ksp->ks_raw_buf = vmem_alloc(ksp->ks_raw_bufsize, KM_SLEEP);
386 	}
387 
388 	/* Dynamically update kstat, on error existing kstats are used */
389 	(void) ksp->ks_update(ksp, KSTAT_READ);
390 
391 	ksp->ks_snaptime = gethrtime();
392 
393 	if (!(ksp->ks_flags & KSTAT_FLAG_NO_HEADERS) && !n &&
394 	    kstat_seq_show_headers(f))
395 		return (NULL);
396 
397 	if (n >= ksp->ks_ndata)
398 		return (NULL);
399 
400 	return (kstat_seq_data_addr(ksp, n));
401 }
402 
403 static void *
404 kstat_seq_next(struct seq_file *f, void *p, loff_t *pos)
405 {
406 	kstat_t *ksp = (kstat_t *)f->private;
407 	ASSERT(ksp->ks_magic == KS_MAGIC);
408 
409 	++*pos;
410 	if (*pos >= ksp->ks_ndata)
411 		return (NULL);
412 
413 	return (kstat_seq_data_addr(ksp, *pos));
414 }
415 
416 static void
417 kstat_seq_stop(struct seq_file *f, void *v)
418 {
419 	kstat_t *ksp = (kstat_t *)f->private;
420 	ASSERT(ksp->ks_magic == KS_MAGIC);
421 
422 	if (ksp->ks_type == KSTAT_TYPE_RAW)
423 		vmem_free(ksp->ks_raw_buf, ksp->ks_raw_bufsize);
424 
425 	mutex_exit(ksp->ks_lock);
426 }
427 
428 static struct seq_operations kstat_seq_ops = {
429 	.show  = kstat_seq_show,
430 	.start = kstat_seq_start,
431 	.next  = kstat_seq_next,
432 	.stop  = kstat_seq_stop,
433 };
434 
435 static kstat_module_t *
436 kstat_find_module(char *name)
437 {
438 	kstat_module_t *module = NULL;
439 
440 	list_for_each_entry(module, &kstat_module_list, ksm_module_list) {
441 		if (strncmp(name, module->ksm_name, KSTAT_STRLEN) == 0)
442 			return (module);
443 	}
444 
445 	return (NULL);
446 }
447 
448 static kstat_module_t *
449 kstat_create_module(char *name)
450 {
451 	kstat_module_t *module;
452 	struct proc_dir_entry *pde;
453 
454 	pde = proc_mkdir(name, proc_spl_kstat);
455 	if (pde == NULL)
456 		return (NULL);
457 
458 	module = kmem_alloc(sizeof (kstat_module_t), KM_SLEEP);
459 	module->ksm_proc = pde;
460 	strlcpy(module->ksm_name, name, KSTAT_STRLEN+1);
461 	INIT_LIST_HEAD(&module->ksm_kstat_list);
462 	list_add_tail(&module->ksm_module_list, &kstat_module_list);
463 
464 	return (module);
465 
466 }
467 
468 static void
469 kstat_delete_module(kstat_module_t *module)
470 {
471 	ASSERT(list_empty(&module->ksm_kstat_list));
472 	remove_proc_entry(module->ksm_name, proc_spl_kstat);
473 	list_del(&module->ksm_module_list);
474 	kmem_free(module, sizeof (kstat_module_t));
475 }
476 
477 static int
478 proc_kstat_open(struct inode *inode, struct file *filp)
479 {
480 	struct seq_file *f;
481 	int rc;
482 
483 	rc = seq_open(filp, &kstat_seq_ops);
484 	if (rc)
485 		return (rc);
486 
487 	f = filp->private_data;
488 	f->private = PDE_DATA(inode);
489 
490 	return (rc);
491 }
492 
493 static ssize_t
494 proc_kstat_write(struct file *filp, const char __user *buf, size_t len,
495     loff_t *ppos)
496 {
497 	struct seq_file *f = filp->private_data;
498 	kstat_t *ksp = f->private;
499 	int rc;
500 
501 	ASSERT(ksp->ks_magic == KS_MAGIC);
502 
503 	mutex_enter(ksp->ks_lock);
504 	rc = ksp->ks_update(ksp, KSTAT_WRITE);
505 	mutex_exit(ksp->ks_lock);
506 
507 	if (rc)
508 		return (-rc);
509 
510 	*ppos += len;
511 	return (len);
512 }
513 
514 static const kstat_proc_op_t proc_kstat_operations = {
515 #ifdef HAVE_PROC_OPS_STRUCT
516 	.proc_open	= proc_kstat_open,
517 	.proc_write	= proc_kstat_write,
518 	.proc_read	= seq_read,
519 	.proc_lseek	= seq_lseek,
520 	.proc_release	= seq_release,
521 #else
522 	.open		= proc_kstat_open,
523 	.write		= proc_kstat_write,
524 	.read		= seq_read,
525 	.llseek		= seq_lseek,
526 	.release	= seq_release,
527 #endif
528 };
529 
530 void
531 __kstat_set_raw_ops(kstat_t *ksp,
532     int (*headers)(char *buf, size_t size),
533     int (*data)(char *buf, size_t size, void *data),
534     void *(*addr)(kstat_t *ksp, loff_t index))
535 {
536 	ksp->ks_raw_ops.headers = headers;
537 	ksp->ks_raw_ops.data    = data;
538 	ksp->ks_raw_ops.addr    = addr;
539 }
540 EXPORT_SYMBOL(__kstat_set_raw_ops);
541 
542 void
543 kstat_proc_entry_init(kstat_proc_entry_t *kpep, const char *module,
544     const char *name)
545 {
546 	kpep->kpe_owner = NULL;
547 	kpep->kpe_proc = NULL;
548 	INIT_LIST_HEAD(&kpep->kpe_list);
549 	strncpy(kpep->kpe_module, module, KSTAT_STRLEN);
550 	strncpy(kpep->kpe_name, name, KSTAT_STRLEN);
551 }
552 EXPORT_SYMBOL(kstat_proc_entry_init);
553 
554 kstat_t *
555 __kstat_create(const char *ks_module, int ks_instance, const char *ks_name,
556     const char *ks_class, uchar_t ks_type, uint_t ks_ndata,
557     uchar_t ks_flags)
558 {
559 	kstat_t *ksp;
560 
561 	ASSERT(ks_module);
562 	ASSERT(ks_instance == 0);
563 	ASSERT(ks_name);
564 
565 	if ((ks_type == KSTAT_TYPE_INTR) || (ks_type == KSTAT_TYPE_IO))
566 		ASSERT(ks_ndata == 1);
567 
568 	ksp = kmem_zalloc(sizeof (*ksp), KM_SLEEP);
569 	if (ksp == NULL)
570 		return (ksp);
571 
572 	mutex_enter(&kstat_module_lock);
573 	ksp->ks_kid = kstat_id;
574 	kstat_id++;
575 	mutex_exit(&kstat_module_lock);
576 
577 	ksp->ks_magic = KS_MAGIC;
578 	mutex_init(&ksp->ks_private_lock, NULL, MUTEX_DEFAULT, NULL);
579 	ksp->ks_lock = &ksp->ks_private_lock;
580 
581 	ksp->ks_crtime = gethrtime();
582 	ksp->ks_snaptime = ksp->ks_crtime;
583 	ksp->ks_instance = ks_instance;
584 	strncpy(ksp->ks_class, ks_class, KSTAT_STRLEN);
585 	ksp->ks_type = ks_type;
586 	ksp->ks_flags = ks_flags;
587 	ksp->ks_update = kstat_default_update;
588 	ksp->ks_private = NULL;
589 	ksp->ks_raw_ops.headers = NULL;
590 	ksp->ks_raw_ops.data = NULL;
591 	ksp->ks_raw_ops.addr = NULL;
592 	ksp->ks_raw_buf = NULL;
593 	ksp->ks_raw_bufsize = 0;
594 	kstat_proc_entry_init(&ksp->ks_proc, ks_module, ks_name);
595 
596 	switch (ksp->ks_type) {
597 		case KSTAT_TYPE_RAW:
598 			ksp->ks_ndata = 1;
599 			ksp->ks_data_size = ks_ndata;
600 			break;
601 		case KSTAT_TYPE_NAMED:
602 			ksp->ks_ndata = ks_ndata;
603 			ksp->ks_data_size = ks_ndata * sizeof (kstat_named_t);
604 			break;
605 		case KSTAT_TYPE_INTR:
606 			ksp->ks_ndata = ks_ndata;
607 			ksp->ks_data_size = ks_ndata * sizeof (kstat_intr_t);
608 			break;
609 		case KSTAT_TYPE_IO:
610 			ksp->ks_ndata = ks_ndata;
611 			ksp->ks_data_size = ks_ndata * sizeof (kstat_io_t);
612 			break;
613 		case KSTAT_TYPE_TIMER:
614 			ksp->ks_ndata = ks_ndata;
615 			ksp->ks_data_size = ks_ndata * sizeof (kstat_timer_t);
616 			break;
617 		default:
618 			PANIC("Undefined kstat type %d\n", ksp->ks_type);
619 	}
620 
621 	if (ksp->ks_flags & KSTAT_FLAG_VIRTUAL) {
622 		ksp->ks_data = NULL;
623 	} else {
624 		ksp->ks_data = kmem_zalloc(ksp->ks_data_size, KM_SLEEP);
625 		if (ksp->ks_data == NULL) {
626 			kmem_free(ksp, sizeof (*ksp));
627 			ksp = NULL;
628 		}
629 	}
630 
631 	return (ksp);
632 }
633 EXPORT_SYMBOL(__kstat_create);
634 
635 static int
636 kstat_detect_collision(kstat_proc_entry_t *kpep)
637 {
638 	kstat_module_t *module;
639 	kstat_proc_entry_t *tmp = NULL;
640 	char *parent;
641 	char *cp;
642 
643 	parent = kmem_asprintf("%s", kpep->kpe_module);
644 
645 	if ((cp = strrchr(parent, '/')) == NULL) {
646 		kmem_strfree(parent);
647 		return (0);
648 	}
649 
650 	cp[0] = '\0';
651 	if ((module = kstat_find_module(parent)) != NULL) {
652 		list_for_each_entry(tmp, &module->ksm_kstat_list, kpe_list) {
653 			if (strncmp(tmp->kpe_name, cp+1, KSTAT_STRLEN) == 0) {
654 				kmem_strfree(parent);
655 				return (EEXIST);
656 			}
657 		}
658 	}
659 
660 	kmem_strfree(parent);
661 	return (0);
662 }
663 
664 /*
665  * Add a file to the proc filesystem under the kstat namespace (i.e.
666  * /proc/spl/kstat/). The file need not necessarily be implemented as a
667  * kstat.
668  */
669 void
670 kstat_proc_entry_install(kstat_proc_entry_t *kpep, mode_t mode,
671     const kstat_proc_op_t *proc_ops, void *data)
672 {
673 	kstat_module_t *module;
674 	kstat_proc_entry_t *tmp = NULL;
675 
676 	ASSERT(kpep);
677 
678 	mutex_enter(&kstat_module_lock);
679 
680 	module = kstat_find_module(kpep->kpe_module);
681 	if (module == NULL) {
682 		if (kstat_detect_collision(kpep) != 0) {
683 			cmn_err(CE_WARN, "kstat_create('%s', '%s'): namespace" \
684 			    " collision", kpep->kpe_module, kpep->kpe_name);
685 			goto out;
686 		}
687 		module = kstat_create_module(kpep->kpe_module);
688 		if (module == NULL)
689 			goto out;
690 	}
691 
692 	/*
693 	 * Only one entry by this name per-module, on failure the module
694 	 * shouldn't be deleted because we know it has at least one entry.
695 	 */
696 	list_for_each_entry(tmp, &module->ksm_kstat_list, kpe_list) {
697 		if (strncmp(tmp->kpe_name, kpep->kpe_name, KSTAT_STRLEN) == 0)
698 			goto out;
699 	}
700 
701 	list_add_tail(&kpep->kpe_list, &module->ksm_kstat_list);
702 
703 	kpep->kpe_owner = module;
704 	kpep->kpe_proc = proc_create_data(kpep->kpe_name, mode,
705 	    module->ksm_proc, proc_ops, data);
706 	if (kpep->kpe_proc == NULL) {
707 		list_del_init(&kpep->kpe_list);
708 		if (list_empty(&module->ksm_kstat_list))
709 			kstat_delete_module(module);
710 	}
711 out:
712 	mutex_exit(&kstat_module_lock);
713 
714 }
715 EXPORT_SYMBOL(kstat_proc_entry_install);
716 
717 void
718 __kstat_install(kstat_t *ksp)
719 {
720 	ASSERT(ksp);
721 	mode_t mode;
722 	/* Specify permission modes for different kstats */
723 	if (strncmp(ksp->ks_proc.kpe_name, "dbufs", KSTAT_STRLEN) == 0) {
724 		mode = 0600;
725 	} else {
726 		mode = 0644;
727 	}
728 	kstat_proc_entry_install(
729 	    &ksp->ks_proc, mode, &proc_kstat_operations, ksp);
730 }
731 EXPORT_SYMBOL(__kstat_install);
732 
733 void
734 kstat_proc_entry_delete(kstat_proc_entry_t *kpep)
735 {
736 	kstat_module_t *module = kpep->kpe_owner;
737 	if (kpep->kpe_proc)
738 		remove_proc_entry(kpep->kpe_name, module->ksm_proc);
739 
740 	mutex_enter(&kstat_module_lock);
741 	list_del_init(&kpep->kpe_list);
742 
743 	/*
744 	 * Remove top level module directory if it wasn't empty before, but now
745 	 * is.
746 	 */
747 	if (kpep->kpe_proc && list_empty(&module->ksm_kstat_list))
748 		kstat_delete_module(module);
749 	mutex_exit(&kstat_module_lock);
750 
751 }
752 EXPORT_SYMBOL(kstat_proc_entry_delete);
753 
754 void
755 __kstat_delete(kstat_t *ksp)
756 {
757 	kstat_proc_entry_delete(&ksp->ks_proc);
758 
759 	if (!(ksp->ks_flags & KSTAT_FLAG_VIRTUAL))
760 		kmem_free(ksp->ks_data, ksp->ks_data_size);
761 
762 	ksp->ks_lock = NULL;
763 	mutex_destroy(&ksp->ks_private_lock);
764 	kmem_free(ksp, sizeof (*ksp));
765 }
766 EXPORT_SYMBOL(__kstat_delete);
767 
768 int
769 spl_kstat_init(void)
770 {
771 	mutex_init(&kstat_module_lock, NULL, MUTEX_DEFAULT, NULL);
772 	INIT_LIST_HEAD(&kstat_module_list);
773 	kstat_id = 0;
774 	return (0);
775 }
776 
777 void
778 spl_kstat_fini(void)
779 {
780 	ASSERT(list_empty(&kstat_module_list));
781 	mutex_destroy(&kstat_module_lock);
782 }
783