166448911SDavid Höppner /* 266448911SDavid Höppner * CDDL HEADER START 366448911SDavid Höppner * 466448911SDavid Höppner * The contents of this file are subject to the terms of the 566448911SDavid Höppner * Common Development and Distribution License (the "License"). 666448911SDavid Höppner * You may not use this file except in compliance with the License. 766448911SDavid Höppner * 866448911SDavid Höppner * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 966448911SDavid Höppner * or http://www.opensolaris.org/os/licensing. 1066448911SDavid Höppner * See the License for the specific language governing permissions 1166448911SDavid Höppner * and limitations under the License. 1266448911SDavid Höppner * 1366448911SDavid Höppner * When distributing Covered Code, include this CDDL HEADER in each 1466448911SDavid Höppner * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1566448911SDavid Höppner * If applicable, add the following below this CDDL HEADER, with the 1666448911SDavid Höppner * fields enclosed by brackets "[]" replaced with your own identifying 1766448911SDavid Höppner * information: Portions Copyright [yyyy] [name of copyright owner] 1866448911SDavid Höppner * 1966448911SDavid Höppner * CDDL HEADER END 2066448911SDavid Höppner */ 2166448911SDavid Höppner 2266448911SDavid Höppner /* 2366448911SDavid Höppner * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 2466448911SDavid Höppner * Copyright (c) 2013 David Hoeppner. All rights reserved. 2566448911SDavid Höppner * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 26*9736aecdSBryan Cantrill * Copyright (c) 2013, Joyent, Inc. All rights reserved. 2766448911SDavid Höppner */ 2866448911SDavid Höppner 2966448911SDavid Höppner /* 3066448911SDavid Höppner * Display kernel statistics 3166448911SDavid Höppner * 3266448911SDavid Höppner * This is a reimplementation of the perl kstat command originally found 3366448911SDavid Höppner * under usr/src/cmd/kstat/kstat.pl 3466448911SDavid Höppner * 3566448911SDavid Höppner * Incompatibilities: 3666448911SDavid Höppner * - perl regular expressions replaced with extended REs bracketed by '/' 3766448911SDavid Höppner * 3866448911SDavid Höppner * Flags added: 3966448911SDavid Höppner * -C similar to the -p option but value is separated by a colon 4066448911SDavid Höppner * -h display help 4166448911SDavid Höppner * -j json format 4266448911SDavid Höppner */ 4366448911SDavid Höppner 4466448911SDavid Höppner #include <assert.h> 4566448911SDavid Höppner #include <ctype.h> 4666448911SDavid Höppner #include <errno.h> 4766448911SDavid Höppner #include <kstat.h> 4866448911SDavid Höppner #include <langinfo.h> 4966448911SDavid Höppner #include <libgen.h> 5066448911SDavid Höppner #include <limits.h> 5166448911SDavid Höppner #include <locale.h> 5266448911SDavid Höppner #include <signal.h> 5366448911SDavid Höppner #include <stddef.h> 5466448911SDavid Höppner #include <stdio.h> 5566448911SDavid Höppner #include <stdlib.h> 5666448911SDavid Höppner #include <string.h> 5766448911SDavid Höppner #include <strings.h> 5866448911SDavid Höppner #include <time.h> 5966448911SDavid Höppner #include <unistd.h> 6066448911SDavid Höppner #include <sys/list.h> 6166448911SDavid Höppner #include <sys/time.h> 6266448911SDavid Höppner #include <sys/types.h> 6366448911SDavid Höppner 6466448911SDavid Höppner #include "kstat.h" 6566448911SDavid Höppner #include "statcommon.h" 6666448911SDavid Höppner 6766448911SDavid Höppner char *cmdname = "kstat"; /* Name of this command */ 6866448911SDavid Höppner int caught_cont = 0; /* Have caught a SIGCONT */ 6966448911SDavid Höppner 7066448911SDavid Höppner static uint_t g_timestamp_fmt = NODATE; 7166448911SDavid Höppner 7266448911SDavid Höppner /* Helper flag - header was printed already? */ 7366448911SDavid Höppner static boolean_t g_headerflg; 7466448911SDavid Höppner 7566448911SDavid Höppner /* Saved command line options */ 7666448911SDavid Höppner static boolean_t g_cflg = B_FALSE; 7766448911SDavid Höppner static boolean_t g_jflg = B_FALSE; 7866448911SDavid Höppner static boolean_t g_lflg = B_FALSE; 7966448911SDavid Höppner static boolean_t g_pflg = B_FALSE; 8066448911SDavid Höppner static boolean_t g_qflg = B_FALSE; 8166448911SDavid Höppner static ks_pattern_t g_ks_class = {"*", 0}; 8266448911SDavid Höppner 8366448911SDavid Höppner /* Return zero if a selector did match */ 8466448911SDavid Höppner static int g_matched = 1; 8566448911SDavid Höppner 8666448911SDavid Höppner /* Sorted list of kstat instances */ 8766448911SDavid Höppner static list_t instances_list; 8866448911SDavid Höppner static list_t selector_list; 8966448911SDavid Höppner 9066448911SDavid Höppner int 9166448911SDavid Höppner main(int argc, char **argv) 9266448911SDavid Höppner { 9366448911SDavid Höppner ks_selector_t *nselector; 9466448911SDavid Höppner ks_selector_t *uselector; 9566448911SDavid Höppner kstat_ctl_t *kc; 9666448911SDavid Höppner hrtime_t start_n; 9766448911SDavid Höppner hrtime_t period_n; 9866448911SDavid Höppner boolean_t errflg = B_FALSE; 9966448911SDavid Höppner boolean_t nselflg = B_FALSE; 10066448911SDavid Höppner boolean_t uselflg = B_FALSE; 10166448911SDavid Höppner char *q; 10266448911SDavid Höppner int count = 1; 10366448911SDavid Höppner int infinite_cycles = 0; 10466448911SDavid Höppner int interval = 0; 10566448911SDavid Höppner int n = 0; 10666448911SDavid Höppner int c, m, tmp; 10766448911SDavid Höppner 10866448911SDavid Höppner (void) setlocale(LC_ALL, ""); 10966448911SDavid Höppner #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 11066448911SDavid Höppner #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 11166448911SDavid Höppner #endif 11266448911SDavid Höppner (void) textdomain(TEXT_DOMAIN); 11366448911SDavid Höppner 11466448911SDavid Höppner /* 11566448911SDavid Höppner * Create the selector list and a dummy default selector to match 11666448911SDavid Höppner * everything. While we process the cmdline options we will add 11766448911SDavid Höppner * selectors to this list. 11866448911SDavid Höppner */ 11966448911SDavid Höppner list_create(&selector_list, sizeof (ks_selector_t), 12066448911SDavid Höppner offsetof(ks_selector_t, ks_next)); 12166448911SDavid Höppner 12266448911SDavid Höppner nselector = new_selector(); 12366448911SDavid Höppner 12466448911SDavid Höppner /* 12566448911SDavid Höppner * Parse named command line arguments. 12666448911SDavid Höppner */ 12766448911SDavid Höppner while ((c = getopt(argc, argv, "h?CqjlpT:m:i:n:s:c:")) != EOF) 12866448911SDavid Höppner switch (c) { 12966448911SDavid Höppner case 'h': 13066448911SDavid Höppner case '?': 13166448911SDavid Höppner usage(); 13266448911SDavid Höppner exit(0); 13366448911SDavid Höppner break; 13466448911SDavid Höppner case 'C': 13566448911SDavid Höppner g_pflg = g_cflg = B_TRUE; 13666448911SDavid Höppner break; 13766448911SDavid Höppner case 'q': 13866448911SDavid Höppner g_qflg = B_TRUE; 13966448911SDavid Höppner break; 14066448911SDavid Höppner case 'j': 14166448911SDavid Höppner g_jflg = B_TRUE; 14266448911SDavid Höppner break; 14366448911SDavid Höppner case 'l': 14466448911SDavid Höppner g_pflg = g_lflg = B_TRUE; 14566448911SDavid Höppner break; 14666448911SDavid Höppner case 'p': 14766448911SDavid Höppner g_pflg = B_TRUE; 14866448911SDavid Höppner break; 14966448911SDavid Höppner case 'T': 15066448911SDavid Höppner switch (*optarg) { 15166448911SDavid Höppner case 'd': 15266448911SDavid Höppner g_timestamp_fmt = DDATE; 15366448911SDavid Höppner break; 15466448911SDavid Höppner case 'u': 15566448911SDavid Höppner g_timestamp_fmt = UDATE; 15666448911SDavid Höppner break; 15766448911SDavid Höppner default: 15866448911SDavid Höppner errflg = B_TRUE; 15966448911SDavid Höppner } 16066448911SDavid Höppner break; 16166448911SDavid Höppner case 'm': 16266448911SDavid Höppner nselflg = B_TRUE; 16366448911SDavid Höppner nselector->ks_module.pstr = 16466448911SDavid Höppner (char *)ks_safe_strdup(optarg); 16566448911SDavid Höppner break; 16666448911SDavid Höppner case 'i': 16766448911SDavid Höppner nselflg = B_TRUE; 16866448911SDavid Höppner nselector->ks_instance.pstr = 16966448911SDavid Höppner (char *)ks_safe_strdup(optarg); 17066448911SDavid Höppner break; 17166448911SDavid Höppner case 'n': 17266448911SDavid Höppner nselflg = B_TRUE; 17366448911SDavid Höppner nselector->ks_name.pstr = 17466448911SDavid Höppner (char *)ks_safe_strdup(optarg); 17566448911SDavid Höppner break; 17666448911SDavid Höppner case 's': 17766448911SDavid Höppner nselflg = B_TRUE; 17866448911SDavid Höppner nselector->ks_statistic.pstr = 17966448911SDavid Höppner (char *)ks_safe_strdup(optarg); 18066448911SDavid Höppner break; 18166448911SDavid Höppner case 'c': 18266448911SDavid Höppner g_ks_class.pstr = 18366448911SDavid Höppner (char *)ks_safe_strdup(optarg); 18466448911SDavid Höppner break; 18566448911SDavid Höppner default: 18666448911SDavid Höppner errflg = B_TRUE; 18766448911SDavid Höppner break; 18866448911SDavid Höppner } 18966448911SDavid Höppner 19066448911SDavid Höppner if (g_qflg && (g_jflg || g_pflg)) { 19166448911SDavid Höppner (void) fprintf(stderr, gettext( 19266448911SDavid Höppner "-q and -lpj are mutually exclusive\n")); 19366448911SDavid Höppner errflg = B_TRUE; 19466448911SDavid Höppner } 19566448911SDavid Höppner 19666448911SDavid Höppner if (errflg) { 19766448911SDavid Höppner usage(); 19866448911SDavid Höppner exit(2); 19966448911SDavid Höppner } 20066448911SDavid Höppner 20166448911SDavid Höppner argc -= optind; 20266448911SDavid Höppner argv += optind; 20366448911SDavid Höppner 20466448911SDavid Höppner /* 20566448911SDavid Höppner * Consume the rest of the command line. Parsing the 20666448911SDavid Höppner * unnamed command line arguments. 20766448911SDavid Höppner */ 20866448911SDavid Höppner while (argc--) { 20966448911SDavid Höppner errno = 0; 21066448911SDavid Höppner tmp = strtoul(*argv, &q, 10); 21166448911SDavid Höppner if (tmp == ULONG_MAX && errno == ERANGE) { 21266448911SDavid Höppner if (n == 0) { 21366448911SDavid Höppner (void) fprintf(stderr, gettext( 21466448911SDavid Höppner "Interval is too large\n")); 21566448911SDavid Höppner } else if (n == 1) { 21666448911SDavid Höppner (void) fprintf(stderr, gettext( 21766448911SDavid Höppner "Count is too large\n")); 21866448911SDavid Höppner } 21966448911SDavid Höppner usage(); 22066448911SDavid Höppner exit(2); 22166448911SDavid Höppner } 22266448911SDavid Höppner 22366448911SDavid Höppner if (errno != 0 || *q != '\0') { 22466448911SDavid Höppner m = 0; 22566448911SDavid Höppner uselector = new_selector(); 22666448911SDavid Höppner while ((q = (char *)strsep(argv, ":")) != NULL) { 22766448911SDavid Höppner m++; 22866448911SDavid Höppner if (m > 4) { 22966448911SDavid Höppner free(uselector); 23066448911SDavid Höppner usage(); 23166448911SDavid Höppner exit(2); 23266448911SDavid Höppner } 23366448911SDavid Höppner 23466448911SDavid Höppner if (*q != '\0') { 23566448911SDavid Höppner switch (m) { 23666448911SDavid Höppner case 1: 23766448911SDavid Höppner uselector->ks_module.pstr = 23866448911SDavid Höppner (char *)ks_safe_strdup(q); 23966448911SDavid Höppner break; 24066448911SDavid Höppner case 2: 24166448911SDavid Höppner uselector->ks_instance.pstr = 24266448911SDavid Höppner (char *)ks_safe_strdup(q); 24366448911SDavid Höppner break; 24466448911SDavid Höppner case 3: 24566448911SDavid Höppner uselector->ks_name.pstr = 24666448911SDavid Höppner (char *)ks_safe_strdup(q); 24766448911SDavid Höppner break; 24866448911SDavid Höppner case 4: 24966448911SDavid Höppner uselector->ks_statistic.pstr = 25066448911SDavid Höppner (char *)ks_safe_strdup(q); 25166448911SDavid Höppner break; 25266448911SDavid Höppner default: 25366448911SDavid Höppner assert(B_FALSE); 25466448911SDavid Höppner } 25566448911SDavid Höppner } 25666448911SDavid Höppner } 25766448911SDavid Höppner 25866448911SDavid Höppner uselflg = B_TRUE; 25966448911SDavid Höppner list_insert_tail(&selector_list, uselector); 26066448911SDavid Höppner } else { 26166448911SDavid Höppner if (tmp < 1) { 26266448911SDavid Höppner if (n == 0) { 26366448911SDavid Höppner (void) fprintf(stderr, gettext( 26466448911SDavid Höppner "Interval must be an " 26566448911SDavid Höppner "integer >= 1")); 26666448911SDavid Höppner } else if (n == 1) { 26766448911SDavid Höppner (void) fprintf(stderr, gettext( 26866448911SDavid Höppner "Count must be an integer >= 1")); 26966448911SDavid Höppner } 27066448911SDavid Höppner usage(); 27166448911SDavid Höppner exit(2); 27266448911SDavid Höppner } else { 27366448911SDavid Höppner if (n == 0) { 27466448911SDavid Höppner interval = tmp; 27566448911SDavid Höppner count = -1; 27666448911SDavid Höppner } else if (n == 1) { 27766448911SDavid Höppner count = tmp; 27866448911SDavid Höppner } else { 27966448911SDavid Höppner usage(); 28066448911SDavid Höppner exit(2); 28166448911SDavid Höppner } 28266448911SDavid Höppner } 28366448911SDavid Höppner n++; 28466448911SDavid Höppner } 28566448911SDavid Höppner argv++; 28666448911SDavid Höppner } 28766448911SDavid Höppner 28866448911SDavid Höppner /* 28966448911SDavid Höppner * Check if we founded a named selector on the cmdline. 29066448911SDavid Höppner */ 29166448911SDavid Höppner if (uselflg) { 29266448911SDavid Höppner if (nselflg) { 29366448911SDavid Höppner (void) fprintf(stderr, gettext( 294617413d1SRichard Lowe "[module[:instance[:name[:statistic]]]] and " 29566448911SDavid Höppner "-m -i -n -s are mutually exclusive")); 29666448911SDavid Höppner usage(); 29766448911SDavid Höppner exit(2); 29866448911SDavid Höppner } else { 29966448911SDavid Höppner free(nselector); 30066448911SDavid Höppner } 30166448911SDavid Höppner } else { 30266448911SDavid Höppner list_insert_tail(&selector_list, nselector); 30366448911SDavid Höppner } 30466448911SDavid Höppner 30566448911SDavid Höppner assert(!list_is_empty(&selector_list)); 30666448911SDavid Höppner 30766448911SDavid Höppner list_create(&instances_list, sizeof (ks_instance_t), 30866448911SDavid Höppner offsetof(ks_instance_t, ks_next)); 30966448911SDavid Höppner 31066448911SDavid Höppner while ((kc = kstat_open()) == NULL) { 31166448911SDavid Höppner if (errno == EAGAIN) { 31266448911SDavid Höppner (void) poll(NULL, 0, 200); 31366448911SDavid Höppner } else { 31466448911SDavid Höppner perror("kstat_open"); 31566448911SDavid Höppner exit(3); 31666448911SDavid Höppner } 31766448911SDavid Höppner } 31866448911SDavid Höppner 31966448911SDavid Höppner if (count > 1) { 32066448911SDavid Höppner if (signal(SIGCONT, cont_handler) == SIG_ERR) { 32166448911SDavid Höppner (void) fprintf(stderr, gettext( 32266448911SDavid Höppner "signal failed")); 32366448911SDavid Höppner exit(3); 32466448911SDavid Höppner } 32566448911SDavid Höppner } 32666448911SDavid Höppner 32766448911SDavid Höppner period_n = (hrtime_t)interval * NANOSEC; 32866448911SDavid Höppner start_n = gethrtime(); 32966448911SDavid Höppner 33066448911SDavid Höppner while (count == -1 || count-- > 0) { 33166448911SDavid Höppner ks_instances_read(kc); 33266448911SDavid Höppner ks_instances_print(); 33366448911SDavid Höppner 33466448911SDavid Höppner if (interval && count) { 33566448911SDavid Höppner ks_sleep_until(&start_n, period_n, infinite_cycles, 33666448911SDavid Höppner &caught_cont); 33766448911SDavid Höppner (void) kstat_chain_update(kc); 33866448911SDavid Höppner (void) putchar('\n'); 33966448911SDavid Höppner } 34066448911SDavid Höppner } 34166448911SDavid Höppner 34266448911SDavid Höppner (void) kstat_close(kc); 34366448911SDavid Höppner 34466448911SDavid Höppner return (g_matched); 34566448911SDavid Höppner } 34666448911SDavid Höppner 34766448911SDavid Höppner /* 34866448911SDavid Höppner * Print usage. 34966448911SDavid Höppner */ 35066448911SDavid Höppner static void 35166448911SDavid Höppner usage(void) 35266448911SDavid Höppner { 35366448911SDavid Höppner (void) fprintf(stderr, gettext( 35466448911SDavid Höppner "Usage:\n" 35566448911SDavid Höppner "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ]\n" 35666448911SDavid Höppner " [ -m module ] [ -i instance ] [ -n name ] [ -s statistic ]\n" 35766448911SDavid Höppner " [ interval [ count ] ]\n" 35866448911SDavid Höppner "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ]\n" 359617413d1SRichard Lowe " [ module[:instance[:name[:statistic]]] ... ]\n" 36066448911SDavid Höppner " [ interval [ count ] ]\n")); 36166448911SDavid Höppner } 36266448911SDavid Höppner 36366448911SDavid Höppner /* 36466448911SDavid Höppner * Sort compare function. 36566448911SDavid Höppner */ 36666448911SDavid Höppner static int 36766448911SDavid Höppner compare_instances(ks_instance_t *l_arg, ks_instance_t *r_arg) 36866448911SDavid Höppner { 36966448911SDavid Höppner int rval; 37066448911SDavid Höppner 37166448911SDavid Höppner rval = strcasecmp(l_arg->ks_module, r_arg->ks_module); 37266448911SDavid Höppner if (rval == 0) { 37366448911SDavid Höppner if (l_arg->ks_instance == r_arg->ks_instance) { 37466448911SDavid Höppner return (strcasecmp(l_arg->ks_name, r_arg->ks_name)); 37566448911SDavid Höppner } else if (l_arg->ks_instance < r_arg->ks_instance) { 37666448911SDavid Höppner return (-1); 37766448911SDavid Höppner } else { 37866448911SDavid Höppner return (1); 37966448911SDavid Höppner } 38066448911SDavid Höppner } else { 38166448911SDavid Höppner return (rval); 38266448911SDavid Höppner } 38366448911SDavid Höppner } 38466448911SDavid Höppner 38566448911SDavid Höppner static char * 38666448911SDavid Höppner ks_safe_strdup(char *str) 38766448911SDavid Höppner { 38866448911SDavid Höppner char *ret; 38966448911SDavid Höppner 39066448911SDavid Höppner if (str == NULL) { 39166448911SDavid Höppner return (NULL); 39266448911SDavid Höppner } 39366448911SDavid Höppner 39466448911SDavid Höppner while ((ret = strdup(str)) == NULL) { 39566448911SDavid Höppner if (errno == EAGAIN) { 39666448911SDavid Höppner (void) poll(NULL, 0, 200); 39766448911SDavid Höppner } else { 39866448911SDavid Höppner perror("strdup"); 39966448911SDavid Höppner exit(3); 40066448911SDavid Höppner } 40166448911SDavid Höppner } 40266448911SDavid Höppner 40366448911SDavid Höppner return (ret); 40466448911SDavid Höppner } 40566448911SDavid Höppner 40666448911SDavid Höppner static void 40766448911SDavid Höppner ks_sleep_until(hrtime_t *wakeup, hrtime_t interval, int forever, 40866448911SDavid Höppner int *caught_cont) 40966448911SDavid Höppner { 41066448911SDavid Höppner hrtime_t now, pause, pause_left; 41166448911SDavid Höppner struct timespec pause_tv; 41266448911SDavid Höppner int status; 41366448911SDavid Höppner 41466448911SDavid Höppner now = gethrtime(); 41566448911SDavid Höppner pause = *wakeup + interval - now; 41666448911SDavid Höppner 41766448911SDavid Höppner if (pause <= 0 || pause < (interval / 4)) { 41866448911SDavid Höppner if (forever || *caught_cont) { 41966448911SDavid Höppner *wakeup = now + interval; 42066448911SDavid Höppner pause = interval; 42166448911SDavid Höppner } else { 42266448911SDavid Höppner pause = interval / 2; 42366448911SDavid Höppner *wakeup += interval; 42466448911SDavid Höppner } 42566448911SDavid Höppner } else { 42666448911SDavid Höppner *wakeup += interval; 42766448911SDavid Höppner } 42866448911SDavid Höppner 42966448911SDavid Höppner if (pause < 1000) { 43066448911SDavid Höppner return; 43166448911SDavid Höppner } 43266448911SDavid Höppner 43366448911SDavid Höppner pause_left = pause; 43466448911SDavid Höppner do { 43566448911SDavid Höppner pause_tv.tv_sec = pause_left / NANOSEC; 43666448911SDavid Höppner pause_tv.tv_nsec = pause_left % NANOSEC; 43766448911SDavid Höppner status = nanosleep(&pause_tv, (struct timespec *)NULL); 43866448911SDavid Höppner if (status < 0) { 43966448911SDavid Höppner if (errno == EINTR) { 44066448911SDavid Höppner now = gethrtime(); 44166448911SDavid Höppner pause_left = *wakeup - now; 44266448911SDavid Höppner if (pause_left < 1000) { 44366448911SDavid Höppner return; 44466448911SDavid Höppner } 44566448911SDavid Höppner } else { 44666448911SDavid Höppner perror("nanosleep"); 44766448911SDavid Höppner exit(3); 44866448911SDavid Höppner } 44966448911SDavid Höppner } 45066448911SDavid Höppner } while (status != 0); 45166448911SDavid Höppner } 45266448911SDavid Höppner 45366448911SDavid Höppner /* 45466448911SDavid Höppner * Inserts an instance in the per selector list. 45566448911SDavid Höppner */ 45666448911SDavid Höppner static void 45766448911SDavid Höppner nvpair_insert(ks_instance_t *ksi, char *name, ks_value_t *value, 45866448911SDavid Höppner uchar_t data_type) 45966448911SDavid Höppner { 46066448911SDavid Höppner ks_nvpair_t *instance; 46166448911SDavid Höppner ks_nvpair_t *tmp; 46266448911SDavid Höppner 46366448911SDavid Höppner instance = (ks_nvpair_t *)malloc(sizeof (ks_nvpair_t)); 46466448911SDavid Höppner if (instance == NULL) { 46566448911SDavid Höppner perror("malloc"); 46666448911SDavid Höppner exit(3); 46766448911SDavid Höppner } 46866448911SDavid Höppner 46966448911SDavid Höppner (void) strlcpy(instance->name, name, KSTAT_STRLEN); 47066448911SDavid Höppner (void) memcpy(&instance->value, value, sizeof (ks_value_t)); 47166448911SDavid Höppner instance->data_type = data_type; 47266448911SDavid Höppner 47366448911SDavid Höppner tmp = list_head(&ksi->ks_nvlist); 47466448911SDavid Höppner while (tmp != NULL && strcasecmp(instance->name, tmp->name) > 0) 47566448911SDavid Höppner tmp = list_next(&ksi->ks_nvlist, tmp); 47666448911SDavid Höppner 47766448911SDavid Höppner list_insert_before(&ksi->ks_nvlist, tmp, instance); 47866448911SDavid Höppner } 47966448911SDavid Höppner 48066448911SDavid Höppner /* 48166448911SDavid Höppner * Allocates a new all-matching selector. 48266448911SDavid Höppner */ 48366448911SDavid Höppner static ks_selector_t * 48466448911SDavid Höppner new_selector(void) 48566448911SDavid Höppner { 48666448911SDavid Höppner ks_selector_t *selector; 48766448911SDavid Höppner 48866448911SDavid Höppner selector = (ks_selector_t *)malloc(sizeof (ks_selector_t)); 48966448911SDavid Höppner if (selector == NULL) { 49066448911SDavid Höppner perror("malloc"); 49166448911SDavid Höppner exit(3); 49266448911SDavid Höppner } 49366448911SDavid Höppner 49466448911SDavid Höppner list_link_init(&selector->ks_next); 49566448911SDavid Höppner 49666448911SDavid Höppner selector->ks_module.pstr = "*"; 49766448911SDavid Höppner selector->ks_instance.pstr = "*"; 49866448911SDavid Höppner selector->ks_name.pstr = "*"; 49966448911SDavid Höppner selector->ks_statistic.pstr = "*"; 50066448911SDavid Höppner 50166448911SDavid Höppner return (selector); 50266448911SDavid Höppner } 50366448911SDavid Höppner 50466448911SDavid Höppner /* 50566448911SDavid Höppner * This function was taken from the perl kstat module code - please 50666448911SDavid Höppner * see for further comments there. 50766448911SDavid Höppner */ 50866448911SDavid Höppner static kstat_raw_reader_t 50966448911SDavid Höppner lookup_raw_kstat_fn(char *module, char *name) 51066448911SDavid Höppner { 51166448911SDavid Höppner char key[KSTAT_STRLEN * 2]; 51266448911SDavid Höppner register char *f, *t; 51366448911SDavid Höppner int n = 0; 51466448911SDavid Höppner 51566448911SDavid Höppner for (f = module, t = key; *f != '\0'; f++, t++) { 51666448911SDavid Höppner while (*f != '\0' && isdigit(*f)) 51766448911SDavid Höppner f++; 51866448911SDavid Höppner *t = *f; 51966448911SDavid Höppner } 52066448911SDavid Höppner *t++ = ':'; 52166448911SDavid Höppner 52266448911SDavid Höppner for (f = name; *f != '\0'; f++, t++) { 52366448911SDavid Höppner while (*f != '\0' && isdigit(*f)) 52466448911SDavid Höppner f++; 52566448911SDavid Höppner *t = *f; 52666448911SDavid Höppner } 52766448911SDavid Höppner *t = '\0'; 52866448911SDavid Höppner 52966448911SDavid Höppner while (ks_raw_lookup[n].fn != NULL) { 53066448911SDavid Höppner if (strncmp(ks_raw_lookup[n].name, key, strlen(key)) == 0) 53166448911SDavid Höppner return (ks_raw_lookup[n].fn); 53266448911SDavid Höppner n++; 53366448911SDavid Höppner } 53466448911SDavid Höppner 53566448911SDavid Höppner return (0); 53666448911SDavid Höppner } 53766448911SDavid Höppner 53866448911SDavid Höppner /* 53966448911SDavid Höppner * Match a string against a shell glob or extended regular expression. 54066448911SDavid Höppner */ 54166448911SDavid Höppner static boolean_t 54266448911SDavid Höppner ks_match(const char *str, ks_pattern_t *pattern) 54366448911SDavid Höppner { 54466448911SDavid Höppner int regcode; 54566448911SDavid Höppner char *regstr; 54666448911SDavid Höppner char *errbuf; 54766448911SDavid Höppner size_t bufsz; 54866448911SDavid Höppner 54966448911SDavid Höppner if (pattern->pstr != NULL && gmatch(pattern->pstr, "/*/") != 0) { 55066448911SDavid Höppner /* All regex patterns are strdup'd copies */ 55166448911SDavid Höppner regstr = pattern->pstr + 1; 55266448911SDavid Höppner *(strrchr(regstr, '/')) = '\0'; 55366448911SDavid Höppner 55466448911SDavid Höppner regcode = regcomp(&pattern->preg, regstr, 55566448911SDavid Höppner REG_EXTENDED | REG_NOSUB); 55666448911SDavid Höppner if (regcode != 0) { 55766448911SDavid Höppner bufsz = regerror(regcode, NULL, NULL, 0); 55866448911SDavid Höppner if (bufsz != 0) { 55966448911SDavid Höppner errbuf = malloc(bufsz); 56066448911SDavid Höppner if (errbuf == NULL) { 56166448911SDavid Höppner perror("malloc"); 56266448911SDavid Höppner exit(3); 56366448911SDavid Höppner } 56466448911SDavid Höppner (void) regerror(regcode, NULL, errbuf, bufsz); 56566448911SDavid Höppner (void) fprintf(stderr, "kstat: %s\n", errbuf); 56666448911SDavid Höppner } 56766448911SDavid Höppner usage(); 56866448911SDavid Höppner exit(2); 56966448911SDavid Höppner } 57066448911SDavid Höppner 57166448911SDavid Höppner pattern->pstr = NULL; 57266448911SDavid Höppner } 57366448911SDavid Höppner 57466448911SDavid Höppner if (pattern->pstr == NULL) { 57566448911SDavid Höppner return (regexec(&pattern->preg, str, 0, NULL, 0) == 0); 57666448911SDavid Höppner } 57766448911SDavid Höppner 57866448911SDavid Höppner return ((gmatch(str, pattern->pstr) != 0)); 57966448911SDavid Höppner } 58066448911SDavid Höppner 58166448911SDavid Höppner /* 58266448911SDavid Höppner * Iterate over all kernel statistics and save matches. 58366448911SDavid Höppner */ 58466448911SDavid Höppner static void 58566448911SDavid Höppner ks_instances_read(kstat_ctl_t *kc) 58666448911SDavid Höppner { 58766448911SDavid Höppner kstat_raw_reader_t save_raw = NULL; 58866448911SDavid Höppner kid_t id; 58966448911SDavid Höppner ks_selector_t *selector; 59066448911SDavid Höppner ks_instance_t *ksi; 59166448911SDavid Höppner ks_instance_t *tmp; 59266448911SDavid Höppner kstat_t *kp; 59366448911SDavid Höppner boolean_t skip; 59466448911SDavid Höppner 59566448911SDavid Höppner for (kp = kc->kc_chain; kp != NULL; kp = kp->ks_next) { 59666448911SDavid Höppner /* Don't bother storing the kstat headers */ 59766448911SDavid Höppner if (strncmp(kp->ks_name, "kstat_", 6) == 0) { 59866448911SDavid Höppner continue; 59966448911SDavid Höppner } 60066448911SDavid Höppner 60166448911SDavid Höppner /* Don't bother storing raw stats we don't understand */ 60266448911SDavid Höppner if (kp->ks_type == KSTAT_TYPE_RAW) { 60366448911SDavid Höppner save_raw = lookup_raw_kstat_fn(kp->ks_module, 60466448911SDavid Höppner kp->ks_name); 60566448911SDavid Höppner if (save_raw == NULL) { 60666448911SDavid Höppner #ifdef REPORT_UNKNOWN 60766448911SDavid Höppner (void) fprintf(stderr, 60866448911SDavid Höppner "Unknown kstat type %s:%d:%s - " 60966448911SDavid Höppner "%d of size %d\n", kp->ks_module, 61066448911SDavid Höppner kp->ks_instance, kp->ks_name, 61166448911SDavid Höppner kp->ks_ndata, kp->ks_data_size); 61266448911SDavid Höppner #endif 61366448911SDavid Höppner continue; 61466448911SDavid Höppner } 61566448911SDavid Höppner } 61666448911SDavid Höppner 61766448911SDavid Höppner /* 61866448911SDavid Höppner * Iterate over the list of selectors and skip 61966448911SDavid Höppner * instances we dont want. We filter for statistics 62066448911SDavid Höppner * later, as we dont know them yet. 62166448911SDavid Höppner */ 62266448911SDavid Höppner skip = B_TRUE; 62366448911SDavid Höppner selector = list_head(&selector_list); 62466448911SDavid Höppner while (selector != NULL) { 625*9736aecdSBryan Cantrill if (ks_match(kp->ks_module, &selector->ks_module) && 62666448911SDavid Höppner ks_match(kp->ks_name, &selector->ks_name)) { 62766448911SDavid Höppner skip = B_FALSE; 62866448911SDavid Höppner break; 62966448911SDavid Höppner } 63066448911SDavid Höppner selector = list_next(&selector_list, selector); 63166448911SDavid Höppner } 63266448911SDavid Höppner 63366448911SDavid Höppner if (skip) { 63466448911SDavid Höppner continue; 63566448911SDavid Höppner } 63666448911SDavid Höppner 63766448911SDavid Höppner /* 63866448911SDavid Höppner * Allocate a new instance and fill in the values 63966448911SDavid Höppner * we know so far. 64066448911SDavid Höppner */ 64166448911SDavid Höppner ksi = (ks_instance_t *)malloc(sizeof (ks_instance_t)); 64266448911SDavid Höppner if (ksi == NULL) { 64366448911SDavid Höppner perror("malloc"); 64466448911SDavid Höppner exit(3); 64566448911SDavid Höppner } 64666448911SDavid Höppner 64766448911SDavid Höppner list_link_init(&ksi->ks_next); 64866448911SDavid Höppner 64966448911SDavid Höppner (void) strlcpy(ksi->ks_module, kp->ks_module, KSTAT_STRLEN); 65066448911SDavid Höppner (void) strlcpy(ksi->ks_name, kp->ks_name, KSTAT_STRLEN); 65166448911SDavid Höppner (void) strlcpy(ksi->ks_class, kp->ks_class, KSTAT_STRLEN); 65266448911SDavid Höppner 65366448911SDavid Höppner ksi->ks_instance = kp->ks_instance; 65466448911SDavid Höppner ksi->ks_snaptime = kp->ks_snaptime; 65566448911SDavid Höppner ksi->ks_type = kp->ks_type; 65666448911SDavid Höppner 65766448911SDavid Höppner list_create(&ksi->ks_nvlist, sizeof (ks_nvpair_t), 65866448911SDavid Höppner offsetof(ks_nvpair_t, nv_next)); 65966448911SDavid Höppner 66066448911SDavid Höppner SAVE_HRTIME_X(ksi, "crtime", kp->ks_crtime); 66166448911SDavid Höppner SAVE_HRTIME_X(ksi, "snaptime", kp->ks_snaptime); 66266448911SDavid Höppner if (g_pflg) { 66366448911SDavid Höppner SAVE_STRING_X(ksi, "class", kp->ks_class); 66466448911SDavid Höppner } 66566448911SDavid Höppner 66666448911SDavid Höppner /* Insert this instance into a sorted list */ 66766448911SDavid Höppner tmp = list_head(&instances_list); 66866448911SDavid Höppner while (tmp != NULL && compare_instances(ksi, tmp) > 0) 66966448911SDavid Höppner tmp = list_next(&instances_list, tmp); 67066448911SDavid Höppner 67166448911SDavid Höppner list_insert_before(&instances_list, tmp, ksi); 67266448911SDavid Höppner 67366448911SDavid Höppner /* Read the actual statistics */ 67466448911SDavid Höppner id = kstat_read(kc, kp, NULL); 67566448911SDavid Höppner if (id == -1) { 67666448911SDavid Höppner #ifdef REPORT_UNKNOWN 67766448911SDavid Höppner perror("kstat_read"); 67866448911SDavid Höppner #endif 67966448911SDavid Höppner continue; 68066448911SDavid Höppner } 68166448911SDavid Höppner 68266448911SDavid Höppner switch (kp->ks_type) { 68366448911SDavid Höppner case KSTAT_TYPE_RAW: 68466448911SDavid Höppner save_raw(kp, ksi); 68566448911SDavid Höppner break; 68666448911SDavid Höppner case KSTAT_TYPE_NAMED: 68766448911SDavid Höppner save_named(kp, ksi); 68866448911SDavid Höppner break; 68966448911SDavid Höppner case KSTAT_TYPE_INTR: 69066448911SDavid Höppner save_intr(kp, ksi); 69166448911SDavid Höppner break; 69266448911SDavid Höppner case KSTAT_TYPE_IO: 69366448911SDavid Höppner save_io(kp, ksi); 69466448911SDavid Höppner break; 69566448911SDavid Höppner case KSTAT_TYPE_TIMER: 69666448911SDavid Höppner save_timer(kp, ksi); 69766448911SDavid Höppner break; 69866448911SDavid Höppner default: 69966448911SDavid Höppner assert(B_FALSE); /* Invalid type */ 70066448911SDavid Höppner break; 70166448911SDavid Höppner } 70266448911SDavid Höppner } 70366448911SDavid Höppner } 70466448911SDavid Höppner 70566448911SDavid Höppner /* 70666448911SDavid Höppner * Print the value of a name-value pair. 70766448911SDavid Höppner */ 70866448911SDavid Höppner static void 70966448911SDavid Höppner ks_value_print(ks_nvpair_t *nvpair) 71066448911SDavid Höppner { 71166448911SDavid Höppner switch (nvpair->data_type) { 71266448911SDavid Höppner case KSTAT_DATA_CHAR: 71366448911SDavid Höppner (void) fprintf(stdout, "%s", nvpair->value.c); 71466448911SDavid Höppner break; 71566448911SDavid Höppner case KSTAT_DATA_INT32: 71666448911SDavid Höppner (void) fprintf(stdout, "%d", nvpair->value.i32); 71766448911SDavid Höppner break; 71866448911SDavid Höppner case KSTAT_DATA_UINT32: 71966448911SDavid Höppner (void) fprintf(stdout, "%u", nvpair->value.ui32); 72066448911SDavid Höppner break; 72166448911SDavid Höppner case KSTAT_DATA_INT64: 72266448911SDavid Höppner (void) fprintf(stdout, "%lld", nvpair->value.i64); 72366448911SDavid Höppner break; 72466448911SDavid Höppner case KSTAT_DATA_UINT64: 72566448911SDavid Höppner (void) fprintf(stdout, "%llu", nvpair->value.ui64); 72666448911SDavid Höppner break; 72766448911SDavid Höppner case KSTAT_DATA_STRING: 72866448911SDavid Höppner (void) fprintf(stdout, "%s", KSTAT_NAMED_STR_PTR(nvpair)); 72966448911SDavid Höppner break; 73066448911SDavid Höppner case KSTAT_DATA_HRTIME: 73166448911SDavid Höppner if (nvpair->value.ui64 == 0) 73266448911SDavid Höppner (void) fprintf(stdout, "0"); 73366448911SDavid Höppner else 73466448911SDavid Höppner (void) fprintf(stdout, "%.9f", 73566448911SDavid Höppner nvpair->value.ui64 / 1000000000.0); 73666448911SDavid Höppner break; 73766448911SDavid Höppner default: 73866448911SDavid Höppner assert(B_FALSE); 73966448911SDavid Höppner } 74066448911SDavid Höppner } 74166448911SDavid Höppner 74266448911SDavid Höppner /* 74366448911SDavid Höppner * Print a single instance. 74466448911SDavid Höppner */ 74566448911SDavid Höppner static void 74666448911SDavid Höppner ks_instance_print(ks_instance_t *ksi, ks_nvpair_t *nvpair) 74766448911SDavid Höppner { 74866448911SDavid Höppner if (g_headerflg) { 74966448911SDavid Höppner if (!g_pflg) { 75066448911SDavid Höppner (void) fprintf(stdout, DFLT_FMT, 75166448911SDavid Höppner ksi->ks_module, ksi->ks_instance, 75266448911SDavid Höppner ksi->ks_name, ksi->ks_class); 75366448911SDavid Höppner } 75466448911SDavid Höppner g_headerflg = B_FALSE; 75566448911SDavid Höppner } 75666448911SDavid Höppner 75766448911SDavid Höppner if (g_pflg) { 75866448911SDavid Höppner (void) fprintf(stdout, KS_PFMT, 75966448911SDavid Höppner ksi->ks_module, ksi->ks_instance, 76066448911SDavid Höppner ksi->ks_name, nvpair->name); 76166448911SDavid Höppner if (!g_lflg) { 76266448911SDavid Höppner (void) putchar(g_cflg ? ':': '\t'); 76366448911SDavid Höppner ks_value_print(nvpair); 76466448911SDavid Höppner } 76566448911SDavid Höppner } else { 76666448911SDavid Höppner (void) fprintf(stdout, KS_DFMT, nvpair->name); 76766448911SDavid Höppner ks_value_print(nvpair); 76866448911SDavid Höppner } 76966448911SDavid Höppner 77066448911SDavid Höppner (void) putchar('\n'); 77166448911SDavid Höppner } 77266448911SDavid Höppner 77366448911SDavid Höppner /* 77466448911SDavid Höppner * Print a single instance in JSON format. 77566448911SDavid Höppner */ 77666448911SDavid Höppner static void 77766448911SDavid Höppner ks_instance_print_json(ks_instance_t *ksi, ks_nvpair_t *nvpair) 77866448911SDavid Höppner { 77966448911SDavid Höppner if (g_headerflg) { 78066448911SDavid Höppner (void) fprintf(stdout, JSON_FMT, 78166448911SDavid Höppner ksi->ks_module, ksi->ks_instance, 78266448911SDavid Höppner ksi->ks_name, ksi->ks_class, 78366448911SDavid Höppner ksi->ks_type); 78466448911SDavid Höppner 78566448911SDavid Höppner if (ksi->ks_snaptime == 0) 78666448911SDavid Höppner (void) fprintf(stdout, "\t\"snaptime\": 0,\n"); 78766448911SDavid Höppner else 78866448911SDavid Höppner (void) fprintf(stdout, "\t\"snaptime\": %.9f,\n", 78966448911SDavid Höppner ksi->ks_snaptime / 1000000000.0); 79066448911SDavid Höppner 79166448911SDavid Höppner (void) fprintf(stdout, "\t\"data\": {\n"); 79266448911SDavid Höppner 79366448911SDavid Höppner g_headerflg = B_FALSE; 79466448911SDavid Höppner } 79566448911SDavid Höppner 79666448911SDavid Höppner (void) fprintf(stdout, KS_JFMT, nvpair->name); 79766448911SDavid Höppner if (nvpair->data_type == KSTAT_DATA_STRING) { 79866448911SDavid Höppner (void) putchar('\"'); 79966448911SDavid Höppner ks_value_print(nvpair); 80066448911SDavid Höppner (void) putchar('\"'); 80166448911SDavid Höppner } else { 80266448911SDavid Höppner ks_value_print(nvpair); 80366448911SDavid Höppner } 80466448911SDavid Höppner if (nvpair != list_tail(&ksi->ks_nvlist)) 80566448911SDavid Höppner (void) putchar(','); 80666448911SDavid Höppner 80766448911SDavid Höppner (void) putchar('\n'); 80866448911SDavid Höppner } 80966448911SDavid Höppner 81066448911SDavid Höppner /* 81166448911SDavid Höppner * Print all instances. 81266448911SDavid Höppner */ 81366448911SDavid Höppner static void 81466448911SDavid Höppner ks_instances_print(void) 81566448911SDavid Höppner { 81666448911SDavid Höppner ks_selector_t *selector; 81766448911SDavid Höppner ks_instance_t *ksi, *ktmp; 81866448911SDavid Höppner ks_nvpair_t *nvpair, *ntmp; 81966448911SDavid Höppner void (*ks_print_fn)(ks_instance_t *, ks_nvpair_t *); 82066448911SDavid Höppner char *ks_number; 82166448911SDavid Höppner 82266448911SDavid Höppner if (g_timestamp_fmt != NODATE) 82366448911SDavid Höppner print_timestamp(g_timestamp_fmt); 82466448911SDavid Höppner 82566448911SDavid Höppner if (g_jflg) { 82666448911SDavid Höppner ks_print_fn = &ks_instance_print_json; 82766448911SDavid Höppner (void) putchar('['); 82866448911SDavid Höppner } else { 82966448911SDavid Höppner ks_print_fn = &ks_instance_print; 83066448911SDavid Höppner } 83166448911SDavid Höppner 83266448911SDavid Höppner /* Iterate over each selector */ 83366448911SDavid Höppner selector = list_head(&selector_list); 83466448911SDavid Höppner while (selector != NULL) { 83566448911SDavid Höppner 83666448911SDavid Höppner /* Iterate over each instance */ 83766448911SDavid Höppner for (ksi = list_head(&instances_list); ksi != NULL; 83866448911SDavid Höppner ksi = list_next(&instances_list, ksi)) { 83966448911SDavid Höppner 84066448911SDavid Höppner (void) asprintf(&ks_number, "%d", ksi->ks_instance); 84166448911SDavid Höppner if (!(ks_match(ksi->ks_module, &selector->ks_module) && 84266448911SDavid Höppner ks_match(ksi->ks_name, &selector->ks_name) && 84366448911SDavid Höppner ks_match(ks_number, &selector->ks_instance) && 84466448911SDavid Höppner ks_match(ksi->ks_class, &g_ks_class))) { 84566448911SDavid Höppner free(ks_number); 84666448911SDavid Höppner continue; 84766448911SDavid Höppner } 84866448911SDavid Höppner 84966448911SDavid Höppner free(ks_number); 85066448911SDavid Höppner 85166448911SDavid Höppner /* Finally iterate over each statistic */ 85266448911SDavid Höppner g_headerflg = B_TRUE; 85366448911SDavid Höppner for (nvpair = list_head(&ksi->ks_nvlist); 85466448911SDavid Höppner nvpair != NULL; 85566448911SDavid Höppner nvpair = list_next(&ksi->ks_nvlist, nvpair)) { 85666448911SDavid Höppner if (!ks_match(nvpair->name, 85766448911SDavid Höppner &selector->ks_statistic)) 85866448911SDavid Höppner continue; 85966448911SDavid Höppner 86066448911SDavid Höppner g_matched = 0; 86166448911SDavid Höppner if (!g_qflg) 86266448911SDavid Höppner (*ks_print_fn)(ksi, nvpair); 86366448911SDavid Höppner } 86466448911SDavid Höppner 86566448911SDavid Höppner if (!g_headerflg) { 86666448911SDavid Höppner if (g_jflg) { 86766448911SDavid Höppner (void) fprintf(stdout, "\t}\n}"); 86866448911SDavid Höppner if (ksi != list_tail(&instances_list)) 86966448911SDavid Höppner (void) putchar(','); 87066448911SDavid Höppner } else if (!g_pflg) { 87166448911SDavid Höppner (void) putchar('\n'); 87266448911SDavid Höppner } 87366448911SDavid Höppner } 87466448911SDavid Höppner } 87566448911SDavid Höppner 87666448911SDavid Höppner selector = list_next(&selector_list, selector); 87766448911SDavid Höppner } 87866448911SDavid Höppner 87966448911SDavid Höppner if (g_jflg) 88066448911SDavid Höppner (void) fprintf(stdout, "]\n"); 88166448911SDavid Höppner 88266448911SDavid Höppner (void) fflush(stdout); 88366448911SDavid Höppner 88466448911SDavid Höppner /* Free the instances list */ 88566448911SDavid Höppner ksi = list_head(&instances_list); 88666448911SDavid Höppner while (ksi != NULL) { 88766448911SDavid Höppner nvpair = list_head(&ksi->ks_nvlist); 88866448911SDavid Höppner while (nvpair != NULL) { 88966448911SDavid Höppner ntmp = nvpair; 89066448911SDavid Höppner nvpair = list_next(&ksi->ks_nvlist, nvpair); 89166448911SDavid Höppner list_remove(&ksi->ks_nvlist, ntmp); 89266448911SDavid Höppner if (ntmp->data_type == KSTAT_DATA_STRING) 89366448911SDavid Höppner free(ntmp->value.str.addr.ptr); 89466448911SDavid Höppner free(ntmp); 89566448911SDavid Höppner } 89666448911SDavid Höppner 89766448911SDavid Höppner ktmp = ksi; 89866448911SDavid Höppner ksi = list_next(&instances_list, ksi); 89966448911SDavid Höppner list_remove(&instances_list, ktmp); 90066448911SDavid Höppner list_destroy(&ktmp->ks_nvlist); 90166448911SDavid Höppner free(ktmp); 90266448911SDavid Höppner } 90366448911SDavid Höppner } 90466448911SDavid Höppner 90566448911SDavid Höppner static void 90666448911SDavid Höppner save_cpu_stat(kstat_t *kp, ks_instance_t *ksi) 90766448911SDavid Höppner { 90866448911SDavid Höppner cpu_stat_t *stat; 90966448911SDavid Höppner cpu_sysinfo_t *sysinfo; 91066448911SDavid Höppner cpu_syswait_t *syswait; 91166448911SDavid Höppner cpu_vminfo_t *vminfo; 91266448911SDavid Höppner 91366448911SDavid Höppner stat = (cpu_stat_t *)(kp->ks_data); 91466448911SDavid Höppner sysinfo = &stat->cpu_sysinfo; 91566448911SDavid Höppner syswait = &stat->cpu_syswait; 91666448911SDavid Höppner vminfo = &stat->cpu_vminfo; 91766448911SDavid Höppner 91866448911SDavid Höppner SAVE_UINT32_X(ksi, "idle", sysinfo->cpu[CPU_IDLE]); 91966448911SDavid Höppner SAVE_UINT32_X(ksi, "user", sysinfo->cpu[CPU_USER]); 92066448911SDavid Höppner SAVE_UINT32_X(ksi, "kernel", sysinfo->cpu[CPU_KERNEL]); 92166448911SDavid Höppner SAVE_UINT32_X(ksi, "wait", sysinfo->cpu[CPU_WAIT]); 9225918f984SRichard Lowe SAVE_UINT32_X(ksi, "wait_io", sysinfo->wait[W_IO]); 9235918f984SRichard Lowe SAVE_UINT32_X(ksi, "wait_swap", sysinfo->wait[W_SWAP]); 9245918f984SRichard Lowe SAVE_UINT32_X(ksi, "wait_pio", sysinfo->wait[W_PIO]); 92566448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, bread); 92666448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, bwrite); 92766448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, lread); 92866448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, lwrite); 92966448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, phread); 93066448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, phwrite); 93166448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, pswitch); 93266448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, trap); 93366448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, intr); 93466448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, syscall); 93566448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, sysread); 93666448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, syswrite); 93766448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, sysfork); 93866448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, sysvfork); 93966448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, sysexec); 94066448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, readch); 94166448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, writech); 94266448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, rcvint); 94366448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, xmtint); 94466448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, mdmint); 94566448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, rawch); 94666448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, canch); 94766448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, outch); 94866448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, msg); 94966448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, sema); 95066448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, namei); 95166448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, ufsiget); 95266448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, ufsdirblk); 95366448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, ufsipage); 95466448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, ufsinopage); 95566448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, inodeovf); 95666448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, fileovf); 95766448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, procovf); 95866448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, intrthread); 95966448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, intrblk); 96066448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, idlethread); 96166448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, inv_swtch); 96266448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, nthreads); 96366448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, cpumigrate); 96466448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, xcalls); 96566448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, mutex_adenters); 96666448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, rw_rdfails); 96766448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, rw_wrfails); 96866448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, modload); 96966448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, modunload); 97066448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, bawrite); 97166448911SDavid Höppner #ifdef STATISTICS /* see header file */ 97266448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, rw_enters); 97366448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, win_uo_cnt); 97466448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, win_uu_cnt); 97566448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, win_so_cnt); 97666448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, win_su_cnt); 97766448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, win_suo_cnt); 97866448911SDavid Höppner #endif 97966448911SDavid Höppner 98066448911SDavid Höppner SAVE_INT32(ksi, syswait, iowait); 98166448911SDavid Höppner SAVE_INT32(ksi, syswait, swap); 98266448911SDavid Höppner SAVE_INT32(ksi, syswait, physio); 98366448911SDavid Höppner 98466448911SDavid Höppner SAVE_UINT32(ksi, vminfo, pgrec); 98566448911SDavid Höppner SAVE_UINT32(ksi, vminfo, pgfrec); 98666448911SDavid Höppner SAVE_UINT32(ksi, vminfo, pgin); 98766448911SDavid Höppner SAVE_UINT32(ksi, vminfo, pgpgin); 98866448911SDavid Höppner SAVE_UINT32(ksi, vminfo, pgout); 98966448911SDavid Höppner SAVE_UINT32(ksi, vminfo, pgpgout); 99066448911SDavid Höppner SAVE_UINT32(ksi, vminfo, swapin); 99166448911SDavid Höppner SAVE_UINT32(ksi, vminfo, pgswapin); 99266448911SDavid Höppner SAVE_UINT32(ksi, vminfo, swapout); 99366448911SDavid Höppner SAVE_UINT32(ksi, vminfo, pgswapout); 99466448911SDavid Höppner SAVE_UINT32(ksi, vminfo, zfod); 99566448911SDavid Höppner SAVE_UINT32(ksi, vminfo, dfree); 99666448911SDavid Höppner SAVE_UINT32(ksi, vminfo, scan); 99766448911SDavid Höppner SAVE_UINT32(ksi, vminfo, rev); 99866448911SDavid Höppner SAVE_UINT32(ksi, vminfo, hat_fault); 99966448911SDavid Höppner SAVE_UINT32(ksi, vminfo, as_fault); 100066448911SDavid Höppner SAVE_UINT32(ksi, vminfo, maj_fault); 100166448911SDavid Höppner SAVE_UINT32(ksi, vminfo, cow_fault); 100266448911SDavid Höppner SAVE_UINT32(ksi, vminfo, prot_fault); 100366448911SDavid Höppner SAVE_UINT32(ksi, vminfo, softlock); 100466448911SDavid Höppner SAVE_UINT32(ksi, vminfo, kernel_asflt); 100566448911SDavid Höppner SAVE_UINT32(ksi, vminfo, pgrrun); 100666448911SDavid Höppner SAVE_UINT32(ksi, vminfo, execpgin); 100766448911SDavid Höppner SAVE_UINT32(ksi, vminfo, execpgout); 100866448911SDavid Höppner SAVE_UINT32(ksi, vminfo, execfree); 100966448911SDavid Höppner SAVE_UINT32(ksi, vminfo, anonpgin); 101066448911SDavid Höppner SAVE_UINT32(ksi, vminfo, anonpgout); 101166448911SDavid Höppner SAVE_UINT32(ksi, vminfo, anonfree); 101266448911SDavid Höppner SAVE_UINT32(ksi, vminfo, fspgin); 101366448911SDavid Höppner SAVE_UINT32(ksi, vminfo, fspgout); 101466448911SDavid Höppner SAVE_UINT32(ksi, vminfo, fsfree); 101566448911SDavid Höppner } 101666448911SDavid Höppner 101766448911SDavid Höppner static void 101866448911SDavid Höppner save_var(kstat_t *kp, ks_instance_t *ksi) 101966448911SDavid Höppner { 102066448911SDavid Höppner struct var *var = (struct var *)(kp->ks_data); 102166448911SDavid Höppner 102266448911SDavid Höppner assert(kp->ks_data_size == sizeof (struct var)); 102366448911SDavid Höppner 102466448911SDavid Höppner SAVE_INT32(ksi, var, v_buf); 102566448911SDavid Höppner SAVE_INT32(ksi, var, v_call); 102666448911SDavid Höppner SAVE_INT32(ksi, var, v_proc); 102766448911SDavid Höppner SAVE_INT32(ksi, var, v_maxupttl); 102866448911SDavid Höppner SAVE_INT32(ksi, var, v_nglobpris); 102966448911SDavid Höppner SAVE_INT32(ksi, var, v_maxsyspri); 103066448911SDavid Höppner SAVE_INT32(ksi, var, v_clist); 103166448911SDavid Höppner SAVE_INT32(ksi, var, v_maxup); 103266448911SDavid Höppner SAVE_INT32(ksi, var, v_hbuf); 103366448911SDavid Höppner SAVE_INT32(ksi, var, v_hmask); 103466448911SDavid Höppner SAVE_INT32(ksi, var, v_pbuf); 103566448911SDavid Höppner SAVE_INT32(ksi, var, v_sptmap); 103666448911SDavid Höppner SAVE_INT32(ksi, var, v_maxpmem); 103766448911SDavid Höppner SAVE_INT32(ksi, var, v_autoup); 103866448911SDavid Höppner SAVE_INT32(ksi, var, v_bufhwm); 103966448911SDavid Höppner } 104066448911SDavid Höppner 104166448911SDavid Höppner static void 104266448911SDavid Höppner save_ncstats(kstat_t *kp, ks_instance_t *ksi) 104366448911SDavid Höppner { 104466448911SDavid Höppner struct ncstats *ncstats = (struct ncstats *)(kp->ks_data); 104566448911SDavid Höppner 104666448911SDavid Höppner assert(kp->ks_data_size == sizeof (struct ncstats)); 104766448911SDavid Höppner 104866448911SDavid Höppner SAVE_INT32(ksi, ncstats, hits); 104966448911SDavid Höppner SAVE_INT32(ksi, ncstats, misses); 105066448911SDavid Höppner SAVE_INT32(ksi, ncstats, enters); 105166448911SDavid Höppner SAVE_INT32(ksi, ncstats, dbl_enters); 105266448911SDavid Höppner SAVE_INT32(ksi, ncstats, long_enter); 105366448911SDavid Höppner SAVE_INT32(ksi, ncstats, long_look); 105466448911SDavid Höppner SAVE_INT32(ksi, ncstats, move_to_front); 105566448911SDavid Höppner SAVE_INT32(ksi, ncstats, purges); 105666448911SDavid Höppner } 105766448911SDavid Höppner 105866448911SDavid Höppner static void 105966448911SDavid Höppner save_sysinfo(kstat_t *kp, ks_instance_t *ksi) 106066448911SDavid Höppner { 106166448911SDavid Höppner sysinfo_t *sysinfo = (sysinfo_t *)(kp->ks_data); 106266448911SDavid Höppner 106366448911SDavid Höppner assert(kp->ks_data_size == sizeof (sysinfo_t)); 106466448911SDavid Höppner 106566448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, updates); 106666448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, runque); 106766448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, runocc); 106866448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, swpque); 106966448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, swpocc); 107066448911SDavid Höppner SAVE_UINT32(ksi, sysinfo, waiting); 107166448911SDavid Höppner } 107266448911SDavid Höppner 107366448911SDavid Höppner static void 107466448911SDavid Höppner save_vminfo(kstat_t *kp, ks_instance_t *ksi) 107566448911SDavid Höppner { 107666448911SDavid Höppner vminfo_t *vminfo = (vminfo_t *)(kp->ks_data); 107766448911SDavid Höppner 107866448911SDavid Höppner assert(kp->ks_data_size == sizeof (vminfo_t)); 107966448911SDavid Höppner 108066448911SDavid Höppner SAVE_UINT64(ksi, vminfo, freemem); 108166448911SDavid Höppner SAVE_UINT64(ksi, vminfo, swap_resv); 108266448911SDavid Höppner SAVE_UINT64(ksi, vminfo, swap_alloc); 108366448911SDavid Höppner SAVE_UINT64(ksi, vminfo, swap_avail); 108466448911SDavid Höppner SAVE_UINT64(ksi, vminfo, swap_free); 108566448911SDavid Höppner SAVE_UINT64(ksi, vminfo, updates); 108666448911SDavid Höppner } 108766448911SDavid Höppner 108866448911SDavid Höppner static void 108966448911SDavid Höppner save_nfs(kstat_t *kp, ks_instance_t *ksi) 109066448911SDavid Höppner { 109166448911SDavid Höppner struct mntinfo_kstat *mntinfo = (struct mntinfo_kstat *)(kp->ks_data); 109266448911SDavid Höppner 109366448911SDavid Höppner assert(kp->ks_data_size == sizeof (struct mntinfo_kstat)); 109466448911SDavid Höppner 109566448911SDavid Höppner SAVE_STRING(ksi, mntinfo, mik_proto); 109666448911SDavid Höppner SAVE_UINT32(ksi, mntinfo, mik_vers); 109766448911SDavid Höppner SAVE_UINT32(ksi, mntinfo, mik_flags); 109866448911SDavid Höppner SAVE_UINT32(ksi, mntinfo, mik_secmod); 109966448911SDavid Höppner SAVE_UINT32(ksi, mntinfo, mik_curread); 110066448911SDavid Höppner SAVE_UINT32(ksi, mntinfo, mik_curwrite); 110166448911SDavid Höppner SAVE_INT32(ksi, mntinfo, mik_timeo); 110266448911SDavid Höppner SAVE_INT32(ksi, mntinfo, mik_retrans); 110366448911SDavid Höppner SAVE_UINT32(ksi, mntinfo, mik_acregmin); 110466448911SDavid Höppner SAVE_UINT32(ksi, mntinfo, mik_acregmax); 110566448911SDavid Höppner SAVE_UINT32(ksi, mntinfo, mik_acdirmin); 110666448911SDavid Höppner SAVE_UINT32(ksi, mntinfo, mik_acdirmax); 110766448911SDavid Höppner SAVE_UINT32_X(ksi, "lookup_srtt", mntinfo->mik_timers[0].srtt); 110866448911SDavid Höppner SAVE_UINT32_X(ksi, "lookup_deviate", mntinfo->mik_timers[0].deviate); 110966448911SDavid Höppner SAVE_UINT32_X(ksi, "lookup_rtxcur", mntinfo->mik_timers[0].rtxcur); 111066448911SDavid Höppner SAVE_UINT32_X(ksi, "read_srtt", mntinfo->mik_timers[1].srtt); 111166448911SDavid Höppner SAVE_UINT32_X(ksi, "read_deviate", mntinfo->mik_timers[1].deviate); 111266448911SDavid Höppner SAVE_UINT32_X(ksi, "read_rtxcur", mntinfo->mik_timers[1].rtxcur); 111366448911SDavid Höppner SAVE_UINT32_X(ksi, "write_srtt", mntinfo->mik_timers[2].srtt); 111466448911SDavid Höppner SAVE_UINT32_X(ksi, "write_deviate", mntinfo->mik_timers[2].deviate); 111566448911SDavid Höppner SAVE_UINT32_X(ksi, "write_rtxcur", mntinfo->mik_timers[2].rtxcur); 111666448911SDavid Höppner SAVE_UINT32(ksi, mntinfo, mik_noresponse); 111766448911SDavid Höppner SAVE_UINT32(ksi, mntinfo, mik_failover); 111866448911SDavid Höppner SAVE_UINT32(ksi, mntinfo, mik_remap); 111966448911SDavid Höppner SAVE_STRING(ksi, mntinfo, mik_curserver); 112066448911SDavid Höppner } 112166448911SDavid Höppner 112266448911SDavid Höppner #ifdef __sparc 112366448911SDavid Höppner static void 112466448911SDavid Höppner save_sfmmu_global_stat(kstat_t *kp, ks_instance_t *ksi) 112566448911SDavid Höppner { 112666448911SDavid Höppner struct sfmmu_global_stat *sfmmug = 112766448911SDavid Höppner (struct sfmmu_global_stat *)(kp->ks_data); 112866448911SDavid Höppner 112966448911SDavid Höppner assert(kp->ks_data_size == sizeof (struct sfmmu_global_stat)); 113066448911SDavid Höppner 113166448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tsb_exceptions); 113266448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tsb_raise_exception); 113366448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_pagefaults); 113466448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_uhash_searches); 113566448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_uhash_links); 113666448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_khash_searches); 113766448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_khash_links); 113866448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_swapout); 113966448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tsb_alloc); 114066448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tsb_allocfail); 114166448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tsb_sectsb_create); 114266448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_scd_1sttsb_alloc); 114366448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_scd_2ndtsb_alloc); 114466448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_scd_1sttsb_allocfail); 114566448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_scd_2ndtsb_allocfail); 114666448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tteload8k); 114766448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tteload64k); 114866448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tteload512k); 114966448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tteload4m); 115066448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tteload32m); 115166448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tteload256m); 115266448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tsb_load8k); 115366448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tsb_load4m); 115466448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_hblk_hit); 115566448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_hblk8_ncreate); 115666448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_hblk8_nalloc); 115766448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_hblk1_ncreate); 115866448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_hblk1_nalloc); 115966448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_hblk_slab_cnt); 116066448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_hblk_reserve_cnt); 116166448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_hblk_recurse_cnt); 116266448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_hblk_reserve_hit); 116366448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_get_free_success); 116466448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_get_free_throttle); 116566448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_get_free_fail); 116666448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_put_free_success); 116766448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_put_free_fail); 116866448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_pgcolor_conflict); 116966448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_uncache_conflict); 117066448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_unload_conflict); 117166448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_ism_uncache); 117266448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_ism_recache); 117366448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_recache); 117466448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_steal_count); 117566448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_pagesync); 117666448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_clrwrt); 117766448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_pagesync_invalid); 117866448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_kernel_xcalls); 117966448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_user_xcalls); 118066448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tsb_grow); 118166448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tsb_shrink); 118266448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tsb_resize_failures); 118366448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tsb_reloc); 118466448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_user_vtop); 118566448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_ctx_inv); 118666448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_tlb_reprog_pgsz); 118766448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_region_remap_demap); 118866448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_create_scd); 118966448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_join_scd); 119066448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_leave_scd); 119166448911SDavid Höppner SAVE_INT32(ksi, sfmmug, sf_destroy_scd); 119266448911SDavid Höppner } 119366448911SDavid Höppner #endif 119466448911SDavid Höppner 119566448911SDavid Höppner #ifdef __sparc 119666448911SDavid Höppner static void 119766448911SDavid Höppner save_sfmmu_tsbsize_stat(kstat_t *kp, ks_instance_t *ksi) 119866448911SDavid Höppner { 119966448911SDavid Höppner struct sfmmu_tsbsize_stat *sfmmut; 120066448911SDavid Höppner 120166448911SDavid Höppner assert(kp->ks_data_size == sizeof (struct sfmmu_tsbsize_stat)); 120266448911SDavid Höppner sfmmut = (struct sfmmu_tsbsize_stat *)(kp->ks_data); 120366448911SDavid Höppner 120466448911SDavid Höppner SAVE_INT32(ksi, sfmmut, sf_tsbsz_8k); 120566448911SDavid Höppner SAVE_INT32(ksi, sfmmut, sf_tsbsz_16k); 120666448911SDavid Höppner SAVE_INT32(ksi, sfmmut, sf_tsbsz_32k); 120766448911SDavid Höppner SAVE_INT32(ksi, sfmmut, sf_tsbsz_64k); 120866448911SDavid Höppner SAVE_INT32(ksi, sfmmut, sf_tsbsz_128k); 120966448911SDavid Höppner SAVE_INT32(ksi, sfmmut, sf_tsbsz_256k); 121066448911SDavid Höppner SAVE_INT32(ksi, sfmmut, sf_tsbsz_512k); 121166448911SDavid Höppner SAVE_INT32(ksi, sfmmut, sf_tsbsz_1m); 121266448911SDavid Höppner SAVE_INT32(ksi, sfmmut, sf_tsbsz_2m); 121366448911SDavid Höppner SAVE_INT32(ksi, sfmmut, sf_tsbsz_4m); 121466448911SDavid Höppner } 121566448911SDavid Höppner #endif 121666448911SDavid Höppner 121766448911SDavid Höppner #ifdef __sparc 121866448911SDavid Höppner static void 121966448911SDavid Höppner save_simmstat(kstat_t *kp, ks_instance_t *ksi) 122066448911SDavid Höppner { 122166448911SDavid Höppner uchar_t *simmstat; 122266448911SDavid Höppner char *simm_buf; 122366448911SDavid Höppner char *list = NULL; 122466448911SDavid Höppner int i; 122566448911SDavid Höppner 122666448911SDavid Höppner assert(kp->ks_data_size == sizeof (uchar_t) * SIMM_COUNT); 122766448911SDavid Höppner 122866448911SDavid Höppner for (i = 0, simmstat = (uchar_t *)(kp->ks_data); i < SIMM_COUNT - 1; 122966448911SDavid Höppner i++, simmstat++) { 123066448911SDavid Höppner if (list == NULL) { 123166448911SDavid Höppner (void) asprintf(&simm_buf, "%d,", *simmstat); 123266448911SDavid Höppner } else { 123366448911SDavid Höppner (void) asprintf(&simm_buf, "%s%d,", list, *simmstat); 123466448911SDavid Höppner free(list); 123566448911SDavid Höppner } 123666448911SDavid Höppner list = simm_buf; 123766448911SDavid Höppner } 123866448911SDavid Höppner 123966448911SDavid Höppner (void) asprintf(&simm_buf, "%s%d", list, *simmstat); 124066448911SDavid Höppner SAVE_STRING_X(ksi, "status", simm_buf); 124166448911SDavid Höppner free(list); 124266448911SDavid Höppner free(simm_buf); 124366448911SDavid Höppner } 124466448911SDavid Höppner #endif 124566448911SDavid Höppner 124666448911SDavid Höppner #ifdef __sparc 124766448911SDavid Höppner /* 124866448911SDavid Höppner * Helper function for save_temperature(). 124966448911SDavid Höppner */ 125066448911SDavid Höppner static char * 125166448911SDavid Höppner short_array_to_string(short *shortp, int len) 125266448911SDavid Höppner { 125366448911SDavid Höppner char *list = NULL; 125466448911SDavid Höppner char *list_buf; 125566448911SDavid Höppner 125666448911SDavid Höppner for (; len > 1; len--, shortp++) { 125766448911SDavid Höppner if (list == NULL) { 1258e633f2d7SRichard Lowe (void) asprintf(&list_buf, "%hd,", *shortp); 125966448911SDavid Höppner } else { 1260e633f2d7SRichard Lowe (void) asprintf(&list_buf, "%s%hd,", list, *shortp); 126166448911SDavid Höppner free(list); 126266448911SDavid Höppner } 126366448911SDavid Höppner list = list_buf; 126466448911SDavid Höppner } 126566448911SDavid Höppner 1266e633f2d7SRichard Lowe (void) asprintf(&list_buf, "%s%hd", list, *shortp); 126766448911SDavid Höppner free(list); 126866448911SDavid Höppner return (list_buf); 126966448911SDavid Höppner } 127066448911SDavid Höppner 127166448911SDavid Höppner static void 127266448911SDavid Höppner save_temperature(kstat_t *kp, ks_instance_t *ksi) 127366448911SDavid Höppner { 127466448911SDavid Höppner struct temp_stats *temps = (struct temp_stats *)(kp->ks_data); 127566448911SDavid Höppner char *buf; 127666448911SDavid Höppner 127766448911SDavid Höppner assert(kp->ks_data_size == sizeof (struct temp_stats)); 127866448911SDavid Höppner 127966448911SDavid Höppner SAVE_UINT32(ksi, temps, index); 128066448911SDavid Höppner 128166448911SDavid Höppner buf = short_array_to_string(temps->l1, L1_SZ); 128266448911SDavid Höppner SAVE_STRING_X(ksi, "l1", buf); 128366448911SDavid Höppner free(buf); 128466448911SDavid Höppner 128566448911SDavid Höppner buf = short_array_to_string(temps->l2, L2_SZ); 128666448911SDavid Höppner SAVE_STRING_X(ksi, "l2", buf); 128766448911SDavid Höppner free(buf); 128866448911SDavid Höppner 128966448911SDavid Höppner buf = short_array_to_string(temps->l3, L3_SZ); 129066448911SDavid Höppner SAVE_STRING_X(ksi, "l3", buf); 129166448911SDavid Höppner free(buf); 129266448911SDavid Höppner 129366448911SDavid Höppner buf = short_array_to_string(temps->l4, L4_SZ); 129466448911SDavid Höppner SAVE_STRING_X(ksi, "l4", buf); 129566448911SDavid Höppner free(buf); 129666448911SDavid Höppner 129766448911SDavid Höppner buf = short_array_to_string(temps->l5, L5_SZ); 129866448911SDavid Höppner SAVE_STRING_X(ksi, "l5", buf); 129966448911SDavid Höppner free(buf); 130066448911SDavid Höppner 130166448911SDavid Höppner SAVE_INT32(ksi, temps, max); 130266448911SDavid Höppner SAVE_INT32(ksi, temps, min); 130366448911SDavid Höppner SAVE_INT32(ksi, temps, state); 130466448911SDavid Höppner SAVE_INT32(ksi, temps, temp_cnt); 130566448911SDavid Höppner SAVE_INT32(ksi, temps, shutdown_cnt); 130666448911SDavid Höppner SAVE_INT32(ksi, temps, version); 130766448911SDavid Höppner SAVE_INT32(ksi, temps, trend); 130866448911SDavid Höppner SAVE_INT32(ksi, temps, override); 130966448911SDavid Höppner } 131066448911SDavid Höppner #endif 131166448911SDavid Höppner 131266448911SDavid Höppner #ifdef __sparc 131366448911SDavid Höppner static void 131466448911SDavid Höppner save_temp_over(kstat_t *kp, ks_instance_t *ksi) 131566448911SDavid Höppner { 131666448911SDavid Höppner short *sh = (short *)(kp->ks_data); 131766448911SDavid Höppner char *value; 131866448911SDavid Höppner 131966448911SDavid Höppner assert(kp->ks_data_size == sizeof (short)); 132066448911SDavid Höppner 132166448911SDavid Höppner (void) asprintf(&value, "%hu", *sh); 132266448911SDavid Höppner SAVE_STRING_X(ksi, "override", value); 132366448911SDavid Höppner free(value); 132466448911SDavid Höppner } 132566448911SDavid Höppner #endif 132666448911SDavid Höppner 132766448911SDavid Höppner #ifdef __sparc 132866448911SDavid Höppner static void 132966448911SDavid Höppner save_ps_shadow(kstat_t *kp, ks_instance_t *ksi) 133066448911SDavid Höppner { 133166448911SDavid Höppner uchar_t *uchar = (uchar_t *)(kp->ks_data); 133266448911SDavid Höppner 133366448911SDavid Höppner assert(kp->ks_data_size == SYS_PS_COUNT); 133466448911SDavid Höppner 133566448911SDavid Höppner SAVE_CHAR_X(ksi, "core_0", *uchar++); 133666448911SDavid Höppner SAVE_CHAR_X(ksi, "core_1", *uchar++); 133766448911SDavid Höppner SAVE_CHAR_X(ksi, "core_2", *uchar++); 133866448911SDavid Höppner SAVE_CHAR_X(ksi, "core_3", *uchar++); 133966448911SDavid Höppner SAVE_CHAR_X(ksi, "core_4", *uchar++); 134066448911SDavid Höppner SAVE_CHAR_X(ksi, "core_5", *uchar++); 134166448911SDavid Höppner SAVE_CHAR_X(ksi, "core_6", *uchar++); 134266448911SDavid Höppner SAVE_CHAR_X(ksi, "core_7", *uchar++); 134366448911SDavid Höppner SAVE_CHAR_X(ksi, "pps_0", *uchar++); 134466448911SDavid Höppner SAVE_CHAR_X(ksi, "clk_33", *uchar++); 134566448911SDavid Höppner SAVE_CHAR_X(ksi, "clk_50", *uchar++); 134666448911SDavid Höppner SAVE_CHAR_X(ksi, "v5_p", *uchar++); 134766448911SDavid Höppner SAVE_CHAR_X(ksi, "v12_p", *uchar++); 134866448911SDavid Höppner SAVE_CHAR_X(ksi, "v5_aux", *uchar++); 134966448911SDavid Höppner SAVE_CHAR_X(ksi, "v5_p_pch", *uchar++); 135066448911SDavid Höppner SAVE_CHAR_X(ksi, "v12_p_pch", *uchar++); 135166448911SDavid Höppner SAVE_CHAR_X(ksi, "v3_pch", *uchar++); 135266448911SDavid Höppner SAVE_CHAR_X(ksi, "v5_pch", *uchar++); 135366448911SDavid Höppner SAVE_CHAR_X(ksi, "p_fan", *uchar++); 135466448911SDavid Höppner } 135566448911SDavid Höppner #endif 135666448911SDavid Höppner 135766448911SDavid Höppner #ifdef __sparc 135866448911SDavid Höppner static void 135966448911SDavid Höppner save_fault_list(kstat_t *kp, ks_instance_t *ksi) 136066448911SDavid Höppner { 136166448911SDavid Höppner struct ft_list *fault; 136266448911SDavid Höppner char name[KSTAT_STRLEN + 7]; 136366448911SDavid Höppner int i; 136466448911SDavid Höppner 136566448911SDavid Höppner for (i = 1, fault = (struct ft_list *)(kp->ks_data); 136666448911SDavid Höppner i <= 999999 && i <= kp->ks_data_size / sizeof (struct ft_list); 136766448911SDavid Höppner i++, fault++) { 136866448911SDavid Höppner (void) snprintf(name, sizeof (name), "unit_%d", i); 136966448911SDavid Höppner SAVE_INT32_X(ksi, name, fault->unit); 137066448911SDavid Höppner (void) snprintf(name, sizeof (name), "type_%d", i); 137166448911SDavid Höppner SAVE_INT32_X(ksi, name, fault->type); 137266448911SDavid Höppner (void) snprintf(name, sizeof (name), "fclass_%d", i); 137366448911SDavid Höppner SAVE_INT32_X(ksi, name, fault->fclass); 137466448911SDavid Höppner (void) snprintf(name, sizeof (name), "create_time_%d", i); 137566448911SDavid Höppner SAVE_HRTIME_X(ksi, name, fault->create_time); 137666448911SDavid Höppner (void) snprintf(name, sizeof (name), "msg_%d", i); 1377e633f2d7SRichard Lowe SAVE_STRING_X(ksi, name, fault->msg); 137866448911SDavid Höppner } 137966448911SDavid Höppner } 138066448911SDavid Höppner #endif 138166448911SDavid Höppner 138266448911SDavid Höppner static void 138366448911SDavid Höppner save_named(kstat_t *kp, ks_instance_t *ksi) 138466448911SDavid Höppner { 138566448911SDavid Höppner kstat_named_t *knp; 138666448911SDavid Höppner int n; 138766448911SDavid Höppner 138866448911SDavid Höppner for (n = kp->ks_ndata, knp = KSTAT_NAMED_PTR(kp); n > 0; n--, knp++) { 138966448911SDavid Höppner switch (knp->data_type) { 139066448911SDavid Höppner case KSTAT_DATA_CHAR: 139166448911SDavid Höppner nvpair_insert(ksi, knp->name, 139266448911SDavid Höppner (ks_value_t *)&knp->value, KSTAT_DATA_CHAR); 139366448911SDavid Höppner break; 139466448911SDavid Höppner case KSTAT_DATA_INT32: 139566448911SDavid Höppner nvpair_insert(ksi, knp->name, 139666448911SDavid Höppner (ks_value_t *)&knp->value, KSTAT_DATA_INT32); 139766448911SDavid Höppner break; 139866448911SDavid Höppner case KSTAT_DATA_UINT32: 139966448911SDavid Höppner nvpair_insert(ksi, knp->name, 140066448911SDavid Höppner (ks_value_t *)&knp->value, KSTAT_DATA_UINT32); 140166448911SDavid Höppner break; 140266448911SDavid Höppner case KSTAT_DATA_INT64: 140366448911SDavid Höppner nvpair_insert(ksi, knp->name, 140466448911SDavid Höppner (ks_value_t *)&knp->value, KSTAT_DATA_INT64); 140566448911SDavid Höppner break; 140666448911SDavid Höppner case KSTAT_DATA_UINT64: 140766448911SDavid Höppner nvpair_insert(ksi, knp->name, 140866448911SDavid Höppner (ks_value_t *)&knp->value, KSTAT_DATA_UINT64); 140966448911SDavid Höppner break; 141066448911SDavid Höppner case KSTAT_DATA_STRING: 141166448911SDavid Höppner SAVE_STRING_X(ksi, knp->name, KSTAT_NAMED_STR_PTR(knp)); 141266448911SDavid Höppner break; 141366448911SDavid Höppner default: 141466448911SDavid Höppner assert(B_FALSE); /* Invalid data type */ 141566448911SDavid Höppner break; 141666448911SDavid Höppner } 141766448911SDavid Höppner } 141866448911SDavid Höppner } 141966448911SDavid Höppner 142066448911SDavid Höppner static void 142166448911SDavid Höppner save_intr(kstat_t *kp, ks_instance_t *ksi) 142266448911SDavid Höppner { 142366448911SDavid Höppner kstat_intr_t *intr = KSTAT_INTR_PTR(kp); 142466448911SDavid Höppner char *intr_names[] = {"hard", "soft", "watchdog", "spurious", 142566448911SDavid Höppner "multiple_service"}; 142666448911SDavid Höppner int n; 142766448911SDavid Höppner 142866448911SDavid Höppner for (n = 0; n < KSTAT_NUM_INTRS; n++) 142966448911SDavid Höppner SAVE_UINT32_X(ksi, intr_names[n], intr->intrs[n]); 143066448911SDavid Höppner } 143166448911SDavid Höppner 143266448911SDavid Höppner static void 143366448911SDavid Höppner save_io(kstat_t *kp, ks_instance_t *ksi) 143466448911SDavid Höppner { 143566448911SDavid Höppner kstat_io_t *ksio = KSTAT_IO_PTR(kp); 143666448911SDavid Höppner 143766448911SDavid Höppner SAVE_UINT64(ksi, ksio, nread); 143866448911SDavid Höppner SAVE_UINT64(ksi, ksio, nwritten); 143966448911SDavid Höppner SAVE_UINT32(ksi, ksio, reads); 144066448911SDavid Höppner SAVE_UINT32(ksi, ksio, writes); 144166448911SDavid Höppner SAVE_HRTIME(ksi, ksio, wtime); 144266448911SDavid Höppner SAVE_HRTIME(ksi, ksio, wlentime); 144366448911SDavid Höppner SAVE_HRTIME(ksi, ksio, wlastupdate); 144466448911SDavid Höppner SAVE_HRTIME(ksi, ksio, rtime); 144566448911SDavid Höppner SAVE_HRTIME(ksi, ksio, rlentime); 144666448911SDavid Höppner SAVE_HRTIME(ksi, ksio, rlastupdate); 144766448911SDavid Höppner SAVE_UINT32(ksi, ksio, wcnt); 144866448911SDavid Höppner SAVE_UINT32(ksi, ksio, rcnt); 144966448911SDavid Höppner } 145066448911SDavid Höppner 145166448911SDavid Höppner static void 145266448911SDavid Höppner save_timer(kstat_t *kp, ks_instance_t *ksi) 145366448911SDavid Höppner { 145466448911SDavid Höppner kstat_timer_t *ktimer = KSTAT_TIMER_PTR(kp); 145566448911SDavid Höppner 145666448911SDavid Höppner SAVE_STRING(ksi, ktimer, name); 145766448911SDavid Höppner SAVE_UINT64(ksi, ktimer, num_events); 145866448911SDavid Höppner SAVE_HRTIME(ksi, ktimer, elapsed_time); 145966448911SDavid Höppner SAVE_HRTIME(ksi, ktimer, min_time); 146066448911SDavid Höppner SAVE_HRTIME(ksi, ktimer, max_time); 146166448911SDavid Höppner SAVE_HRTIME(ksi, ktimer, start_time); 146266448911SDavid Höppner SAVE_HRTIME(ksi, ktimer, stop_time); 146366448911SDavid Höppner } 1464