8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / stat / kstat / kstat.c
blob236437face4961cfc88c63a362ed83a143ae791a
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
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.
30 * Display kernel statistics
32 * This is a reimplementation of the perl kstat command originally found
33 * under usr/src/cmd/kstat/kstat.pl
35 * Incompatibilities:
36 * - perl regular expressions replaced with extended REs bracketed by '/'
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
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>
64 #include "kstat.h"
65 #include "statcommon.h"
67 char *cmdname = "kstat"; /* Name of this command */
68 int caught_cont = 0; /* Have caught a SIGCONT */
70 static uint_t g_timestamp_fmt = NODATE;
72 /* Helper flag - header was printed already? */
73 static boolean_t g_headerflg;
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};
83 static boolean_t g_matched = B_FALSE;
85 /* Sorted list of kstat instances */
86 static list_t instances_list;
87 static list_t selector_list;
89 int
90 main(int argc, char **argv)
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;
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);
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.
118 list_create(&selector_list, sizeof (ks_selector_t),
119 offsetof(ks_selector_t, ks_next));
121 nselector = new_selector();
124 * Parse named command line arguments.
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':
141 * If we're printing JSON, we're going to force numeric
142 * representation to be in the C locale to assure that
143 * the decimal point is compliant with RFC 7159 (i.e.,
144 * ASCII 0x2e).
146 (void) setlocale(LC_NUMERIC, "C");
147 g_jflg = B_TRUE;
148 break;
149 case 'l':
150 g_pflg = g_lflg = B_TRUE;
151 break;
152 case 'p':
153 g_pflg = B_TRUE;
154 break;
155 case 'T':
156 switch (*optarg) {
157 case 'd':
158 g_timestamp_fmt = DDATE;
159 break;
160 case 'u':
161 g_timestamp_fmt = UDATE;
162 break;
163 default:
164 errflg = B_TRUE;
166 break;
167 case 'm':
168 nselflg = B_TRUE;
169 nselector->ks_module.pstr =
170 (char *)ks_safe_strdup(optarg);
171 break;
172 case 'i':
173 nselflg = B_TRUE;
174 nselector->ks_instance.pstr =
175 (char *)ks_safe_strdup(optarg);
176 break;
177 case 'n':
178 nselflg = B_TRUE;
179 nselector->ks_name.pstr =
180 (char *)ks_safe_strdup(optarg);
181 break;
182 case 's':
183 nselflg = B_TRUE;
184 nselector->ks_statistic.pstr =
185 (char *)ks_safe_strdup(optarg);
186 break;
187 case 'c':
188 g_ks_class.pstr =
189 (char *)ks_safe_strdup(optarg);
190 break;
191 default:
192 errflg = B_TRUE;
193 break;
196 if (g_qflg && (g_jflg || g_pflg)) {
197 (void) fprintf(stderr, gettext(
198 "-q and -lpj are mutually exclusive\n"));
199 errflg = B_TRUE;
202 if (errflg) {
203 usage();
204 exit(2);
207 argc -= optind;
208 argv += optind;
211 * Consume the rest of the command line. Parsing the
212 * unnamed command line arguments.
214 while (argc--) {
215 errno = 0;
216 tmp = strtoul(*argv, &q, 10);
217 if (tmp == ULONG_MAX && errno == ERANGE) {
218 if (n == 0) {
219 (void) fprintf(stderr, gettext(
220 "Interval is too large\n"));
221 } else if (n == 1) {
222 (void) fprintf(stderr, gettext(
223 "Count is too large\n"));
225 usage();
226 exit(2);
229 if (errno != 0 || *q != '\0') {
230 m = 0;
231 uselector = new_selector();
232 while ((q = (char *)strsep(argv, ":")) != NULL) {
233 m++;
234 if (m > 4) {
235 free(uselector);
236 usage();
237 exit(2);
240 if (*q != '\0') {
241 switch (m) {
242 case 1:
243 uselector->ks_module.pstr =
244 (char *)ks_safe_strdup(q);
245 break;
246 case 2:
247 uselector->ks_instance.pstr =
248 (char *)ks_safe_strdup(q);
249 break;
250 case 3:
251 uselector->ks_name.pstr =
252 (char *)ks_safe_strdup(q);
253 break;
254 case 4:
255 uselector->ks_statistic.pstr =
256 (char *)ks_safe_strdup(q);
257 break;
258 default:
259 assert(B_FALSE);
264 uselflg = B_TRUE;
265 list_insert_tail(&selector_list, uselector);
266 } else {
267 if (tmp < 1) {
268 if (n == 0) {
269 (void) fprintf(stderr, gettext(
270 "Interval must be an "
271 "integer >= 1"));
272 } else if (n == 1) {
273 (void) fprintf(stderr, gettext(
274 "Count must be an integer >= 1"));
276 usage();
277 exit(2);
278 } else {
279 if (n == 0) {
280 interval = tmp;
281 count = -1;
282 } else if (n == 1) {
283 count = tmp;
284 } else {
285 usage();
286 exit(2);
289 n++;
291 argv++;
295 * Check if we founded a named selector on the cmdline.
297 if (uselflg) {
298 if (nselflg) {
299 (void) fprintf(stderr, gettext(
300 "[module[:instance[:name[:statistic]]]] and "
301 "-m -i -n -s are mutually exclusive"));
302 usage();
303 exit(2);
304 } else {
305 free(nselector);
307 } else {
308 list_insert_tail(&selector_list, nselector);
311 assert(!list_is_empty(&selector_list));
313 list_create(&instances_list, sizeof (ks_instance_t),
314 offsetof(ks_instance_t, ks_next));
316 while ((kc = kstat_open()) == NULL) {
317 if (errno == EAGAIN) {
318 (void) poll(NULL, 0, 200);
319 } else {
320 perror("kstat_open");
321 exit(3);
325 if (count > 1) {
326 if (signal(SIGCONT, cont_handler) == SIG_ERR) {
327 (void) fprintf(stderr, gettext(
328 "signal failed"));
329 exit(3);
333 period_n = (hrtime_t)interval * NANOSEC;
334 start_n = gethrtime();
336 while (count == -1 || count-- > 0) {
337 ks_instances_read(kc);
338 ks_instances_print();
340 if (interval && count) {
341 ks_sleep_until(&start_n, period_n, infinite_cycles,
342 &caught_cont);
343 (void) kstat_chain_update(kc);
344 (void) putchar('\n');
348 (void) kstat_close(kc);
351 * Return a non-zero exit code if we didn't match anything.
353 return (g_matched ? 0 : 1);
357 * Print usage.
359 static void
360 usage(void)
362 (void) fprintf(stderr, gettext(
363 "Usage:\n"
364 "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ]\n"
365 " [ -m module ] [ -i instance ] [ -n name ] [ -s statistic ]\n"
366 " [ interval [ count ] ]\n"
367 "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ]\n"
368 " [ module[:instance[:name[:statistic]]] ... ]\n"
369 " [ interval [ count ] ]\n"));
373 * Sort compare function.
375 static int
376 compare_instances(ks_instance_t *l_arg, ks_instance_t *r_arg)
378 int rval;
380 rval = strcasecmp(l_arg->ks_module, r_arg->ks_module);
381 if (rval == 0) {
382 if (l_arg->ks_instance == r_arg->ks_instance) {
383 return (strcasecmp(l_arg->ks_name, r_arg->ks_name));
384 } else if (l_arg->ks_instance < r_arg->ks_instance) {
385 return (-1);
386 } else {
387 return (1);
389 } else {
390 return (rval);
394 static char *
395 ks_safe_strdup(char *str)
397 char *ret;
399 if (str == NULL) {
400 return (NULL);
403 while ((ret = strdup(str)) == NULL) {
404 if (errno == EAGAIN) {
405 (void) poll(NULL, 0, 200);
406 } else {
407 perror("strdup");
408 exit(3);
412 return (ret);
415 static void
416 ks_sleep_until(hrtime_t *wakeup, hrtime_t interval, int forever,
417 int *caught_cont)
419 hrtime_t now, pause, pause_left;
420 struct timespec pause_tv;
421 int status;
423 now = gethrtime();
424 pause = *wakeup + interval - now;
426 if (pause <= 0 || pause < (interval / 4)) {
427 if (forever || *caught_cont) {
428 *wakeup = now + interval;
429 pause = interval;
430 } else {
431 pause = interval / 2;
432 *wakeup += interval;
434 } else {
435 *wakeup += interval;
438 if (pause < 1000) {
439 return;
442 pause_left = pause;
443 do {
444 pause_tv.tv_sec = pause_left / NANOSEC;
445 pause_tv.tv_nsec = pause_left % NANOSEC;
446 status = nanosleep(&pause_tv, (struct timespec *)NULL);
447 if (status < 0) {
448 if (errno == EINTR) {
449 now = gethrtime();
450 pause_left = *wakeup - now;
451 if (pause_left < 1000) {
452 return;
454 } else {
455 perror("nanosleep");
456 exit(3);
459 } while (status != 0);
463 * Inserts an instance in the per selector list.
465 static void
466 nvpair_insert(ks_instance_t *ksi, char *name, ks_value_t *value,
467 uchar_t data_type)
469 ks_nvpair_t *instance;
470 ks_nvpair_t *tmp;
472 instance = (ks_nvpair_t *)malloc(sizeof (ks_nvpair_t));
473 if (instance == NULL) {
474 perror("malloc");
475 exit(3);
478 (void) strlcpy(instance->name, name, KSTAT_STRLEN);
479 (void) memcpy(&instance->value, value, sizeof (ks_value_t));
480 instance->data_type = data_type;
482 tmp = list_head(&ksi->ks_nvlist);
483 while (tmp != NULL && strcasecmp(instance->name, tmp->name) > 0)
484 tmp = list_next(&ksi->ks_nvlist, tmp);
486 list_insert_before(&ksi->ks_nvlist, tmp, instance);
490 * Allocates a new all-matching selector.
492 static ks_selector_t *
493 new_selector(void)
495 ks_selector_t *selector;
497 selector = (ks_selector_t *)malloc(sizeof (ks_selector_t));
498 if (selector == NULL) {
499 perror("malloc");
500 exit(3);
503 list_link_init(&selector->ks_next);
505 selector->ks_module.pstr = "*";
506 selector->ks_instance.pstr = "*";
507 selector->ks_name.pstr = "*";
508 selector->ks_statistic.pstr = "*";
510 return (selector);
514 * This function was taken from the perl kstat module code - please
515 * see for further comments there.
517 static kstat_raw_reader_t
518 lookup_raw_kstat_fn(char *module, char *name)
520 char key[KSTAT_STRLEN * 2];
521 register char *f, *t;
522 int n = 0;
524 for (f = module, t = key; *f != '\0'; f++, t++) {
525 while (*f != '\0' && isdigit(*f))
526 f++;
527 *t = *f;
529 *t++ = ':';
531 for (f = name; *f != '\0'; f++, t++) {
532 while (*f != '\0' && isdigit(*f))
533 f++;
534 *t = *f;
536 *t = '\0';
538 while (ks_raw_lookup[n].fn != NULL) {
539 if (strncmp(ks_raw_lookup[n].name, key, strlen(key)) == 0)
540 return (ks_raw_lookup[n].fn);
541 n++;
544 return (0);
548 * Match a string against a shell glob or extended regular expression.
550 static boolean_t
551 ks_match(const char *str, ks_pattern_t *pattern)
553 int regcode;
554 char *regstr;
555 char *errbuf;
556 size_t bufsz;
558 if (pattern->pstr != NULL && gmatch(pattern->pstr, "/*/") != 0) {
559 /* All regex patterns are strdup'd copies */
560 regstr = pattern->pstr + 1;
561 *(strrchr(regstr, '/')) = '\0';
563 regcode = regcomp(&pattern->preg, regstr,
564 REG_EXTENDED | REG_NOSUB);
565 if (regcode != 0) {
566 bufsz = regerror(regcode, NULL, NULL, 0);
567 if (bufsz != 0) {
568 errbuf = malloc(bufsz);
569 if (errbuf == NULL) {
570 perror("malloc");
571 exit(3);
573 (void) regerror(regcode, NULL, errbuf, bufsz);
574 (void) fprintf(stderr, "kstat: %s\n", errbuf);
576 usage();
577 exit(2);
580 pattern->pstr = NULL;
583 if (pattern->pstr == NULL) {
584 return (regexec(&pattern->preg, str, 0, NULL, 0) == 0);
587 return ((gmatch(str, pattern->pstr) != 0));
591 * Iterate over all kernel statistics and save matches.
593 static void
594 ks_instances_read(kstat_ctl_t *kc)
596 kstat_raw_reader_t save_raw = NULL;
597 kid_t id;
598 ks_selector_t *selector;
599 ks_instance_t *ksi;
600 ks_instance_t *tmp;
601 kstat_t *kp;
602 boolean_t skip;
604 for (kp = kc->kc_chain; kp != NULL; kp = kp->ks_next) {
605 /* Don't bother storing the kstat headers */
606 if (strncmp(kp->ks_name, "kstat_", 6) == 0) {
607 continue;
610 /* Don't bother storing raw stats we don't understand */
611 if (kp->ks_type == KSTAT_TYPE_RAW) {
612 save_raw = lookup_raw_kstat_fn(kp->ks_module,
613 kp->ks_name);
614 if (save_raw == NULL) {
615 #ifdef REPORT_UNKNOWN
616 (void) fprintf(stderr,
617 "Unknown kstat type %s:%d:%s - "
618 "%d of size %d\n", kp->ks_module,
619 kp->ks_instance, kp->ks_name,
620 kp->ks_ndata, kp->ks_data_size);
621 #endif
622 continue;
627 * Iterate over the list of selectors and skip
628 * instances we dont want. We filter for statistics
629 * later, as we dont know them yet.
631 skip = B_TRUE;
632 selector = list_head(&selector_list);
633 while (selector != NULL) {
634 if (ks_match(kp->ks_module, &selector->ks_module) &&
635 ks_match(kp->ks_name, &selector->ks_name)) {
636 skip = B_FALSE;
637 break;
639 selector = list_next(&selector_list, selector);
642 if (skip) {
643 continue;
647 * Allocate a new instance and fill in the values
648 * we know so far.
650 ksi = (ks_instance_t *)malloc(sizeof (ks_instance_t));
651 if (ksi == NULL) {
652 perror("malloc");
653 exit(3);
656 list_link_init(&ksi->ks_next);
658 (void) strlcpy(ksi->ks_module, kp->ks_module, KSTAT_STRLEN);
659 (void) strlcpy(ksi->ks_name, kp->ks_name, KSTAT_STRLEN);
660 (void) strlcpy(ksi->ks_class, kp->ks_class, KSTAT_STRLEN);
662 ksi->ks_instance = kp->ks_instance;
663 ksi->ks_snaptime = kp->ks_snaptime;
664 ksi->ks_type = kp->ks_type;
666 list_create(&ksi->ks_nvlist, sizeof (ks_nvpair_t),
667 offsetof(ks_nvpair_t, nv_next));
669 SAVE_HRTIME_X(ksi, "crtime", kp->ks_crtime);
670 if (g_pflg) {
671 SAVE_STRING_X(ksi, "class", kp->ks_class);
674 /* Insert this instance into a sorted list */
675 tmp = list_head(&instances_list);
676 while (tmp != NULL && compare_instances(ksi, tmp) > 0)
677 tmp = list_next(&instances_list, tmp);
679 list_insert_before(&instances_list, tmp, ksi);
681 /* Read the actual statistics */
682 id = kstat_read(kc, kp, NULL);
683 if (id == -1) {
684 #ifdef REPORT_UNKNOWN
685 perror("kstat_read");
686 #endif
687 continue;
690 SAVE_HRTIME_X(ksi, "snaptime", kp->ks_snaptime);
692 switch (kp->ks_type) {
693 case KSTAT_TYPE_RAW:
694 save_raw(kp, ksi);
695 break;
696 case KSTAT_TYPE_NAMED:
697 save_named(kp, ksi);
698 break;
699 case KSTAT_TYPE_INTR:
700 save_intr(kp, ksi);
701 break;
702 case KSTAT_TYPE_IO:
703 save_io(kp, ksi);
704 break;
705 case KSTAT_TYPE_TIMER:
706 save_timer(kp, ksi);
707 break;
708 default:
709 assert(B_FALSE); /* Invalid type */
710 break;
716 * Print the value of a name-value pair.
718 static void
719 ks_value_print(ks_nvpair_t *nvpair)
721 switch (nvpair->data_type) {
722 case KSTAT_DATA_CHAR:
723 (void) fprintf(stdout, "%s", nvpair->value.c);
724 break;
725 case KSTAT_DATA_INT32:
726 (void) fprintf(stdout, "%d", nvpair->value.i32);
727 break;
728 case KSTAT_DATA_UINT32:
729 (void) fprintf(stdout, "%u", nvpair->value.ui32);
730 break;
731 case KSTAT_DATA_INT64:
732 (void) fprintf(stdout, "%lld", nvpair->value.i64);
733 break;
734 case KSTAT_DATA_UINT64:
735 (void) fprintf(stdout, "%llu", nvpair->value.ui64);
736 break;
737 case KSTAT_DATA_STRING:
738 (void) fprintf(stdout, "%s", KSTAT_NAMED_STR_PTR(nvpair));
739 break;
740 case KSTAT_DATA_HRTIME:
741 if (nvpair->value.ui64 == 0)
742 (void) fprintf(stdout, "0");
743 else
744 (void) fprintf(stdout, "%.9f",
745 nvpair->value.ui64 / 1000000000.0);
746 break;
747 default:
748 assert(B_FALSE);
753 * Print a single instance.
755 /*ARGSUSED*/
756 static void
757 ks_instance_print(ks_instance_t *ksi, ks_nvpair_t *nvpair, boolean_t last)
759 if (g_headerflg) {
760 if (!g_pflg) {
761 (void) fprintf(stdout, DFLT_FMT,
762 ksi->ks_module, ksi->ks_instance,
763 ksi->ks_name, ksi->ks_class);
765 g_headerflg = B_FALSE;
768 if (g_pflg) {
769 (void) fprintf(stdout, KS_PFMT,
770 ksi->ks_module, ksi->ks_instance,
771 ksi->ks_name, nvpair->name);
772 if (!g_lflg) {
773 (void) putchar(g_cflg ? ':': '\t');
774 ks_value_print(nvpair);
776 } else {
777 (void) fprintf(stdout, KS_DFMT, nvpair->name);
778 ks_value_print(nvpair);
781 (void) putchar('\n');
785 * Print a C string as a JSON string.
787 static void
788 ks_print_json_string(const char *str)
790 char c;
792 (void) putchar('"');
794 while ((c = *str++) != '\0') {
796 * For readability, we use the allowed alternate escape
797 * sequence for quote, question mark, reverse solidus (look
798 * it up!), newline and tab -- and use the universal escape
799 * sequence for all other control characters.
801 switch (c) {
802 case '"':
803 case '?':
804 case '\\':
805 (void) fprintf(stdout, "\\%c", c);
806 break;
808 case '\n':
809 (void) fprintf(stdout, "\\n");
810 break;
812 case '\t':
813 (void) fprintf(stdout, "\\t");
814 break;
816 default:
818 * By escaping those characters for which isprint(3C)
819 * is false, we escape both the RFC 7159 mandated
820 * escaped range of 0x01 through 0x1f as well as DEL
821 * (0x7f -- the control character that RFC 7159 forgot)
822 * and then everything else that's unprintable for
823 * good measure.
825 if (!isprint(c)) {
826 (void) fprintf(stdout, "\\u%04hhx", (uint8_t)c);
827 break;
830 (void) putchar(c);
831 break;
835 (void) putchar('"');
839 * Print a single instance in JSON format.
841 static void
842 ks_instance_print_json(ks_instance_t *ksi, ks_nvpair_t *nvpair, boolean_t last)
844 static int headers;
846 if (g_headerflg) {
847 if (headers++ > 0)
848 (void) fprintf(stdout, ", ");
850 (void) fprintf(stdout, "{\n\t\"module\": ");
851 ks_print_json_string(ksi->ks_module);
853 (void) fprintf(stdout,
854 ",\n\t\"instance\": %d,\n\t\"name\": ", ksi->ks_instance);
855 ks_print_json_string(ksi->ks_name);
857 (void) fprintf(stdout, ",\n\t\"class\": ");
858 ks_print_json_string(ksi->ks_class);
860 (void) fprintf(stdout, ",\n\t\"type\": %d,\n", ksi->ks_type);
862 if (ksi->ks_snaptime == 0)
863 (void) fprintf(stdout, "\t\"snaptime\": 0,\n");
864 else
865 (void) fprintf(stdout, "\t\"snaptime\": %.9f,\n",
866 ksi->ks_snaptime / 1000000000.0);
868 (void) fprintf(stdout, "\t\"data\": {\n");
870 g_headerflg = B_FALSE;
873 (void) fprintf(stdout, "\t\t");
874 ks_print_json_string(nvpair->name);
875 (void) fprintf(stdout, ": ");
877 switch (nvpair->data_type) {
878 case KSTAT_DATA_CHAR:
879 ks_print_json_string(nvpair->value.c);
880 break;
882 case KSTAT_DATA_STRING:
883 ks_print_json_string(KSTAT_NAMED_STR_PTR(nvpair));
884 break;
886 default:
887 ks_value_print(nvpair);
888 break;
891 if (!last)
892 (void) putchar(',');
894 (void) putchar('\n');
898 * Print all instances.
900 static void
901 ks_instances_print(void)
903 ks_selector_t *selector;
904 ks_instance_t *ksi, *ktmp;
905 ks_nvpair_t *nvpair, *ntmp, *next;
906 void (*ks_print_fn)(ks_instance_t *, ks_nvpair_t *, boolean_t);
907 char *ks_number;
909 if (g_timestamp_fmt != NODATE)
910 print_timestamp(g_timestamp_fmt);
912 if (g_jflg) {
913 ks_print_fn = &ks_instance_print_json;
914 (void) putchar('[');
915 } else {
916 ks_print_fn = &ks_instance_print;
919 /* Iterate over each selector */
920 selector = list_head(&selector_list);
921 while (selector != NULL) {
923 /* Iterate over each instance */
924 for (ksi = list_head(&instances_list); ksi != NULL;
925 ksi = list_next(&instances_list, ksi)) {
927 (void) asprintf(&ks_number, "%d", ksi->ks_instance);
928 if (!(ks_match(ksi->ks_module, &selector->ks_module) &&
929 ks_match(ksi->ks_name, &selector->ks_name) &&
930 ks_match(ks_number, &selector->ks_instance) &&
931 ks_match(ksi->ks_class, &g_ks_class))) {
932 free(ks_number);
933 continue;
936 free(ks_number);
938 g_headerflg = B_TRUE;
941 * Find our first statistic to print.
943 for (nvpair = list_head(&ksi->ks_nvlist);
944 nvpair != NULL;
945 nvpair = list_next(&ksi->ks_nvlist, nvpair)) {
946 if (ks_match(nvpair->name,
947 &selector->ks_statistic))
948 break;
951 while (nvpair != NULL) {
952 boolean_t last;
955 * Find the next statistic to print so we can
956 * indicate to the print function if this
957 * statistic is the last to be printed for
958 * this instance.
960 for (next = list_next(&ksi->ks_nvlist, nvpair);
961 next != NULL;
962 next = list_next(&ksi->ks_nvlist, next)) {
963 if (ks_match(next->name,
964 &selector->ks_statistic))
965 break;
968 g_matched = B_TRUE;
969 last = next == NULL ? B_TRUE : B_FALSE;
971 if (!g_qflg)
972 (*ks_print_fn)(ksi, nvpair, last);
974 nvpair = next;
977 if (!g_headerflg) {
978 if (g_jflg) {
979 (void) fprintf(stdout, "\t}\n}");
980 } else if (!g_pflg) {
981 (void) putchar('\n');
986 selector = list_next(&selector_list, selector);
989 if (g_jflg)
990 (void) fprintf(stdout, "]\n");
992 (void) fflush(stdout);
994 /* Free the instances list */
995 ksi = list_head(&instances_list);
996 while (ksi != NULL) {
997 nvpair = list_head(&ksi->ks_nvlist);
998 while (nvpair != NULL) {
999 ntmp = nvpair;
1000 nvpair = list_next(&ksi->ks_nvlist, nvpair);
1001 list_remove(&ksi->ks_nvlist, ntmp);
1002 if (ntmp->data_type == KSTAT_DATA_STRING)
1003 free(ntmp->value.str.addr.ptr);
1004 free(ntmp);
1007 ktmp = ksi;
1008 ksi = list_next(&instances_list, ksi);
1009 list_remove(&instances_list, ktmp);
1010 list_destroy(&ktmp->ks_nvlist);
1011 free(ktmp);
1015 static void
1016 save_cpu_stat(kstat_t *kp, ks_instance_t *ksi)
1018 cpu_stat_t *stat;
1019 cpu_sysinfo_t *sysinfo;
1020 cpu_syswait_t *syswait;
1021 cpu_vminfo_t *vminfo;
1023 stat = (cpu_stat_t *)(kp->ks_data);
1024 sysinfo = &stat->cpu_sysinfo;
1025 syswait = &stat->cpu_syswait;
1026 vminfo = &stat->cpu_vminfo;
1028 SAVE_UINT32_X(ksi, "idle", sysinfo->cpu[CPU_IDLE]);
1029 SAVE_UINT32_X(ksi, "user", sysinfo->cpu[CPU_USER]);
1030 SAVE_UINT32_X(ksi, "kernel", sysinfo->cpu[CPU_KERNEL]);
1031 SAVE_UINT32_X(ksi, "wait", sysinfo->cpu[CPU_WAIT]);
1032 SAVE_UINT32_X(ksi, "wait_io", sysinfo->wait[W_IO]);
1033 SAVE_UINT32_X(ksi, "wait_swap", sysinfo->wait[W_SWAP]);
1034 SAVE_UINT32_X(ksi, "wait_pio", sysinfo->wait[W_PIO]);
1035 SAVE_UINT32(ksi, sysinfo, bread);
1036 SAVE_UINT32(ksi, sysinfo, bwrite);
1037 SAVE_UINT32(ksi, sysinfo, lread);
1038 SAVE_UINT32(ksi, sysinfo, lwrite);
1039 SAVE_UINT32(ksi, sysinfo, phread);
1040 SAVE_UINT32(ksi, sysinfo, phwrite);
1041 SAVE_UINT32(ksi, sysinfo, pswitch);
1042 SAVE_UINT32(ksi, sysinfo, trap);
1043 SAVE_UINT32(ksi, sysinfo, intr);
1044 SAVE_UINT32(ksi, sysinfo, syscall);
1045 SAVE_UINT32(ksi, sysinfo, sysread);
1046 SAVE_UINT32(ksi, sysinfo, syswrite);
1047 SAVE_UINT32(ksi, sysinfo, sysfork);
1048 SAVE_UINT32(ksi, sysinfo, sysvfork);
1049 SAVE_UINT32(ksi, sysinfo, sysexec);
1050 SAVE_UINT32(ksi, sysinfo, readch);
1051 SAVE_UINT32(ksi, sysinfo, writech);
1052 SAVE_UINT32(ksi, sysinfo, rcvint);
1053 SAVE_UINT32(ksi, sysinfo, xmtint);
1054 SAVE_UINT32(ksi, sysinfo, mdmint);
1055 SAVE_UINT32(ksi, sysinfo, rawch);
1056 SAVE_UINT32(ksi, sysinfo, canch);
1057 SAVE_UINT32(ksi, sysinfo, outch);
1058 SAVE_UINT32(ksi, sysinfo, msg);
1059 SAVE_UINT32(ksi, sysinfo, sema);
1060 SAVE_UINT32(ksi, sysinfo, namei);
1061 SAVE_UINT32(ksi, sysinfo, ufsiget);
1062 SAVE_UINT32(ksi, sysinfo, ufsdirblk);
1063 SAVE_UINT32(ksi, sysinfo, ufsipage);
1064 SAVE_UINT32(ksi, sysinfo, ufsinopage);
1065 SAVE_UINT32(ksi, sysinfo, inodeovf);
1066 SAVE_UINT32(ksi, sysinfo, fileovf);
1067 SAVE_UINT32(ksi, sysinfo, procovf);
1068 SAVE_UINT32(ksi, sysinfo, intrthread);
1069 SAVE_UINT32(ksi, sysinfo, intrblk);
1070 SAVE_UINT32(ksi, sysinfo, idlethread);
1071 SAVE_UINT32(ksi, sysinfo, inv_swtch);
1072 SAVE_UINT32(ksi, sysinfo, nthreads);
1073 SAVE_UINT32(ksi, sysinfo, cpumigrate);
1074 SAVE_UINT32(ksi, sysinfo, xcalls);
1075 SAVE_UINT32(ksi, sysinfo, mutex_adenters);
1076 SAVE_UINT32(ksi, sysinfo, rw_rdfails);
1077 SAVE_UINT32(ksi, sysinfo, rw_wrfails);
1078 SAVE_UINT32(ksi, sysinfo, modload);
1079 SAVE_UINT32(ksi, sysinfo, modunload);
1080 SAVE_UINT32(ksi, sysinfo, bawrite);
1081 #ifdef STATISTICS /* see header file */
1082 SAVE_UINT32(ksi, sysinfo, rw_enters);
1083 SAVE_UINT32(ksi, sysinfo, win_uo_cnt);
1084 SAVE_UINT32(ksi, sysinfo, win_uu_cnt);
1085 SAVE_UINT32(ksi, sysinfo, win_so_cnt);
1086 SAVE_UINT32(ksi, sysinfo, win_su_cnt);
1087 SAVE_UINT32(ksi, sysinfo, win_suo_cnt);
1088 #endif
1090 SAVE_INT32(ksi, syswait, iowait);
1091 SAVE_INT32(ksi, syswait, swap);
1092 SAVE_INT32(ksi, syswait, physio);
1094 SAVE_UINT32(ksi, vminfo, pgrec);
1095 SAVE_UINT32(ksi, vminfo, pgfrec);
1096 SAVE_UINT32(ksi, vminfo, pgin);
1097 SAVE_UINT32(ksi, vminfo, pgpgin);
1098 SAVE_UINT32(ksi, vminfo, pgout);
1099 SAVE_UINT32(ksi, vminfo, pgpgout);
1100 SAVE_UINT32(ksi, vminfo, swapin);
1101 SAVE_UINT32(ksi, vminfo, pgswapin);
1102 SAVE_UINT32(ksi, vminfo, swapout);
1103 SAVE_UINT32(ksi, vminfo, pgswapout);
1104 SAVE_UINT32(ksi, vminfo, zfod);
1105 SAVE_UINT32(ksi, vminfo, dfree);
1106 SAVE_UINT32(ksi, vminfo, scan);
1107 SAVE_UINT32(ksi, vminfo, rev);
1108 SAVE_UINT32(ksi, vminfo, hat_fault);
1109 SAVE_UINT32(ksi, vminfo, as_fault);
1110 SAVE_UINT32(ksi, vminfo, maj_fault);
1111 SAVE_UINT32(ksi, vminfo, cow_fault);
1112 SAVE_UINT32(ksi, vminfo, prot_fault);
1113 SAVE_UINT32(ksi, vminfo, softlock);
1114 SAVE_UINT32(ksi, vminfo, kernel_asflt);
1115 SAVE_UINT32(ksi, vminfo, pgrrun);
1116 SAVE_UINT32(ksi, vminfo, execpgin);
1117 SAVE_UINT32(ksi, vminfo, execpgout);
1118 SAVE_UINT32(ksi, vminfo, execfree);
1119 SAVE_UINT32(ksi, vminfo, anonpgin);
1120 SAVE_UINT32(ksi, vminfo, anonpgout);
1121 SAVE_UINT32(ksi, vminfo, anonfree);
1122 SAVE_UINT32(ksi, vminfo, fspgin);
1123 SAVE_UINT32(ksi, vminfo, fspgout);
1124 SAVE_UINT32(ksi, vminfo, fsfree);
1127 static void
1128 save_var(kstat_t *kp, ks_instance_t *ksi)
1130 struct var *var = (struct var *)(kp->ks_data);
1132 assert(kp->ks_data_size == sizeof (struct var));
1134 SAVE_INT32(ksi, var, v_buf);
1135 SAVE_INT32(ksi, var, v_call);
1136 SAVE_INT32(ksi, var, v_proc);
1137 SAVE_INT32(ksi, var, v_maxupttl);
1138 SAVE_INT32(ksi, var, v_nglobpris);
1139 SAVE_INT32(ksi, var, v_maxsyspri);
1140 SAVE_INT32(ksi, var, v_clist);
1141 SAVE_INT32(ksi, var, v_maxup);
1142 SAVE_INT32(ksi, var, v_hbuf);
1143 SAVE_INT32(ksi, var, v_hmask);
1144 SAVE_INT32(ksi, var, v_pbuf);
1145 SAVE_INT32(ksi, var, v_sptmap);
1146 SAVE_INT32(ksi, var, v_maxpmem);
1147 SAVE_INT32(ksi, var, v_autoup);
1148 SAVE_INT32(ksi, var, v_bufhwm);
1151 static void
1152 save_ncstats(kstat_t *kp, ks_instance_t *ksi)
1154 struct ncstats *ncstats = (struct ncstats *)(kp->ks_data);
1156 assert(kp->ks_data_size == sizeof (struct ncstats));
1158 SAVE_INT32(ksi, ncstats, hits);
1159 SAVE_INT32(ksi, ncstats, misses);
1160 SAVE_INT32(ksi, ncstats, enters);
1161 SAVE_INT32(ksi, ncstats, dbl_enters);
1162 SAVE_INT32(ksi, ncstats, long_enter);
1163 SAVE_INT32(ksi, ncstats, long_look);
1164 SAVE_INT32(ksi, ncstats, move_to_front);
1165 SAVE_INT32(ksi, ncstats, purges);
1168 static void
1169 save_sysinfo(kstat_t *kp, ks_instance_t *ksi)
1171 sysinfo_t *sysinfo = (sysinfo_t *)(kp->ks_data);
1173 assert(kp->ks_data_size == sizeof (sysinfo_t));
1175 SAVE_UINT32(ksi, sysinfo, updates);
1176 SAVE_UINT32(ksi, sysinfo, runque);
1177 SAVE_UINT32(ksi, sysinfo, runocc);
1178 SAVE_UINT32(ksi, sysinfo, swpque);
1179 SAVE_UINT32(ksi, sysinfo, swpocc);
1180 SAVE_UINT32(ksi, sysinfo, waiting);
1183 static void
1184 save_vminfo(kstat_t *kp, ks_instance_t *ksi)
1186 vminfo_t *vminfo = (vminfo_t *)(kp->ks_data);
1188 assert(kp->ks_data_size == sizeof (vminfo_t));
1190 SAVE_UINT64(ksi, vminfo, freemem);
1191 SAVE_UINT64(ksi, vminfo, swap_resv);
1192 SAVE_UINT64(ksi, vminfo, swap_alloc);
1193 SAVE_UINT64(ksi, vminfo, swap_avail);
1194 SAVE_UINT64(ksi, vminfo, swap_free);
1195 SAVE_UINT64(ksi, vminfo, updates);
1198 static void
1199 save_nfs(kstat_t *kp, ks_instance_t *ksi)
1201 struct mntinfo_kstat *mntinfo = (struct mntinfo_kstat *)(kp->ks_data);
1203 assert(kp->ks_data_size == sizeof (struct mntinfo_kstat));
1205 SAVE_STRING(ksi, mntinfo, mik_proto);
1206 SAVE_UINT32(ksi, mntinfo, mik_vers);
1207 SAVE_UINT32(ksi, mntinfo, mik_flags);
1208 SAVE_UINT32(ksi, mntinfo, mik_secmod);
1209 SAVE_UINT32(ksi, mntinfo, mik_curread);
1210 SAVE_UINT32(ksi, mntinfo, mik_curwrite);
1211 SAVE_INT32(ksi, mntinfo, mik_timeo);
1212 SAVE_INT32(ksi, mntinfo, mik_retrans);
1213 SAVE_UINT32(ksi, mntinfo, mik_acregmin);
1214 SAVE_UINT32(ksi, mntinfo, mik_acregmax);
1215 SAVE_UINT32(ksi, mntinfo, mik_acdirmin);
1216 SAVE_UINT32(ksi, mntinfo, mik_acdirmax);
1217 SAVE_UINT32_X(ksi, "lookup_srtt", mntinfo->mik_timers[0].srtt);
1218 SAVE_UINT32_X(ksi, "lookup_deviate", mntinfo->mik_timers[0].deviate);
1219 SAVE_UINT32_X(ksi, "lookup_rtxcur", mntinfo->mik_timers[0].rtxcur);
1220 SAVE_UINT32_X(ksi, "read_srtt", mntinfo->mik_timers[1].srtt);
1221 SAVE_UINT32_X(ksi, "read_deviate", mntinfo->mik_timers[1].deviate);
1222 SAVE_UINT32_X(ksi, "read_rtxcur", mntinfo->mik_timers[1].rtxcur);
1223 SAVE_UINT32_X(ksi, "write_srtt", mntinfo->mik_timers[2].srtt);
1224 SAVE_UINT32_X(ksi, "write_deviate", mntinfo->mik_timers[2].deviate);
1225 SAVE_UINT32_X(ksi, "write_rtxcur", mntinfo->mik_timers[2].rtxcur);
1226 SAVE_UINT32(ksi, mntinfo, mik_noresponse);
1227 SAVE_UINT32(ksi, mntinfo, mik_failover);
1228 SAVE_UINT32(ksi, mntinfo, mik_remap);
1229 SAVE_STRING(ksi, mntinfo, mik_curserver);
1232 #ifdef __sparc
1233 static void
1234 save_sfmmu_global_stat(kstat_t *kp, ks_instance_t *ksi)
1236 struct sfmmu_global_stat *sfmmug =
1237 (struct sfmmu_global_stat *)(kp->ks_data);
1239 assert(kp->ks_data_size == sizeof (struct sfmmu_global_stat));
1241 SAVE_INT32(ksi, sfmmug, sf_tsb_exceptions);
1242 SAVE_INT32(ksi, sfmmug, sf_tsb_raise_exception);
1243 SAVE_INT32(ksi, sfmmug, sf_pagefaults);
1244 SAVE_INT32(ksi, sfmmug, sf_uhash_searches);
1245 SAVE_INT32(ksi, sfmmug, sf_uhash_links);
1246 SAVE_INT32(ksi, sfmmug, sf_khash_searches);
1247 SAVE_INT32(ksi, sfmmug, sf_khash_links);
1248 SAVE_INT32(ksi, sfmmug, sf_swapout);
1249 SAVE_INT32(ksi, sfmmug, sf_tsb_alloc);
1250 SAVE_INT32(ksi, sfmmug, sf_tsb_allocfail);
1251 SAVE_INT32(ksi, sfmmug, sf_tsb_sectsb_create);
1252 SAVE_INT32(ksi, sfmmug, sf_scd_1sttsb_alloc);
1253 SAVE_INT32(ksi, sfmmug, sf_scd_2ndtsb_alloc);
1254 SAVE_INT32(ksi, sfmmug, sf_scd_1sttsb_allocfail);
1255 SAVE_INT32(ksi, sfmmug, sf_scd_2ndtsb_allocfail);
1256 SAVE_INT32(ksi, sfmmug, sf_tteload8k);
1257 SAVE_INT32(ksi, sfmmug, sf_tteload64k);
1258 SAVE_INT32(ksi, sfmmug, sf_tteload512k);
1259 SAVE_INT32(ksi, sfmmug, sf_tteload4m);
1260 SAVE_INT32(ksi, sfmmug, sf_tteload32m);
1261 SAVE_INT32(ksi, sfmmug, sf_tteload256m);
1262 SAVE_INT32(ksi, sfmmug, sf_tsb_load8k);
1263 SAVE_INT32(ksi, sfmmug, sf_tsb_load4m);
1264 SAVE_INT32(ksi, sfmmug, sf_hblk_hit);
1265 SAVE_INT32(ksi, sfmmug, sf_hblk8_ncreate);
1266 SAVE_INT32(ksi, sfmmug, sf_hblk8_nalloc);
1267 SAVE_INT32(ksi, sfmmug, sf_hblk1_ncreate);
1268 SAVE_INT32(ksi, sfmmug, sf_hblk1_nalloc);
1269 SAVE_INT32(ksi, sfmmug, sf_hblk_slab_cnt);
1270 SAVE_INT32(ksi, sfmmug, sf_hblk_reserve_cnt);
1271 SAVE_INT32(ksi, sfmmug, sf_hblk_recurse_cnt);
1272 SAVE_INT32(ksi, sfmmug, sf_hblk_reserve_hit);
1273 SAVE_INT32(ksi, sfmmug, sf_get_free_success);
1274 SAVE_INT32(ksi, sfmmug, sf_get_free_throttle);
1275 SAVE_INT32(ksi, sfmmug, sf_get_free_fail);
1276 SAVE_INT32(ksi, sfmmug, sf_put_free_success);
1277 SAVE_INT32(ksi, sfmmug, sf_put_free_fail);
1278 SAVE_INT32(ksi, sfmmug, sf_pgcolor_conflict);
1279 SAVE_INT32(ksi, sfmmug, sf_uncache_conflict);
1280 SAVE_INT32(ksi, sfmmug, sf_unload_conflict);
1281 SAVE_INT32(ksi, sfmmug, sf_ism_uncache);
1282 SAVE_INT32(ksi, sfmmug, sf_ism_recache);
1283 SAVE_INT32(ksi, sfmmug, sf_recache);
1284 SAVE_INT32(ksi, sfmmug, sf_steal_count);
1285 SAVE_INT32(ksi, sfmmug, sf_pagesync);
1286 SAVE_INT32(ksi, sfmmug, sf_clrwrt);
1287 SAVE_INT32(ksi, sfmmug, sf_pagesync_invalid);
1288 SAVE_INT32(ksi, sfmmug, sf_kernel_xcalls);
1289 SAVE_INT32(ksi, sfmmug, sf_user_xcalls);
1290 SAVE_INT32(ksi, sfmmug, sf_tsb_grow);
1291 SAVE_INT32(ksi, sfmmug, sf_tsb_shrink);
1292 SAVE_INT32(ksi, sfmmug, sf_tsb_resize_failures);
1293 SAVE_INT32(ksi, sfmmug, sf_tsb_reloc);
1294 SAVE_INT32(ksi, sfmmug, sf_user_vtop);
1295 SAVE_INT32(ksi, sfmmug, sf_ctx_inv);
1296 SAVE_INT32(ksi, sfmmug, sf_tlb_reprog_pgsz);
1297 SAVE_INT32(ksi, sfmmug, sf_region_remap_demap);
1298 SAVE_INT32(ksi, sfmmug, sf_create_scd);
1299 SAVE_INT32(ksi, sfmmug, sf_join_scd);
1300 SAVE_INT32(ksi, sfmmug, sf_leave_scd);
1301 SAVE_INT32(ksi, sfmmug, sf_destroy_scd);
1303 #endif
1305 #ifdef __sparc
1306 static void
1307 save_sfmmu_tsbsize_stat(kstat_t *kp, ks_instance_t *ksi)
1309 struct sfmmu_tsbsize_stat *sfmmut;
1311 assert(kp->ks_data_size == sizeof (struct sfmmu_tsbsize_stat));
1312 sfmmut = (struct sfmmu_tsbsize_stat *)(kp->ks_data);
1314 SAVE_INT32(ksi, sfmmut, sf_tsbsz_8k);
1315 SAVE_INT32(ksi, sfmmut, sf_tsbsz_16k);
1316 SAVE_INT32(ksi, sfmmut, sf_tsbsz_32k);
1317 SAVE_INT32(ksi, sfmmut, sf_tsbsz_64k);
1318 SAVE_INT32(ksi, sfmmut, sf_tsbsz_128k);
1319 SAVE_INT32(ksi, sfmmut, sf_tsbsz_256k);
1320 SAVE_INT32(ksi, sfmmut, sf_tsbsz_512k);
1321 SAVE_INT32(ksi, sfmmut, sf_tsbsz_1m);
1322 SAVE_INT32(ksi, sfmmut, sf_tsbsz_2m);
1323 SAVE_INT32(ksi, sfmmut, sf_tsbsz_4m);
1325 #endif
1327 #ifdef __sparc
1328 static void
1329 save_simmstat(kstat_t *kp, ks_instance_t *ksi)
1331 uchar_t *simmstat;
1332 char *simm_buf;
1333 char *list = NULL;
1334 int i;
1336 assert(kp->ks_data_size == sizeof (uchar_t) * SIMM_COUNT);
1338 for (i = 0, simmstat = (uchar_t *)(kp->ks_data); i < SIMM_COUNT - 1;
1339 i++, simmstat++) {
1340 if (list == NULL) {
1341 (void) asprintf(&simm_buf, "%d,", *simmstat);
1342 } else {
1343 (void) asprintf(&simm_buf, "%s%d,", list, *simmstat);
1344 free(list);
1346 list = simm_buf;
1349 (void) asprintf(&simm_buf, "%s%d", list, *simmstat);
1350 SAVE_STRING_X(ksi, "status", simm_buf);
1351 free(list);
1352 free(simm_buf);
1354 #endif
1356 #ifdef __sparc
1358 * Helper function for save_temperature().
1360 static char *
1361 short_array_to_string(short *shortp, int len)
1363 char *list = NULL;
1364 char *list_buf;
1366 for (; len > 1; len--, shortp++) {
1367 if (list == NULL) {
1368 (void) asprintf(&list_buf, "%hd,", *shortp);
1369 } else {
1370 (void) asprintf(&list_buf, "%s%hd,", list, *shortp);
1371 free(list);
1373 list = list_buf;
1376 (void) asprintf(&list_buf, "%s%hd", list, *shortp);
1377 free(list);
1378 return (list_buf);
1381 static void
1382 save_temperature(kstat_t *kp, ks_instance_t *ksi)
1384 struct temp_stats *temps = (struct temp_stats *)(kp->ks_data);
1385 char *buf;
1387 assert(kp->ks_data_size == sizeof (struct temp_stats));
1389 SAVE_UINT32(ksi, temps, index);
1391 buf = short_array_to_string(temps->l1, L1_SZ);
1392 SAVE_STRING_X(ksi, "l1", buf);
1393 free(buf);
1395 buf = short_array_to_string(temps->l2, L2_SZ);
1396 SAVE_STRING_X(ksi, "l2", buf);
1397 free(buf);
1399 buf = short_array_to_string(temps->l3, L3_SZ);
1400 SAVE_STRING_X(ksi, "l3", buf);
1401 free(buf);
1403 buf = short_array_to_string(temps->l4, L4_SZ);
1404 SAVE_STRING_X(ksi, "l4", buf);
1405 free(buf);
1407 buf = short_array_to_string(temps->l5, L5_SZ);
1408 SAVE_STRING_X(ksi, "l5", buf);
1409 free(buf);
1411 SAVE_INT32(ksi, temps, max);
1412 SAVE_INT32(ksi, temps, min);
1413 SAVE_INT32(ksi, temps, state);
1414 SAVE_INT32(ksi, temps, temp_cnt);
1415 SAVE_INT32(ksi, temps, shutdown_cnt);
1416 SAVE_INT32(ksi, temps, version);
1417 SAVE_INT32(ksi, temps, trend);
1418 SAVE_INT32(ksi, temps, override);
1420 #endif
1422 #ifdef __sparc
1423 static void
1424 save_temp_over(kstat_t *kp, ks_instance_t *ksi)
1426 short *sh = (short *)(kp->ks_data);
1427 char *value;
1429 assert(kp->ks_data_size == sizeof (short));
1431 (void) asprintf(&value, "%hu", *sh);
1432 SAVE_STRING_X(ksi, "override", value);
1433 free(value);
1435 #endif
1437 #ifdef __sparc
1438 static void
1439 save_ps_shadow(kstat_t *kp, ks_instance_t *ksi)
1441 uchar_t *uchar = (uchar_t *)(kp->ks_data);
1443 assert(kp->ks_data_size == SYS_PS_COUNT);
1445 SAVE_CHAR_X(ksi, "core_0", *uchar++);
1446 SAVE_CHAR_X(ksi, "core_1", *uchar++);
1447 SAVE_CHAR_X(ksi, "core_2", *uchar++);
1448 SAVE_CHAR_X(ksi, "core_3", *uchar++);
1449 SAVE_CHAR_X(ksi, "core_4", *uchar++);
1450 SAVE_CHAR_X(ksi, "core_5", *uchar++);
1451 SAVE_CHAR_X(ksi, "core_6", *uchar++);
1452 SAVE_CHAR_X(ksi, "core_7", *uchar++);
1453 SAVE_CHAR_X(ksi, "pps_0", *uchar++);
1454 SAVE_CHAR_X(ksi, "clk_33", *uchar++);
1455 SAVE_CHAR_X(ksi, "clk_50", *uchar++);
1456 SAVE_CHAR_X(ksi, "v5_p", *uchar++);
1457 SAVE_CHAR_X(ksi, "v12_p", *uchar++);
1458 SAVE_CHAR_X(ksi, "v5_aux", *uchar++);
1459 SAVE_CHAR_X(ksi, "v5_p_pch", *uchar++);
1460 SAVE_CHAR_X(ksi, "v12_p_pch", *uchar++);
1461 SAVE_CHAR_X(ksi, "v3_pch", *uchar++);
1462 SAVE_CHAR_X(ksi, "v5_pch", *uchar++);
1463 SAVE_CHAR_X(ksi, "p_fan", *uchar++);
1465 #endif
1467 #ifdef __sparc
1468 static void
1469 save_fault_list(kstat_t *kp, ks_instance_t *ksi)
1471 struct ft_list *fault;
1472 char name[KSTAT_STRLEN + 7];
1473 int i;
1475 for (i = 1, fault = (struct ft_list *)(kp->ks_data);
1476 i <= 999999 && i <= kp->ks_data_size / sizeof (struct ft_list);
1477 i++, fault++) {
1478 (void) snprintf(name, sizeof (name), "unit_%d", i);
1479 SAVE_INT32_X(ksi, name, fault->unit);
1480 (void) snprintf(name, sizeof (name), "type_%d", i);
1481 SAVE_INT32_X(ksi, name, fault->type);
1482 (void) snprintf(name, sizeof (name), "fclass_%d", i);
1483 SAVE_INT32_X(ksi, name, fault->fclass);
1484 (void) snprintf(name, sizeof (name), "create_time_%d", i);
1485 SAVE_HRTIME_X(ksi, name, fault->create_time);
1486 (void) snprintf(name, sizeof (name), "msg_%d", i);
1487 SAVE_STRING_X(ksi, name, fault->msg);
1490 #endif
1492 static void
1493 save_named(kstat_t *kp, ks_instance_t *ksi)
1495 kstat_named_t *knp;
1496 int n;
1498 for (n = kp->ks_ndata, knp = KSTAT_NAMED_PTR(kp); n > 0; n--, knp++) {
1500 * Annoyingly, some drivers have kstats with uninitialized
1501 * members (which kstat_install(9F) is sadly powerless to
1502 * prevent, and kstat_read(3KSTAT) unfortunately does nothing
1503 * to stop). To prevent these from confusing us to be
1504 * KSTAT_DATA_CHAR statistics, we skip over them.
1506 if (knp->name[0] == '\0')
1507 continue;
1509 switch (knp->data_type) {
1510 case KSTAT_DATA_CHAR:
1511 nvpair_insert(ksi, knp->name,
1512 (ks_value_t *)&knp->value, KSTAT_DATA_CHAR);
1513 break;
1514 case KSTAT_DATA_INT32:
1515 nvpair_insert(ksi, knp->name,
1516 (ks_value_t *)&knp->value, KSTAT_DATA_INT32);
1517 break;
1518 case KSTAT_DATA_UINT32:
1519 nvpair_insert(ksi, knp->name,
1520 (ks_value_t *)&knp->value, KSTAT_DATA_UINT32);
1521 break;
1522 case KSTAT_DATA_INT64:
1523 nvpair_insert(ksi, knp->name,
1524 (ks_value_t *)&knp->value, KSTAT_DATA_INT64);
1525 break;
1526 case KSTAT_DATA_UINT64:
1527 nvpair_insert(ksi, knp->name,
1528 (ks_value_t *)&knp->value, KSTAT_DATA_UINT64);
1529 break;
1530 case KSTAT_DATA_STRING:
1531 SAVE_STRING_X(ksi, knp->name, KSTAT_NAMED_STR_PTR(knp));
1532 break;
1533 default:
1534 assert(B_FALSE); /* Invalid data type */
1535 break;
1540 static void
1541 save_intr(kstat_t *kp, ks_instance_t *ksi)
1543 kstat_intr_t *intr = KSTAT_INTR_PTR(kp);
1544 char *intr_names[] = {"hard", "soft", "watchdog", "spurious",
1545 "multiple_service"};
1546 int n;
1548 for (n = 0; n < KSTAT_NUM_INTRS; n++)
1549 SAVE_UINT32_X(ksi, intr_names[n], intr->intrs[n]);
1552 static void
1553 save_io(kstat_t *kp, ks_instance_t *ksi)
1555 kstat_io_t *ksio = KSTAT_IO_PTR(kp);
1557 SAVE_UINT64(ksi, ksio, nread);
1558 SAVE_UINT64(ksi, ksio, nwritten);
1559 SAVE_UINT32(ksi, ksio, reads);
1560 SAVE_UINT32(ksi, ksio, writes);
1561 SAVE_HRTIME(ksi, ksio, wtime);
1562 SAVE_HRTIME(ksi, ksio, wlentime);
1563 SAVE_HRTIME(ksi, ksio, wlastupdate);
1564 SAVE_HRTIME(ksi, ksio, rtime);
1565 SAVE_HRTIME(ksi, ksio, rlentime);
1566 SAVE_HRTIME(ksi, ksio, rlastupdate);
1567 SAVE_UINT32(ksi, ksio, wcnt);
1568 SAVE_UINT32(ksi, ksio, rcnt);
1571 static void
1572 save_timer(kstat_t *kp, ks_instance_t *ksi)
1574 kstat_timer_t *ktimer = KSTAT_TIMER_PTR(kp);
1576 SAVE_STRING(ksi, ktimer, name);
1577 SAVE_UINT64(ksi, ktimer, num_events);
1578 SAVE_HRTIME(ksi, ktimer, elapsed_time);
1579 SAVE_HRTIME(ksi, ktimer, min_time);
1580 SAVE_HRTIME(ksi, ktimer, max_time);
1581 SAVE_HRTIME(ksi, ktimer, start_time);
1582 SAVE_HRTIME(ksi, ktimer, stop_time);