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]
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
36 * - perl regular expressions replaced with extended REs bracketed by '/'
39 * -C similar to the -p option but value is separated by a colon
62 #include <sys/types.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
;
90 main(int argc
, char **argv
)
92 ks_selector_t
*nselector
;
93 ks_selector_t
*uselector
;
97 boolean_t errflg
= B_FALSE
;
98 boolean_t nselflg
= B_FALSE
;
99 boolean_t uselflg
= B_FALSE
;
102 int infinite_cycles
= 0;
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 */
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
)
134 g_pflg
= g_cflg
= B_TRUE
;
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.,
146 (void) setlocale(LC_NUMERIC
, "C");
150 g_pflg
= g_lflg
= B_TRUE
;
158 g_timestamp_fmt
= DDATE
;
161 g_timestamp_fmt
= UDATE
;
169 nselector
->ks_module
.pstr
=
170 (char *)ks_safe_strdup(optarg
);
174 nselector
->ks_instance
.pstr
=
175 (char *)ks_safe_strdup(optarg
);
179 nselector
->ks_name
.pstr
=
180 (char *)ks_safe_strdup(optarg
);
184 nselector
->ks_statistic
.pstr
=
185 (char *)ks_safe_strdup(optarg
);
189 (char *)ks_safe_strdup(optarg
);
196 if (g_qflg
&& (g_jflg
|| g_pflg
)) {
197 (void) fprintf(stderr
, gettext(
198 "-q and -lpj are mutually exclusive\n"));
211 * Consume the rest of the command line. Parsing the
212 * unnamed command line arguments.
216 tmp
= strtoul(*argv
, &q
, 10);
217 if (tmp
== ULONG_MAX
&& errno
== ERANGE
) {
219 (void) fprintf(stderr
, gettext(
220 "Interval is too large\n"));
222 (void) fprintf(stderr
, gettext(
223 "Count is too large\n"));
229 if (errno
!= 0 || *q
!= '\0') {
231 uselector
= new_selector();
232 while ((q
= (char *)strsep(argv
, ":")) != NULL
) {
243 uselector
->ks_module
.pstr
=
244 (char *)ks_safe_strdup(q
);
247 uselector
->ks_instance
.pstr
=
248 (char *)ks_safe_strdup(q
);
251 uselector
->ks_name
.pstr
=
252 (char *)ks_safe_strdup(q
);
255 uselector
->ks_statistic
.pstr
=
256 (char *)ks_safe_strdup(q
);
265 list_insert_tail(&selector_list
, uselector
);
269 (void) fprintf(stderr
, gettext(
270 "Interval must be an "
273 (void) fprintf(stderr
, gettext(
274 "Count must be an integer >= 1"));
295 * Check if we founded a named selector on the cmdline.
299 (void) fprintf(stderr
, gettext(
300 "[module[:instance[:name[:statistic]]]] and "
301 "-m -i -n -s are mutually exclusive"));
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);
320 perror("kstat_open");
326 if (signal(SIGCONT
, cont_handler
) == SIG_ERR
) {
327 (void) fprintf(stderr
, gettext(
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
,
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);
362 (void) fprintf(stderr
, gettext(
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.
376 compare_instances(ks_instance_t
*l_arg
, ks_instance_t
*r_arg
)
380 rval
= strcasecmp(l_arg
->ks_module
, r_arg
->ks_module
);
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
) {
395 ks_safe_strdup(char *str
)
403 while ((ret
= strdup(str
)) == NULL
) {
404 if (errno
== EAGAIN
) {
405 (void) poll(NULL
, 0, 200);
416 ks_sleep_until(hrtime_t
*wakeup
, hrtime_t interval
, int forever
,
419 hrtime_t now
, pause
, pause_left
;
420 struct timespec pause_tv
;
424 pause
= *wakeup
+ interval
- now
;
426 if (pause
<= 0 || pause
< (interval
/ 4)) {
427 if (forever
|| *caught_cont
) {
428 *wakeup
= now
+ interval
;
431 pause
= interval
/ 2;
444 pause_tv
.tv_sec
= pause_left
/ NANOSEC
;
445 pause_tv
.tv_nsec
= pause_left
% NANOSEC
;
446 status
= nanosleep(&pause_tv
, NULL
);
448 if (errno
== EINTR
) {
450 pause_left
= *wakeup
- now
;
451 if (pause_left
< 1000) {
459 } while (status
!= 0);
463 * Inserts an instance in the per selector list.
466 nvpair_insert(ks_instance_t
*ksi
, char *name
, ks_value_t
*value
,
469 ks_nvpair_t
*instance
;
472 instance
= (ks_nvpair_t
*)malloc(sizeof (ks_nvpair_t
));
473 if (instance
== NULL
) {
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
*
495 ks_selector_t
*selector
;
497 selector
= (ks_selector_t
*)malloc(sizeof (ks_selector_t
));
498 if (selector
== NULL
) {
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
= "*";
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
;
524 for (f
= module
, t
= key
; *f
!= '\0'; f
++, t
++) {
525 while (*f
!= '\0' && isdigit(*f
))
531 for (f
= name
; *f
!= '\0'; f
++, t
++) {
532 while (*f
!= '\0' && isdigit(*f
))
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
);
548 * Match a string against a shell glob or extended regular expression.
551 ks_match(const char *str
, ks_pattern_t
*pattern
)
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
);
566 bufsz
= regerror(regcode
, NULL
, NULL
, 0);
568 errbuf
= malloc(bufsz
);
569 if (errbuf
== NULL
) {
573 (void) regerror(regcode
, NULL
, errbuf
, bufsz
);
574 (void) fprintf(stderr
, "kstat: %s\n", errbuf
);
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.
594 ks_instances_read(kstat_ctl_t
*kc
)
596 kstat_raw_reader_t save_raw
= NULL
;
598 ks_selector_t
*selector
;
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) {
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
,
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
);
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.
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
)) {
639 selector
= list_next(&selector_list
, selector
);
647 * Allocate a new instance and fill in the values
650 ksi
= (ks_instance_t
*)malloc(sizeof (ks_instance_t
));
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
);
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
);
684 #ifdef REPORT_UNKNOWN
685 perror("kstat_read");
690 SAVE_HRTIME_X(ksi
, "snaptime", kp
->ks_snaptime
);
692 switch (kp
->ks_type
) {
696 case KSTAT_TYPE_NAMED
:
699 case KSTAT_TYPE_INTR
:
705 case KSTAT_TYPE_TIMER
:
709 assert(B_FALSE
); /* Invalid type */
716 * Print the value of a name-value pair.
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
);
725 case KSTAT_DATA_INT32
:
726 (void) fprintf(stdout
, "%d", nvpair
->value
.i32
);
728 case KSTAT_DATA_UINT32
:
729 (void) fprintf(stdout
, "%u", nvpair
->value
.ui32
);
731 case KSTAT_DATA_INT64
:
732 (void) fprintf(stdout
, "%lld", nvpair
->value
.i64
);
734 case KSTAT_DATA_UINT64
:
735 (void) fprintf(stdout
, "%llu", nvpair
->value
.ui64
);
737 case KSTAT_DATA_STRING
:
738 (void) fprintf(stdout
, "%s", KSTAT_NAMED_STR_PTR(nvpair
));
740 case KSTAT_DATA_HRTIME
:
741 if (nvpair
->value
.ui64
== 0)
742 (void) fprintf(stdout
, "0");
744 (void) fprintf(stdout
, "%.9f",
745 nvpair
->value
.ui64
/ 1000000000.0);
753 * Print a single instance.
757 ks_instance_print(ks_instance_t
*ksi
, ks_nvpair_t
*nvpair
, boolean_t last
)
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
;
769 (void) fprintf(stdout
, KS_PFMT
,
770 ksi
->ks_module
, ksi
->ks_instance
,
771 ksi
->ks_name
, nvpair
->name
);
773 (void) putchar(g_cflg
? ':': '\t');
774 ks_value_print(nvpair
);
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.
788 ks_print_json_string(const char *str
)
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.
805 (void) fprintf(stdout
, "\\%c", c
);
809 (void) fprintf(stdout
, "\\n");
813 (void) fprintf(stdout
, "\\t");
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
826 (void) fprintf(stdout
, "\\u%04hhx", (uint8_t)c
);
839 * Print a single instance in JSON format.
842 ks_instance_print_json(ks_instance_t
*ksi
, ks_nvpair_t
*nvpair
, boolean_t last
)
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");
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
);
882 case KSTAT_DATA_STRING
:
883 ks_print_json_string(KSTAT_NAMED_STR_PTR(nvpair
));
887 ks_value_print(nvpair
);
894 (void) putchar('\n');
898 * Print all instances.
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
);
909 if (g_timestamp_fmt
!= NODATE
)
910 print_timestamp(g_timestamp_fmt
);
913 ks_print_fn
= &ks_instance_print_json
;
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
))) {
938 g_headerflg
= B_TRUE
;
941 * Find our first statistic to print.
943 for (nvpair
= list_head(&ksi
->ks_nvlist
);
945 nvpair
= list_next(&ksi
->ks_nvlist
, nvpair
)) {
946 if (ks_match(nvpair
->name
,
947 &selector
->ks_statistic
))
951 while (nvpair
!= NULL
) {
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
960 for (next
= list_next(&ksi
->ks_nvlist
, nvpair
);
962 next
= list_next(&ksi
->ks_nvlist
, next
)) {
963 if (ks_match(next
->name
,
964 &selector
->ks_statistic
))
969 last
= next
== NULL
? B_TRUE
: B_FALSE
;
972 (*ks_print_fn
)(ksi
, nvpair
, last
);
979 (void) fprintf(stdout
, "\t}\n}");
980 } else if (!g_pflg
) {
981 (void) putchar('\n');
986 selector
= list_next(&selector_list
, selector
);
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
) {
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
);
1008 ksi
= list_next(&instances_list
, ksi
);
1009 list_remove(&instances_list
, ktmp
);
1010 list_destroy(&ktmp
->ks_nvlist
);
1016 save_cpu_stat(kstat_t
*kp
, ks_instance_t
*ksi
)
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
);
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
);
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
);
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
);
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
);
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
);
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
);
1240 save_named(kstat_t
*kp
, ks_instance_t
*ksi
)
1245 for (n
= kp
->ks_ndata
, knp
= KSTAT_NAMED_PTR(kp
); n
> 0; n
--, knp
++) {
1247 * Annoyingly, some drivers have kstats with uninitialized
1248 * members (which kstat_install(9F) is sadly powerless to
1249 * prevent, and kstat_read(3KSTAT) unfortunately does nothing
1250 * to stop). To prevent these from confusing us to be
1251 * KSTAT_DATA_CHAR statistics, we skip over them.
1253 if (knp
->name
[0] == '\0')
1256 switch (knp
->data_type
) {
1257 case KSTAT_DATA_CHAR
:
1258 nvpair_insert(ksi
, knp
->name
,
1259 (ks_value_t
*)&knp
->value
, KSTAT_DATA_CHAR
);
1261 case KSTAT_DATA_INT32
:
1262 nvpair_insert(ksi
, knp
->name
,
1263 (ks_value_t
*)&knp
->value
, KSTAT_DATA_INT32
);
1265 case KSTAT_DATA_UINT32
:
1266 nvpair_insert(ksi
, knp
->name
,
1267 (ks_value_t
*)&knp
->value
, KSTAT_DATA_UINT32
);
1269 case KSTAT_DATA_INT64
:
1270 nvpair_insert(ksi
, knp
->name
,
1271 (ks_value_t
*)&knp
->value
, KSTAT_DATA_INT64
);
1273 case KSTAT_DATA_UINT64
:
1274 nvpair_insert(ksi
, knp
->name
,
1275 (ks_value_t
*)&knp
->value
, KSTAT_DATA_UINT64
);
1277 case KSTAT_DATA_STRING
:
1278 SAVE_STRING_X(ksi
, knp
->name
, KSTAT_NAMED_STR_PTR(knp
));
1281 assert(B_FALSE
); /* Invalid data type */
1288 save_intr(kstat_t
*kp
, ks_instance_t
*ksi
)
1290 kstat_intr_t
*intr
= KSTAT_INTR_PTR(kp
);
1291 char *intr_names
[] = {"hard", "soft", "watchdog", "spurious",
1292 "multiple_service"};
1295 for (n
= 0; n
< KSTAT_NUM_INTRS
; n
++)
1296 SAVE_UINT32_X(ksi
, intr_names
[n
], intr
->intrs
[n
]);
1300 save_io(kstat_t
*kp
, ks_instance_t
*ksi
)
1302 kstat_io_t
*ksio
= KSTAT_IO_PTR(kp
);
1304 SAVE_UINT64(ksi
, ksio
, nread
);
1305 SAVE_UINT64(ksi
, ksio
, nwritten
);
1306 SAVE_UINT32(ksi
, ksio
, reads
);
1307 SAVE_UINT32(ksi
, ksio
, writes
);
1308 SAVE_HRTIME(ksi
, ksio
, wtime
);
1309 SAVE_HRTIME(ksi
, ksio
, wlentime
);
1310 SAVE_HRTIME(ksi
, ksio
, wlastupdate
);
1311 SAVE_HRTIME(ksi
, ksio
, rtime
);
1312 SAVE_HRTIME(ksi
, ksio
, rlentime
);
1313 SAVE_HRTIME(ksi
, ksio
, rlastupdate
);
1314 SAVE_UINT32(ksi
, ksio
, wcnt
);
1315 SAVE_UINT32(ksi
, ksio
, rcnt
);
1319 save_timer(kstat_t
*kp
, ks_instance_t
*ksi
)
1321 kstat_timer_t
*ktimer
= KSTAT_TIMER_PTR(kp
);
1323 SAVE_STRING(ksi
, ktimer
, name
);
1324 SAVE_UINT64(ksi
, ktimer
, num_events
);
1325 SAVE_HRTIME(ksi
, ktimer
, elapsed_time
);
1326 SAVE_HRTIME(ksi
, ktimer
, min_time
);
1327 SAVE_HRTIME(ksi
, ktimer
, max_time
);
1328 SAVE_HRTIME(ksi
, ktimer
, start_time
);
1329 SAVE_HRTIME(ksi
, ktimer
, stop_time
);