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