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