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