1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright (c) 2012 David Hoeppner. All rights reserved. 25 */ 26 27 /* 28 * Display kernel statistics 29 * 30 * This is a reimplementation of the perl kstat command originally found 31 * under usr/src/cmd/kstat/kstat.pl 32 * 33 * Incompatibilities: 34 * - perl regular expressions not longer supported 35 * - options checking is stricter 36 * 37 * Flags added: 38 * -C similar to the -p option but value is separated by a colon 39 * -h display help 40 * -j json format 41 */ 42 43 #include <assert.h> 44 #include <ctype.h> 45 #include <errno.h> 46 #include <kstat.h> 47 #include <langinfo.h> 48 #include <libgen.h> 49 #include <limits.h> 50 #include <locale.h> 51 #include <signal.h> 52 #include <stddef.h> 53 #include <stdio.h> 54 #include <stdlib.h> 55 #include <string.h> 56 #include <strings.h> 57 #include <time.h> 58 #include <unistd.h> 59 #include <sys/list.h> 60 #include <sys/time.h> 61 #include <sys/types.h> 62 63 #include "kstat.h" 64 #include "statcommon.h" 65 66 char *cmdname = "kstat"; /* Name of this command */ 67 int caught_cont = 0; /* Have caught a SIGCONT */ 68 69 static uint_t g_timestamp_fmt = NODATE; 70 71 /* Helper flag - header was printed already? */ 72 static boolean_t g_headerflg; 73 74 /* Saved command line options */ 75 static boolean_t g_cflg = B_FALSE; 76 static boolean_t g_jflg = B_FALSE; 77 static boolean_t g_lflg = B_FALSE; 78 static boolean_t g_pflg = B_FALSE; 79 static boolean_t g_qflg = B_FALSE; 80 static char *g_ks_class = "*"; 81 82 /* Return zero if a selector did match */ 83 static int g_matched = 1; 84 85 /* Sorted list of kstat instances */ 86 static list_t instances_list; 87 static list_t selector_list; 88 89 int 90 main(int argc, char **argv) 91 { 92 ks_selector_t *nselector; 93 ks_selector_t *uselector; 94 kstat_ctl_t *kc; 95 hrtime_t start_n; 96 hrtime_t period_n; 97 boolean_t errflg = B_FALSE; 98 boolean_t nselflg = B_FALSE; 99 boolean_t uselflg = B_FALSE; 100 char *q; 101 int count = 1; 102 int infinite_cycles = 0; 103 int interval = 0; 104 int n = 0; 105 int c, m, tmp; 106 107 (void) setlocale(LC_ALL, ""); 108 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 109 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 110 #endif 111 (void) textdomain(TEXT_DOMAIN); 112 113 /* 114 * Create the selector list and a dummy default selector to match 115 * everything. While we process the cmdline options we will add 116 * selectors to this list. 117 */ 118 list_create(&selector_list, sizeof (ks_selector_t), 119 offsetof(ks_selector_t, ks_next)); 120 121 nselector = new_selector(); 122 123 /* 124 * Parse named command line arguments. 125 */ 126 while ((c = getopt(argc, argv, "h?CqjlpT:m:i:n:s:c:")) != EOF) 127 switch (c) { 128 case 'h': 129 case '?': 130 usage(); 131 exit(0); 132 break; 133 case 'C': 134 g_pflg = g_cflg = B_TRUE; 135 break; 136 case 'q': 137 g_qflg = B_TRUE; 138 break; 139 case 'j': 140 g_jflg = B_TRUE; 141 break; 142 case 'l': 143 g_pflg = g_lflg = B_TRUE; 144 break; 145 case 'p': 146 g_pflg = B_TRUE; 147 break; 148 case 'T': 149 switch (*optarg) { 150 case 'd': 151 g_timestamp_fmt = DDATE; 152 break; 153 case 'u': 154 g_timestamp_fmt = UDATE; 155 break; 156 default: 157 errflg = B_TRUE; 158 } 159 break; 160 case 'm': 161 nselflg = B_TRUE; 162 nselector->ks_module = 163 (char *)ks_safe_strdup(optarg); 164 break; 165 case 'i': 166 nselflg = B_TRUE; 167 nselector->ks_instance = 168 (char *)ks_safe_strdup(optarg); 169 break; 170 case 'n': 171 nselflg = B_TRUE; 172 nselector->ks_name = 173 (char *)ks_safe_strdup(optarg); 174 break; 175 case 's': 176 nselflg = B_TRUE; 177 nselector->ks_statistic = 178 (char *)ks_safe_strdup(optarg); 179 break; 180 case 'c': 181 g_ks_class = 182 (char *)ks_safe_strdup(optarg); 183 break; 184 default: 185 errflg = B_TRUE; 186 break; 187 } 188 189 if (g_qflg && (g_jflg || g_pflg)) { 190 (void) fprintf(stderr, gettext( 191 "-q and -lpj are mutually exclusive\n")); 192 errflg = B_TRUE; 193 } 194 195 if (errflg) { 196 usage(); 197 exit(2); 198 } 199 200 argc -= optind; 201 argv += optind; 202 203 /* 204 * Consume the rest of the command line. Parsing the 205 * unnamed command line arguments. 206 */ 207 while (argc--) { 208 errno = 0; 209 tmp = strtoul(*argv, &q, 10); 210 if (tmp == ULONG_MAX && errno == ERANGE) { 211 if (n == 0) { 212 (void) fprintf(stderr, gettext( 213 "Interval is too large\n")); 214 } else if (n == 1) { 215 (void) fprintf(stderr, gettext( 216 "Count is too large\n")); 217 } 218 usage(); 219 exit(2); 220 } 221 222 if (errno != 0 || *q != '\0') { 223 m = 0; 224 uselector = new_selector(); 225 while ((q = (char *)strsep(argv, ":")) != NULL) { 226 m++; 227 if (m > 4) { 228 free(uselector); 229 usage(); 230 exit(2); 231 } 232 233 if (*q != '\0') { 234 switch (m) { 235 case 1: 236 uselector->ks_module = 237 (char *)ks_safe_strdup(q); 238 break; 239 case 2: 240 uselector->ks_instance = 241 (char *)ks_safe_strdup(q); 242 break; 243 case 3: 244 uselector->ks_name = 245 (char *)ks_safe_strdup(q); 246 break; 247 case 4: 248 uselector->ks_statistic = 249 (char *)ks_safe_strdup(q); 250 break; 251 default: 252 assert(B_FALSE); 253 } 254 } 255 } 256 257 if (m < 4) { 258 free(uselector); 259 usage(); 260 exit(2); 261 } 262 263 uselflg = B_TRUE; 264 list_insert_tail(&selector_list, uselector); 265 } else { 266 if (tmp < 1) { 267 if (n == 0) { 268 (void) fprintf(stderr, gettext( 269 "Interval must be an " 270 "integer >= 1")); 271 } else if (n == 1) { 272 (void) fprintf(stderr, gettext( 273 "Count must be an integer >= 1")); 274 } 275 usage(); 276 exit(2); 277 } else { 278 if (n == 0) { 279 interval = tmp; 280 count = -1; 281 } else if (n == 1) { 282 count = tmp; 283 } else { 284 usage(); 285 exit(2); 286 } 287 } 288 n++; 289 } 290 argv++; 291 } 292 293 /* 294 * Check if we founded a named selector on the cmdline. 295 */ 296 if (uselflg) { 297 if (nselflg) { 298 (void) fprintf(stderr, gettext( 299 "module:instance:name:statistic and " 300 "-m -i -n -s are mutually exclusive")); 301 usage(); 302 exit(2); 303 } else { 304 free(nselector); 305 } 306 } else { 307 list_insert_tail(&selector_list, nselector); 308 } 309 310 assert(!list_is_empty(&selector_list)); 311 312 list_create(&instances_list, sizeof (ks_instance_t), 313 offsetof(ks_instance_t, ks_next)); 314 315 while ((kc = kstat_open()) == NULL) { 316 if (errno == EAGAIN) { 317 (void) poll(NULL, 0, 200); 318 } else { 319 perror("kstat_open"); 320 exit(3); 321 } 322 } 323 324 if (count > 1) { 325 if (signal(SIGCONT, cont_handler) == SIG_ERR) { 326 (void) fprintf(stderr, gettext( 327 "signal failed")); 328 exit(3); 329 } 330 } 331 332 period_n = (hrtime_t)interval * NANOSEC; 333 start_n = gethrtime(); 334 335 while (count == -1 || count-- > 0) { 336 ks_instances_read(kc); 337 ks_instances_print(); 338 339 if (interval && count) { 340 ks_sleep_until(&start_n, period_n, infinite_cycles, 341 &caught_cont); 342 (void) kstat_chain_update(kc); 343 (void) putchar('\n'); 344 } 345 } 346 347 (void) kstat_close(kc); 348 349 return (g_matched); 350 } 351 352 /* 353 * Print usage. 354 */ 355 static void 356 usage(void) 357 { 358 (void) fprintf(stderr, gettext( 359 "Usage:\n" 360 "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ]\n" 361 " [ -m module ] [ -i instance ] [ -n name ] [ -s statistic ]\n" 362 " [ interval [ count ] ]\n" 363 "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ]\n" 364 " [ module:instance:name:statistic ... ]\n" 365 " [ interval [ count ] ]\n")); 366 } 367 368 /* 369 * Sort compare function. 370 */ 371 static int 372 compare_instances(ks_instance_t *l_arg, ks_instance_t *r_arg) 373 { 374 int rval; 375 376 rval = strcasecmp(l_arg->ks_module, r_arg->ks_module); 377 if (rval == 0) { 378 if (l_arg->ks_instance == r_arg->ks_instance) { 379 return (strcasecmp(l_arg->ks_name, r_arg->ks_name)); 380 } else if (l_arg->ks_instance < r_arg->ks_instance) { 381 return (-1); 382 } else { 383 return (1); 384 } 385 } else { 386 return (rval); 387 } 388 } 389 390 static char * 391 ks_safe_strdup(char *str) 392 { 393 char *ret; 394 395 if (str == NULL) { 396 return (NULL); 397 } 398 399 while ((ret = strdup(str)) == NULL) { 400 if (errno == EAGAIN) { 401 (void) poll(NULL, 0, 200); 402 } else { 403 perror("strdup"); 404 exit(3); 405 } 406 } 407 408 return (ret); 409 } 410 411 static void 412 ks_sleep_until(hrtime_t *wakeup, hrtime_t interval, int forever, 413 int *caught_cont) 414 { 415 hrtime_t now, pause, pause_left; 416 struct timespec pause_tv; 417 int status; 418 419 now = gethrtime(); 420 pause = *wakeup + interval - now; 421 422 if (pause <= 0 || pause < (interval / 4)) { 423 if (forever || *caught_cont) { 424 *wakeup = now + interval; 425 pause = interval; 426 } else { 427 pause = interval / 2; 428 *wakeup += interval; 429 } 430 } else { 431 *wakeup += interval; 432 } 433 434 if (pause < 1000) { 435 return; 436 } 437 438 pause_left = pause; 439 do { 440 pause_tv.tv_sec = pause_left / NANOSEC; 441 pause_tv.tv_nsec = pause_left % NANOSEC; 442 status = nanosleep(&pause_tv, (struct timespec *)NULL); 443 if (status < 0) { 444 if (errno == EINTR) { 445 now = gethrtime(); 446 pause_left = *wakeup - now; 447 if (pause_left < 1000) { 448 return; 449 } 450 } else { 451 perror("nanosleep"); 452 exit(3); 453 } 454 } 455 } while (status != 0); 456 } 457 458 /* 459 * Inserts an instance in the per selector list. 460 */ 461 static void 462 nvpair_insert(ks_instance_t *ksi, char *name, ks_value_t *value, 463 uchar_t data_type) 464 { 465 ks_nvpair_t *instance; 466 ks_nvpair_t *tmp; 467 468 instance = (ks_nvpair_t *)malloc(sizeof (ks_nvpair_t)); 469 if (instance == NULL) { 470 perror("malloc"); 471 exit(3); 472 } 473 474 (void) strlcpy(instance->name, name, KSTAT_STRLEN); 475 (void) memcpy(&instance->value, value, sizeof (ks_value_t)); 476 instance->data_type = data_type; 477 478 tmp = list_head(&ksi->ks_nvlist); 479 while (tmp != NULL && strcasecmp(instance->name, tmp->name) > 0) 480 tmp = list_next(&ksi->ks_nvlist, tmp); 481 482 list_insert_before(&ksi->ks_nvlist, tmp, instance); 483 } 484 485 /* 486 * Allocates a new all-matching selector. 487 */ 488 static ks_selector_t * 489 new_selector(void) 490 { 491 ks_selector_t *selector; 492 493 selector = (ks_selector_t *)malloc(sizeof (ks_selector_t)); 494 if (selector == NULL) { 495 perror("malloc"); 496 exit(3); 497 } 498 499 list_link_init(&selector->ks_next); 500 501 selector->ks_module = "*"; 502 selector->ks_instance = "*"; 503 selector->ks_name = "*"; 504 selector->ks_statistic = "*"; 505 506 return (selector); 507 } 508 509 /* 510 * This function was taken from the perl kstat module code - please 511 * see for further comments there. 512 */ 513 static kstat_raw_reader_t 514 lookup_raw_kstat_fn(char *module, char *name) 515 { 516 char key[KSTAT_STRLEN * 2]; 517 register char *f, *t; 518 int n = 0; 519 520 for (f = module, t = key; *f != '\0'; f++, t++) { 521 while (*f != '\0' && isdigit(*f)) 522 f++; 523 *t = *f; 524 } 525 *t++ = ':'; 526 527 for (f = name; *f != '\0'; f++, t++) { 528 while (*f != '\0' && isdigit(*f)) 529 f++; 530 *t = *f; 531 } 532 *t = '\0'; 533 534 while (ks_raw_lookup[n].fn != NULL) { 535 if (strncmp(ks_raw_lookup[n].name, key, strlen(key)) == 0) 536 return (ks_raw_lookup[n].fn); 537 n++; 538 } 539 540 return (0); 541 } 542 543 /* 544 * Iterate over all kernel statistics and save matches. 545 */ 546 static void 547 ks_instances_read(kstat_ctl_t *kc) 548 { 549 kstat_raw_reader_t save_raw = NULL; 550 kid_t id; 551 ks_selector_t *selector; 552 ks_instance_t *ksi; 553 ks_instance_t *tmp; 554 kstat_t *kp; 555 boolean_t skip; 556 char *ks_number; 557 558 for (kp = kc->kc_chain; kp != NULL; kp = kp->ks_next) { 559 /* Don't bother storing the kstat headers */ 560 if (strncmp(kp->ks_name, "kstat_", 6) == 0) { 561 continue; 562 } 563 564 /* Don't bother storing raw stats we don't understand */ 565 if (kp->ks_type == KSTAT_TYPE_RAW) { 566 save_raw = lookup_raw_kstat_fn(kp->ks_module, 567 kp->ks_name); 568 if (save_raw == NULL) { 569 #ifdef REPORT_UNKNOWN 570 (void) fprintf(stderr, 571 "Unknown kstat type %s:%d:%s - " 572 "%d of size %d\n", kp->ks_module, 573 kp->ks_instance, kp->ks_name, 574 kp->ks_ndata, kp->ks_data_size); 575 #endif 576 continue; 577 } 578 } 579 580 /* 581 * Iterate over the list of selectors and skip 582 * instances we dont want. We filter for statistics 583 * later, as we dont know them yet. 584 */ 585 skip = B_FALSE; 586 (void) asprintf(&ks_number, "%d", kp->ks_instance); 587 selector = list_head(&selector_list); 588 while (selector != NULL) { 589 if (!(gmatch(kp->ks_module, selector->ks_module) != 0 && 590 gmatch(ks_number, selector->ks_instance) != 0 && 591 gmatch(kp->ks_name, selector->ks_name) != 0 && 592 gmatch(kp->ks_class, g_ks_class))) { 593 skip = B_TRUE; 594 } 595 selector = list_next(&selector_list, selector); 596 } 597 598 free(ks_number); 599 600 if (skip) { 601 continue; 602 } 603 604 /* 605 * Allocate a new instance and fill in the values 606 * we know so far. 607 */ 608 ksi = (ks_instance_t *)malloc(sizeof (ks_instance_t)); 609 if (ksi == NULL) { 610 perror("malloc"); 611 exit(3); 612 } 613 614 list_link_init(&ksi->ks_next); 615 616 (void) strlcpy(ksi->ks_module, kp->ks_module, KSTAT_STRLEN); 617 (void) strlcpy(ksi->ks_name, kp->ks_name, KSTAT_STRLEN); 618 (void) strlcpy(ksi->ks_class, kp->ks_class, KSTAT_STRLEN); 619 620 ksi->ks_instance = kp->ks_instance; 621 ksi->ks_snaptime = kp->ks_snaptime; 622 ksi->ks_type = kp->ks_type; 623 624 list_create(&ksi->ks_nvlist, sizeof (ks_nvpair_t), 625 offsetof(ks_nvpair_t, nv_next)); 626 627 SAVE_HRTIME_X(ksi, "crtime", kp->ks_crtime); 628 SAVE_HRTIME_X(ksi, "snaptime", kp->ks_snaptime); 629 if (g_pflg) { 630 SAVE_STRING_X(ksi, "class", kp->ks_class); 631 } 632 633 /* Insert this instance into a sorted list */ 634 tmp = list_head(&instances_list); 635 while (tmp != NULL && compare_instances(ksi, tmp) > 0) 636 tmp = list_next(&instances_list, tmp); 637 638 list_insert_before(&instances_list, tmp, ksi); 639 640 /* Read the actual statistics */ 641 id = kstat_read(kc, kp, NULL); 642 if (id == -1) { 643 #ifdef REPORT_UNKNOWN 644 perror("kstat_read"); 645 #endif 646 continue; 647 } 648 649 switch (kp->ks_type) { 650 case KSTAT_TYPE_RAW: 651 save_raw(kp, ksi); 652 break; 653 case KSTAT_TYPE_NAMED: 654 save_named(kp, ksi); 655 break; 656 case KSTAT_TYPE_INTR: 657 save_intr(kp, ksi); 658 break; 659 case KSTAT_TYPE_IO: 660 save_io(kp, ksi); 661 break; 662 case KSTAT_TYPE_TIMER: 663 save_timer(kp, ksi); 664 break; 665 default: 666 assert(B_FALSE); /* Invalid type */ 667 break; 668 } 669 } 670 } 671 672 /* 673 * Print the value of a name-value pair. 674 */ 675 static void 676 ks_value_print(ks_nvpair_t *nvpair) 677 { 678 switch (nvpair->data_type) { 679 case KSTAT_DATA_CHAR: 680 (void) fprintf(stdout, "%s", nvpair->value.c); 681 break; 682 case KSTAT_DATA_INT32: 683 (void) fprintf(stdout, "%d", nvpair->value.i32); 684 break; 685 case KSTAT_DATA_UINT32: 686 (void) fprintf(stdout, "%u", nvpair->value.ui32); 687 break; 688 case KSTAT_DATA_INT64: 689 (void) fprintf(stdout, "%lld", nvpair->value.i64); 690 break; 691 case KSTAT_DATA_UINT64: 692 (void) fprintf(stdout, "%llu", nvpair->value.ui64); 693 break; 694 case KSTAT_DATA_STRING: 695 (void) fprintf(stdout, "%s", KSTAT_NAMED_STR_PTR(nvpair)); 696 break; 697 case KSTAT_DATA_HRTIME: 698 if (nvpair->value.ui64 == 0) 699 (void) fprintf(stdout, "0"); 700 else 701 (void) fprintf(stdout, "%.9f", 702 nvpair->value.ui64 / 1000000000.0); 703 break; 704 default: 705 assert(B_FALSE); 706 } 707 } 708 709 /* 710 * Print a single instance. 711 */ 712 static void 713 ks_instance_print(ks_instance_t *ksi, ks_nvpair_t *nvpair) 714 { 715 if (g_headerflg) { 716 if (!g_pflg) { 717 (void) fprintf(stdout, DFLT_FMT, 718 ksi->ks_module, ksi->ks_instance, 719 ksi->ks_name, ksi->ks_class); 720 } 721 g_headerflg = B_FALSE; 722 } 723 724 if (g_pflg) { 725 (void) fprintf(stdout, KS_PFMT, 726 ksi->ks_module, ksi->ks_instance, 727 ksi->ks_name, nvpair->name); 728 if (!g_lflg) { 729 (void) putchar(g_cflg ? ':': '\t'); 730 ks_value_print(nvpair); 731 } 732 } else { 733 (void) fprintf(stdout, KS_DFMT, nvpair->name); 734 ks_value_print(nvpair); 735 } 736 737 (void) putchar('\n'); 738 } 739 740 /* 741 * Print a single instance in JSON format. 742 */ 743 static void 744 ks_instance_print_json(ks_instance_t *ksi, ks_nvpair_t *nvpair) 745 { 746 if (g_headerflg) { 747 (void) fprintf(stdout, JSON_FMT, 748 ksi->ks_module, ksi->ks_instance, 749 ksi->ks_name, ksi->ks_class, 750 ksi->ks_type); 751 752 if (ksi->ks_snaptime == 0) 753 (void) fprintf(stdout, "\t\"snaptime\": 0,\n"); 754 else 755 (void) fprintf(stdout, "\t\"snaptime\": %.9f,\n", 756 ksi->ks_snaptime / 1000000000.0); 757 758 (void) fprintf(stdout, "\t\"data\": {\n"); 759 760 g_headerflg = B_FALSE; 761 } 762 763 (void) fprintf(stdout, KS_JFMT, nvpair->name); 764 if (nvpair->data_type == KSTAT_DATA_STRING) { 765 (void) putchar('\"'); 766 ks_value_print(nvpair); 767 (void) putchar('\"'); 768 } else { 769 ks_value_print(nvpair); 770 } 771 if (nvpair != list_tail(&ksi->ks_nvlist)) 772 (void) putchar(','); 773 774 (void) putchar('\n'); 775 } 776 777 /* 778 * Print all instances. 779 */ 780 static void 781 ks_instances_print(void) 782 { 783 ks_selector_t *selector; 784 ks_instance_t *ksi, *ktmp; 785 ks_nvpair_t *nvpair, *ntmp; 786 void (*ks_print_fn)(ks_instance_t *, ks_nvpair_t *); 787 788 if (g_timestamp_fmt != NODATE) 789 print_timestamp(g_timestamp_fmt); 790 791 if (g_jflg) { 792 ks_print_fn = &ks_instance_print_json; 793 (void) putchar('['); 794 } else { 795 ks_print_fn = &ks_instance_print; 796 } 797 798 /* Iterate over each selector */ 799 selector = list_head(&selector_list); 800 while (selector != NULL) { 801 802 /* Iterate over each instance */ 803 for (ksi = list_head(&instances_list); ksi != NULL; 804 ksi = list_next(&instances_list, ksi)) { 805 806 /* Finally iterate over each statistic */ 807 g_headerflg = B_TRUE; 808 for (nvpair = list_head(&ksi->ks_nvlist); 809 nvpair != NULL; 810 nvpair = list_next(&ksi->ks_nvlist, nvpair)) { 811 if (gmatch(nvpair->name, 812 selector->ks_statistic) == 0) 813 continue; 814 815 g_matched = 0; 816 if (!g_qflg) 817 (*ks_print_fn)(ksi, nvpair); 818 } 819 820 if (!g_headerflg) { 821 if (g_jflg) { 822 (void) fprintf(stdout, "\t}\n}"); 823 if (ksi != list_tail(&instances_list)) 824 (void) putchar(','); 825 } else if (!g_pflg) { 826 (void) putchar('\n'); 827 } 828 } 829 } 830 831 selector = list_next(&selector_list, selector); 832 } 833 834 if (g_jflg) 835 (void) fprintf(stdout, "]\n"); 836 837 (void) fflush(stdout); 838 839 /* Free the instances list */ 840 ksi = list_head(&instances_list); 841 while (ksi != NULL) { 842 nvpair = list_head(&ksi->ks_nvlist); 843 while (nvpair != NULL) { 844 ntmp = nvpair; 845 nvpair = list_next(&ksi->ks_nvlist, nvpair); 846 list_remove(&ksi->ks_nvlist, ntmp); 847 if (ntmp->data_type == KSTAT_DATA_STRING) 848 free(ntmp->value.str.addr.ptr); 849 free(ntmp); 850 } 851 852 ktmp = ksi; 853 ksi = list_next(&instances_list, ksi); 854 list_remove(&instances_list, ktmp); 855 list_destroy(&ktmp->ks_nvlist); 856 free(ktmp); 857 } 858 } 859 860 static void 861 save_cpu_stat(kstat_t *kp, ks_instance_t *ksi) 862 { 863 cpu_stat_t *stat; 864 cpu_sysinfo_t *sysinfo; 865 cpu_syswait_t *syswait; 866 cpu_vminfo_t *vminfo; 867 868 stat = (cpu_stat_t *)(kp->ks_data); 869 sysinfo = &stat->cpu_sysinfo; 870 syswait = &stat->cpu_syswait; 871 vminfo = &stat->cpu_vminfo; 872 873 SAVE_UINT32_X(ksi, "idle", sysinfo->cpu[CPU_IDLE]); 874 SAVE_UINT32_X(ksi, "user", sysinfo->cpu[CPU_USER]); 875 SAVE_UINT32_X(ksi, "kernel", sysinfo->cpu[CPU_KERNEL]); 876 SAVE_UINT32_X(ksi, "wait", sysinfo->cpu[CPU_WAIT]); 877 SAVE_UINT32_X(ksi, "wait_io", sysinfo->cpu[W_IO]); 878 SAVE_UINT32_X(ksi, "wait_swap", sysinfo->cpu[W_SWAP]); 879 SAVE_UINT32_X(ksi, "wait_pio", sysinfo->cpu[W_PIO]); 880 SAVE_UINT32(ksi, sysinfo, bread); 881 SAVE_UINT32(ksi, sysinfo, bwrite); 882 SAVE_UINT32(ksi, sysinfo, lread); 883 SAVE_UINT32(ksi, sysinfo, lwrite); 884 SAVE_UINT32(ksi, sysinfo, phread); 885 SAVE_UINT32(ksi, sysinfo, phwrite); 886 SAVE_UINT32(ksi, sysinfo, pswitch); 887 SAVE_UINT32(ksi, sysinfo, trap); 888 SAVE_UINT32(ksi, sysinfo, intr); 889 SAVE_UINT32(ksi, sysinfo, syscall); 890 SAVE_UINT32(ksi, sysinfo, sysread); 891 SAVE_UINT32(ksi, sysinfo, syswrite); 892 SAVE_UINT32(ksi, sysinfo, sysfork); 893 SAVE_UINT32(ksi, sysinfo, sysvfork); 894 SAVE_UINT32(ksi, sysinfo, sysexec); 895 SAVE_UINT32(ksi, sysinfo, readch); 896 SAVE_UINT32(ksi, sysinfo, writech); 897 SAVE_UINT32(ksi, sysinfo, rcvint); 898 SAVE_UINT32(ksi, sysinfo, xmtint); 899 SAVE_UINT32(ksi, sysinfo, mdmint); 900 SAVE_UINT32(ksi, sysinfo, rawch); 901 SAVE_UINT32(ksi, sysinfo, canch); 902 SAVE_UINT32(ksi, sysinfo, outch); 903 SAVE_UINT32(ksi, sysinfo, msg); 904 SAVE_UINT32(ksi, sysinfo, sema); 905 SAVE_UINT32(ksi, sysinfo, namei); 906 SAVE_UINT32(ksi, sysinfo, ufsiget); 907 SAVE_UINT32(ksi, sysinfo, ufsdirblk); 908 SAVE_UINT32(ksi, sysinfo, ufsipage); 909 SAVE_UINT32(ksi, sysinfo, ufsinopage); 910 SAVE_UINT32(ksi, sysinfo, inodeovf); 911 SAVE_UINT32(ksi, sysinfo, fileovf); 912 SAVE_UINT32(ksi, sysinfo, procovf); 913 SAVE_UINT32(ksi, sysinfo, intrthread); 914 SAVE_UINT32(ksi, sysinfo, intrblk); 915 SAVE_UINT32(ksi, sysinfo, idlethread); 916 SAVE_UINT32(ksi, sysinfo, inv_swtch); 917 SAVE_UINT32(ksi, sysinfo, nthreads); 918 SAVE_UINT32(ksi, sysinfo, cpumigrate); 919 SAVE_UINT32(ksi, sysinfo, xcalls); 920 SAVE_UINT32(ksi, sysinfo, mutex_adenters); 921 SAVE_UINT32(ksi, sysinfo, rw_rdfails); 922 SAVE_UINT32(ksi, sysinfo, rw_wrfails); 923 SAVE_UINT32(ksi, sysinfo, modload); 924 SAVE_UINT32(ksi, sysinfo, modunload); 925 SAVE_UINT32(ksi, sysinfo, bawrite); 926 #ifdef STATISTICS /* see header file */ 927 SAVE_UINT32(ksi, sysinfo, rw_enters); 928 SAVE_UINT32(ksi, sysinfo, win_uo_cnt); 929 SAVE_UINT32(ksi, sysinfo, win_uu_cnt); 930 SAVE_UINT32(ksi, sysinfo, win_so_cnt); 931 SAVE_UINT32(ksi, sysinfo, win_su_cnt); 932 SAVE_UINT32(ksi, sysinfo, win_suo_cnt); 933 #endif 934 935 SAVE_INT32(ksi, syswait, iowait); 936 SAVE_INT32(ksi, syswait, swap); 937 SAVE_INT32(ksi, syswait, physio); 938 939 SAVE_UINT32(ksi, vminfo, pgrec); 940 SAVE_UINT32(ksi, vminfo, pgfrec); 941 SAVE_UINT32(ksi, vminfo, pgin); 942 SAVE_UINT32(ksi, vminfo, pgpgin); 943 SAVE_UINT32(ksi, vminfo, pgout); 944 SAVE_UINT32(ksi, vminfo, pgpgout); 945 SAVE_UINT32(ksi, vminfo, swapin); 946 SAVE_UINT32(ksi, vminfo, pgswapin); 947 SAVE_UINT32(ksi, vminfo, swapout); 948 SAVE_UINT32(ksi, vminfo, pgswapout); 949 SAVE_UINT32(ksi, vminfo, zfod); 950 SAVE_UINT32(ksi, vminfo, dfree); 951 SAVE_UINT32(ksi, vminfo, scan); 952 SAVE_UINT32(ksi, vminfo, rev); 953 SAVE_UINT32(ksi, vminfo, hat_fault); 954 SAVE_UINT32(ksi, vminfo, as_fault); 955 SAVE_UINT32(ksi, vminfo, maj_fault); 956 SAVE_UINT32(ksi, vminfo, cow_fault); 957 SAVE_UINT32(ksi, vminfo, prot_fault); 958 SAVE_UINT32(ksi, vminfo, softlock); 959 SAVE_UINT32(ksi, vminfo, kernel_asflt); 960 SAVE_UINT32(ksi, vminfo, pgrrun); 961 SAVE_UINT32(ksi, vminfo, execpgin); 962 SAVE_UINT32(ksi, vminfo, execpgout); 963 SAVE_UINT32(ksi, vminfo, execfree); 964 SAVE_UINT32(ksi, vminfo, anonpgin); 965 SAVE_UINT32(ksi, vminfo, anonpgout); 966 SAVE_UINT32(ksi, vminfo, anonfree); 967 SAVE_UINT32(ksi, vminfo, fspgin); 968 SAVE_UINT32(ksi, vminfo, fspgout); 969 SAVE_UINT32(ksi, vminfo, fsfree); 970 } 971 972 static void 973 save_var(kstat_t *kp, ks_instance_t *ksi) 974 { 975 struct var *var = (struct var *)(kp->ks_data); 976 977 assert(kp->ks_data_size == sizeof (struct var)); 978 979 SAVE_INT32(ksi, var, v_buf); 980 SAVE_INT32(ksi, var, v_call); 981 SAVE_INT32(ksi, var, v_proc); 982 SAVE_INT32(ksi, var, v_maxupttl); 983 SAVE_INT32(ksi, var, v_nglobpris); 984 SAVE_INT32(ksi, var, v_maxsyspri); 985 SAVE_INT32(ksi, var, v_clist); 986 SAVE_INT32(ksi, var, v_maxup); 987 SAVE_INT32(ksi, var, v_hbuf); 988 SAVE_INT32(ksi, var, v_hmask); 989 SAVE_INT32(ksi, var, v_pbuf); 990 SAVE_INT32(ksi, var, v_sptmap); 991 SAVE_INT32(ksi, var, v_maxpmem); 992 SAVE_INT32(ksi, var, v_autoup); 993 SAVE_INT32(ksi, var, v_bufhwm); 994 } 995 996 static void 997 save_ncstats(kstat_t *kp, ks_instance_t *ksi) 998 { 999 struct ncstats *ncstats = (struct ncstats *)(kp->ks_data); 1000 1001 assert(kp->ks_data_size == sizeof (struct ncstats)); 1002 1003 SAVE_INT32(ksi, ncstats, hits); 1004 SAVE_INT32(ksi, ncstats, misses); 1005 SAVE_INT32(ksi, ncstats, enters); 1006 SAVE_INT32(ksi, ncstats, dbl_enters); 1007 SAVE_INT32(ksi, ncstats, long_enter); 1008 SAVE_INT32(ksi, ncstats, long_look); 1009 SAVE_INT32(ksi, ncstats, move_to_front); 1010 SAVE_INT32(ksi, ncstats, purges); 1011 } 1012 1013 static void 1014 save_sysinfo(kstat_t *kp, ks_instance_t *ksi) 1015 { 1016 sysinfo_t *sysinfo = (sysinfo_t *)(kp->ks_data); 1017 1018 assert(kp->ks_data_size == sizeof (sysinfo_t)); 1019 1020 SAVE_UINT32(ksi, sysinfo, updates); 1021 SAVE_UINT32(ksi, sysinfo, runque); 1022 SAVE_UINT32(ksi, sysinfo, runocc); 1023 SAVE_UINT32(ksi, sysinfo, swpque); 1024 SAVE_UINT32(ksi, sysinfo, swpocc); 1025 SAVE_UINT32(ksi, sysinfo, waiting); 1026 } 1027 1028 static void 1029 save_vminfo(kstat_t *kp, ks_instance_t *ksi) 1030 { 1031 vminfo_t *vminfo = (vminfo_t *)(kp->ks_data); 1032 1033 assert(kp->ks_data_size == sizeof (vminfo_t)); 1034 1035 SAVE_UINT64(ksi, vminfo, freemem); 1036 SAVE_UINT64(ksi, vminfo, swap_resv); 1037 SAVE_UINT64(ksi, vminfo, swap_alloc); 1038 SAVE_UINT64(ksi, vminfo, swap_avail); 1039 SAVE_UINT64(ksi, vminfo, swap_free); 1040 SAVE_UINT64(ksi, vminfo, updates); 1041 } 1042 1043 static void 1044 save_nfs(kstat_t *kp, ks_instance_t *ksi) 1045 { 1046 struct mntinfo_kstat *mntinfo = (struct mntinfo_kstat *)(kp->ks_data); 1047 1048 assert(kp->ks_data_size == sizeof (struct mntinfo_kstat)); 1049 1050 SAVE_STRING(ksi, mntinfo, mik_proto); 1051 SAVE_UINT32(ksi, mntinfo, mik_vers); 1052 SAVE_UINT32(ksi, mntinfo, mik_flags); 1053 SAVE_UINT32(ksi, mntinfo, mik_secmod); 1054 SAVE_UINT32(ksi, mntinfo, mik_curread); 1055 SAVE_UINT32(ksi, mntinfo, mik_curwrite); 1056 SAVE_INT32(ksi, mntinfo, mik_timeo); 1057 SAVE_INT32(ksi, mntinfo, mik_retrans); 1058 SAVE_UINT32(ksi, mntinfo, mik_acregmin); 1059 SAVE_UINT32(ksi, mntinfo, mik_acregmax); 1060 SAVE_UINT32(ksi, mntinfo, mik_acdirmin); 1061 SAVE_UINT32(ksi, mntinfo, mik_acdirmax); 1062 SAVE_UINT32_X(ksi, "lookup_srtt", mntinfo->mik_timers[0].srtt); 1063 SAVE_UINT32_X(ksi, "lookup_deviate", mntinfo->mik_timers[0].deviate); 1064 SAVE_UINT32_X(ksi, "lookup_rtxcur", mntinfo->mik_timers[0].rtxcur); 1065 SAVE_UINT32_X(ksi, "read_srtt", mntinfo->mik_timers[1].srtt); 1066 SAVE_UINT32_X(ksi, "read_deviate", mntinfo->mik_timers[1].deviate); 1067 SAVE_UINT32_X(ksi, "read_rtxcur", mntinfo->mik_timers[1].rtxcur); 1068 SAVE_UINT32_X(ksi, "write_srtt", mntinfo->mik_timers[2].srtt); 1069 SAVE_UINT32_X(ksi, "write_deviate", mntinfo->mik_timers[2].deviate); 1070 SAVE_UINT32_X(ksi, "write_rtxcur", mntinfo->mik_timers[2].rtxcur); 1071 SAVE_UINT32(ksi, mntinfo, mik_noresponse); 1072 SAVE_UINT32(ksi, mntinfo, mik_failover); 1073 SAVE_UINT32(ksi, mntinfo, mik_remap); 1074 SAVE_STRING(ksi, mntinfo, mik_curserver); 1075 } 1076 1077 #ifdef __sparc 1078 static void 1079 save_sfmmu_global_stat(kstat_t *kp, ks_instance_t *ksi) 1080 { 1081 struct sfmmu_global_stat *sfmmug = 1082 (struct sfmmu_global_stat *)(kp->ks_data); 1083 1084 assert(kp->ks_data_size == sizeof (struct sfmmu_global_stat)); 1085 1086 SAVE_INT32(ksi, sfmmug, sf_tsb_exceptions); 1087 SAVE_INT32(ksi, sfmmug, sf_tsb_raise_exception); 1088 SAVE_INT32(ksi, sfmmug, sf_pagefaults); 1089 SAVE_INT32(ksi, sfmmug, sf_uhash_searches); 1090 SAVE_INT32(ksi, sfmmug, sf_uhash_links); 1091 SAVE_INT32(ksi, sfmmug, sf_khash_searches); 1092 SAVE_INT32(ksi, sfmmug, sf_khash_links); 1093 SAVE_INT32(ksi, sfmmug, sf_swapout); 1094 SAVE_INT32(ksi, sfmmug, sf_tsb_alloc); 1095 SAVE_INT32(ksi, sfmmug, sf_tsb_allocfail); 1096 SAVE_INT32(ksi, sfmmug, sf_tsb_sectsb_create); 1097 SAVE_INT32(ksi, sfmmug, sf_scd_1sttsb_alloc); 1098 SAVE_INT32(ksi, sfmmug, sf_scd_2ndtsb_alloc); 1099 SAVE_INT32(ksi, sfmmug, sf_scd_1sttsb_allocfail); 1100 SAVE_INT32(ksi, sfmmug, sf_scd_2ndtsb_allocfail); 1101 SAVE_INT32(ksi, sfmmug, sf_tteload8k); 1102 SAVE_INT32(ksi, sfmmug, sf_tteload64k); 1103 SAVE_INT32(ksi, sfmmug, sf_tteload512k); 1104 SAVE_INT32(ksi, sfmmug, sf_tteload4m); 1105 SAVE_INT32(ksi, sfmmug, sf_tteload32m); 1106 SAVE_INT32(ksi, sfmmug, sf_tteload256m); 1107 SAVE_INT32(ksi, sfmmug, sf_tsb_load8k); 1108 SAVE_INT32(ksi, sfmmug, sf_tsb_load4m); 1109 SAVE_INT32(ksi, sfmmug, sf_hblk_hit); 1110 SAVE_INT32(ksi, sfmmug, sf_hblk8_ncreate); 1111 SAVE_INT32(ksi, sfmmug, sf_hblk8_nalloc); 1112 SAVE_INT32(ksi, sfmmug, sf_hblk1_ncreate); 1113 SAVE_INT32(ksi, sfmmug, sf_hblk1_nalloc); 1114 SAVE_INT32(ksi, sfmmug, sf_hblk_slab_cnt); 1115 SAVE_INT32(ksi, sfmmug, sf_hblk_reserve_cnt); 1116 SAVE_INT32(ksi, sfmmug, sf_hblk_recurse_cnt); 1117 SAVE_INT32(ksi, sfmmug, sf_hblk_reserve_hit); 1118 SAVE_INT32(ksi, sfmmug, sf_get_free_success); 1119 SAVE_INT32(ksi, sfmmug, sf_get_free_throttle); 1120 SAVE_INT32(ksi, sfmmug, sf_get_free_fail); 1121 SAVE_INT32(ksi, sfmmug, sf_put_free_success); 1122 SAVE_INT32(ksi, sfmmug, sf_put_free_fail); 1123 SAVE_INT32(ksi, sfmmug, sf_pgcolor_conflict); 1124 SAVE_INT32(ksi, sfmmug, sf_uncache_conflict); 1125 SAVE_INT32(ksi, sfmmug, sf_unload_conflict); 1126 SAVE_INT32(ksi, sfmmug, sf_ism_uncache); 1127 SAVE_INT32(ksi, sfmmug, sf_ism_recache); 1128 SAVE_INT32(ksi, sfmmug, sf_recache); 1129 SAVE_INT32(ksi, sfmmug, sf_steal_count); 1130 SAVE_INT32(ksi, sfmmug, sf_pagesync); 1131 SAVE_INT32(ksi, sfmmug, sf_clrwrt); 1132 SAVE_INT32(ksi, sfmmug, sf_pagesync_invalid); 1133 SAVE_INT32(ksi, sfmmug, sf_kernel_xcalls); 1134 SAVE_INT32(ksi, sfmmug, sf_user_xcalls); 1135 SAVE_INT32(ksi, sfmmug, sf_tsb_grow); 1136 SAVE_INT32(ksi, sfmmug, sf_tsb_shrink); 1137 SAVE_INT32(ksi, sfmmug, sf_tsb_resize_failures); 1138 SAVE_INT32(ksi, sfmmug, sf_tsb_reloc); 1139 SAVE_INT32(ksi, sfmmug, sf_user_vtop); 1140 SAVE_INT32(ksi, sfmmug, sf_ctx_inv); 1141 SAVE_INT32(ksi, sfmmug, sf_tlb_reprog_pgsz); 1142 SAVE_INT32(ksi, sfmmug, sf_region_remap_demap); 1143 SAVE_INT32(ksi, sfmmug, sf_create_scd); 1144 SAVE_INT32(ksi, sfmmug, sf_join_scd); 1145 SAVE_INT32(ksi, sfmmug, sf_leave_scd); 1146 SAVE_INT32(ksi, sfmmug, sf_destroy_scd); 1147 } 1148 #endif 1149 1150 #ifdef __sparc 1151 static void 1152 save_sfmmu_tsbsize_stat(kstat_t *kp, ks_instance_t *ksi) 1153 { 1154 struct sfmmu_tsbsize_stat *sfmmut; 1155 1156 assert(kp->ks_data_size == sizeof (struct sfmmu_tsbsize_stat)); 1157 sfmmut = (struct sfmmu_tsbsize_stat *)(kp->ks_data); 1158 1159 SAVE_INT32(ksi, sfmmut, sf_tsbsz_8k); 1160 SAVE_INT32(ksi, sfmmut, sf_tsbsz_16k); 1161 SAVE_INT32(ksi, sfmmut, sf_tsbsz_32k); 1162 SAVE_INT32(ksi, sfmmut, sf_tsbsz_64k); 1163 SAVE_INT32(ksi, sfmmut, sf_tsbsz_128k); 1164 SAVE_INT32(ksi, sfmmut, sf_tsbsz_256k); 1165 SAVE_INT32(ksi, sfmmut, sf_tsbsz_512k); 1166 SAVE_INT32(ksi, sfmmut, sf_tsbsz_1m); 1167 SAVE_INT32(ksi, sfmmut, sf_tsbsz_2m); 1168 SAVE_INT32(ksi, sfmmut, sf_tsbsz_4m); 1169 } 1170 #endif 1171 1172 #ifdef __sparc 1173 static void 1174 save_simmstat(kstat_t *kp, ks_instance_t *ksi) 1175 { 1176 uchar_t *simmstat; 1177 char *simm_buf; 1178 char *list = NULL; 1179 int i; 1180 1181 assert(kp->ks_data_size == sizeof (uchar_t) * SIMM_COUNT); 1182 1183 for (i = 0, simmstat = (uchar_t *)(kp->ks_data); i < SIMM_COUNT - 1; 1184 i++, simmstat++) { 1185 if (list == NULL) { 1186 (void) asprintf(&simm_buf, "%d,", *simmstat); 1187 } else { 1188 (void) asprintf(&simm_buf, "%s%d,", list, *simmstat); 1189 free(list); 1190 } 1191 list = simm_buf; 1192 } 1193 1194 (void) asprintf(&simm_buf, "%s%d", list, *simmstat); 1195 SAVE_STRING_X(ksi, "status", simm_buf); 1196 free(list); 1197 free(simm_buf); 1198 } 1199 #endif 1200 1201 #ifdef __sparc 1202 /* 1203 * Helper function for save_temperature(). 1204 */ 1205 static char * 1206 short_array_to_string(short *shortp, int len) 1207 { 1208 char *list = NULL; 1209 char *list_buf; 1210 1211 for (; len > 1; len--, shortp++) { 1212 if (list == NULL) { 1213 (void) asprintf(&list_buf, "%d,", *shortp); 1214 } else { 1215 (void) asprintf(&list_buf, "%s%d,", list, *shortp); 1216 free(list); 1217 } 1218 list = list_buf; 1219 } 1220 1221 (void) asprintf(&list_buf, "%s%s", list, *shortp); 1222 free(list); 1223 return (list_buf); 1224 } 1225 1226 static void 1227 save_temperature(kstat_t *kp, ks_instance_t *ksi) 1228 { 1229 struct temp_stats *temps = (struct temp_stats *)(kp->ks_data); 1230 char *buf; 1231 int n = 1; 1232 1233 assert(kp->ks_data_size == sizeof (struct temp_stats)); 1234 1235 SAVE_UINT32(ksi, temps, index); 1236 1237 buf = short_array_to_string(temps->l1, L1_SZ); 1238 SAVE_STRING_X(ksi, "l1", buf); 1239 free(buf); 1240 1241 buf = short_array_to_string(temps->l2, L2_SZ); 1242 SAVE_STRING_X(ksi, "l2", buf); 1243 free(buf); 1244 1245 buf = short_array_to_string(temps->l3, L3_SZ); 1246 SAVE_STRING_X(ksi, "l3", buf); 1247 free(buf); 1248 1249 buf = short_array_to_string(temps->l4, L4_SZ); 1250 SAVE_STRING_X(ksi, "l4", buf); 1251 free(buf); 1252 1253 buf = short_array_to_string(temps->l5, L5_SZ); 1254 SAVE_STRING_X(ksi, "l5", buf); 1255 free(buf); 1256 1257 SAVE_INT32(ksi, temps, max); 1258 SAVE_INT32(ksi, temps, min); 1259 SAVE_INT32(ksi, temps, state); 1260 SAVE_INT32(ksi, temps, temp_cnt); 1261 SAVE_INT32(ksi, temps, shutdown_cnt); 1262 SAVE_INT32(ksi, temps, version); 1263 SAVE_INT32(ksi, temps, trend); 1264 SAVE_INT32(ksi, temps, override); 1265 } 1266 #endif 1267 1268 #ifdef __sparc 1269 static void 1270 save_temp_over(kstat_t *kp, ks_instance_t *ksi) 1271 { 1272 short *sh = (short *)(kp->ks_data); 1273 char *value; 1274 1275 assert(kp->ks_data_size == sizeof (short)); 1276 1277 (void) asprintf(&value, "%hu", *sh); 1278 SAVE_STRING_X(ksi, "override", value); 1279 free(value); 1280 } 1281 #endif 1282 1283 #ifdef __sparc 1284 static void 1285 save_ps_shadow(kstat_t *kp, ks_instance_t *ksi) 1286 { 1287 uchar_t *uchar = (uchar_t *)(kp->ks_data); 1288 1289 assert(kp->ks_data_size == SYS_PS_COUNT); 1290 1291 SAVE_CHAR_X(ksi, "core_0", *uchar++); 1292 SAVE_CHAR_X(ksi, "core_1", *uchar++); 1293 SAVE_CHAR_X(ksi, "core_2", *uchar++); 1294 SAVE_CHAR_X(ksi, "core_3", *uchar++); 1295 SAVE_CHAR_X(ksi, "core_4", *uchar++); 1296 SAVE_CHAR_X(ksi, "core_5", *uchar++); 1297 SAVE_CHAR_X(ksi, "core_6", *uchar++); 1298 SAVE_CHAR_X(ksi, "core_7", *uchar++); 1299 SAVE_CHAR_X(ksi, "pps_0", *uchar++); 1300 SAVE_CHAR_X(ksi, "clk_33", *uchar++); 1301 SAVE_CHAR_X(ksi, "clk_50", *uchar++); 1302 SAVE_CHAR_X(ksi, "v5_p", *uchar++); 1303 SAVE_CHAR_X(ksi, "v12_p", *uchar++); 1304 SAVE_CHAR_X(ksi, "v5_aux", *uchar++); 1305 SAVE_CHAR_X(ksi, "v5_p_pch", *uchar++); 1306 SAVE_CHAR_X(ksi, "v12_p_pch", *uchar++); 1307 SAVE_CHAR_X(ksi, "v3_pch", *uchar++); 1308 SAVE_CHAR_X(ksi, "v5_pch", *uchar++); 1309 SAVE_CHAR_X(ksi, "p_fan", *uchar++); 1310 } 1311 #endif 1312 1313 #ifdef __sparc 1314 static void 1315 save_fault_list(kstat_t *kp, ks_instance_t *ksi) 1316 { 1317 struct ft_list *fault; 1318 char name[KSTAT_STRLEN + 7]; 1319 int i; 1320 1321 for (i = 1, fault = (struct ft_list *)(kp->ks_data); 1322 i <= 999999 && i <= kp->ks_data_size / sizeof (struct ft_list); 1323 i++, fault++) { 1324 (void) snprintf(name, sizeof (name), "unit_%d", i); 1325 SAVE_INT32_X(ksi, name, fault->unit); 1326 (void) snprintf(name, sizeof (name), "type_%d", i); 1327 SAVE_INT32_X(ksi, name, fault->type); 1328 (void) snprintf(name, sizeof (name), "fclass_%d", i); 1329 SAVE_INT32_X(ksi, name, fault->fclass); 1330 (void) snprintf(name, sizeof (name), "create_time_%d", i); 1331 SAVE_HRTIME_X(ksi, name, fault->create_time); 1332 (void) snprintf(name, sizeof (name), "msg_%d", i); 1333 SAVE_STRING_X(ksi, name, faultp->msg); 1334 } 1335 } 1336 #endif 1337 1338 static void 1339 save_named(kstat_t *kp, ks_instance_t *ksi) 1340 { 1341 kstat_named_t *knp; 1342 int n; 1343 1344 for (n = kp->ks_ndata, knp = KSTAT_NAMED_PTR(kp); n > 0; n--, knp++) { 1345 switch (knp->data_type) { 1346 case KSTAT_DATA_CHAR: 1347 nvpair_insert(ksi, knp->name, 1348 (ks_value_t *)&knp->value, KSTAT_DATA_CHAR); 1349 break; 1350 case KSTAT_DATA_INT32: 1351 nvpair_insert(ksi, knp->name, 1352 (ks_value_t *)&knp->value, KSTAT_DATA_INT32); 1353 break; 1354 case KSTAT_DATA_UINT32: 1355 nvpair_insert(ksi, knp->name, 1356 (ks_value_t *)&knp->value, KSTAT_DATA_UINT32); 1357 break; 1358 case KSTAT_DATA_INT64: 1359 nvpair_insert(ksi, knp->name, 1360 (ks_value_t *)&knp->value, KSTAT_DATA_INT64); 1361 break; 1362 case KSTAT_DATA_UINT64: 1363 nvpair_insert(ksi, knp->name, 1364 (ks_value_t *)&knp->value, KSTAT_DATA_UINT64); 1365 break; 1366 case KSTAT_DATA_STRING: 1367 SAVE_STRING_X(ksi, knp->name, KSTAT_NAMED_STR_PTR(knp)); 1368 break; 1369 default: 1370 assert(B_FALSE); /* Invalid data type */ 1371 break; 1372 } 1373 } 1374 } 1375 1376 static void 1377 save_intr(kstat_t *kp, ks_instance_t *ksi) 1378 { 1379 kstat_intr_t *intr = KSTAT_INTR_PTR(kp); 1380 char *intr_names[] = {"hard", "soft", "watchdog", "spurious", 1381 "multiple_service"}; 1382 int n; 1383 1384 for (n = 0; n < KSTAT_NUM_INTRS; n++) 1385 SAVE_UINT32_X(ksi, intr_names[n], intr->intrs[n]); 1386 } 1387 1388 static void 1389 save_io(kstat_t *kp, ks_instance_t *ksi) 1390 { 1391 kstat_io_t *ksio = KSTAT_IO_PTR(kp); 1392 1393 SAVE_UINT64(ksi, ksio, nread); 1394 SAVE_UINT64(ksi, ksio, nwritten); 1395 SAVE_UINT32(ksi, ksio, reads); 1396 SAVE_UINT32(ksi, ksio, writes); 1397 SAVE_HRTIME(ksi, ksio, wtime); 1398 SAVE_HRTIME(ksi, ksio, wlentime); 1399 SAVE_HRTIME(ksi, ksio, wlastupdate); 1400 SAVE_HRTIME(ksi, ksio, rtime); 1401 SAVE_HRTIME(ksi, ksio, rlentime); 1402 SAVE_HRTIME(ksi, ksio, rlastupdate); 1403 SAVE_UINT32(ksi, ksio, wcnt); 1404 SAVE_UINT32(ksi, ksio, rcnt); 1405 } 1406 1407 static void 1408 save_timer(kstat_t *kp, ks_instance_t *ksi) 1409 { 1410 kstat_timer_t *ktimer = KSTAT_TIMER_PTR(kp); 1411 1412 SAVE_STRING(ksi, ktimer, name); 1413 SAVE_UINT64(ksi, ktimer, num_events); 1414 SAVE_HRTIME(ksi, ktimer, elapsed_time); 1415 SAVE_HRTIME(ksi, ktimer, min_time); 1416 SAVE_HRTIME(ksi, ktimer, max_time); 1417 SAVE_HRTIME(ksi, ktimer, start_time); 1418 SAVE_HRTIME(ksi, ktimer, stop_time); 1419 }