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