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