Print this page
check return from clock_gettime.
fix cstyle
codereview and testing fixes.
6558 kstat: desire type for timestamps


   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2013 David Hoeppner. All rights reserved.
  25  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  26  * Copyright (c) 2013, Joyent, Inc. All rights reserved.

  27  */
  28 
  29 /*
  30  * Display kernel statistics
  31  *
  32  * This is a reimplementation of the perl kstat command originally found
  33  * under usr/src/cmd/kstat/kstat.pl
  34  *
  35  * Incompatibilities:
  36  *      - perl regular expressions replaced with extended REs bracketed by '/'
  37  *
  38  * Flags added:
  39  *      -C      similar to the -p option but value is separated by a colon
  40  *      -h      display help
  41  *      -j      json format






  42  */
  43 
  44 #include <assert.h>
  45 #include <ctype.h>
  46 #include <errno.h>
  47 #include <kstat.h>
  48 #include <langinfo.h>
  49 #include <libgen.h>
  50 #include <limits.h>
  51 #include <locale.h>
  52 #include <signal.h>
  53 #include <stddef.h>
  54 #include <stdio.h>
  55 #include <stdlib.h>
  56 #include <string.h>
  57 #include <strings.h>
  58 #include <time.h>
  59 #include <unistd.h>
  60 #include <sys/list.h>
  61 #include <sys/time.h>
  62 #include <sys/types.h>
  63 
  64 #include "kstat.h"
  65 #include "statcommon.h"
  66 
  67 char    *cmdname = "kstat";     /* Name of this command */
  68 int     caught_cont = 0;        /* Have caught a SIGCONT */
  69 
  70 static uint_t   g_timestamp_fmt = NODATE;

  71 
  72 /* Helper flag - header was printed already? */
  73 static boolean_t g_headerflg;
  74 
  75 /* Saved command line options */
  76 static boolean_t g_cflg = B_FALSE;
  77 static boolean_t g_jflg = B_FALSE;
  78 static boolean_t g_lflg = B_FALSE;
  79 static boolean_t g_pflg = B_FALSE;
  80 static boolean_t g_qflg = B_FALSE;
  81 static ks_pattern_t     g_ks_class = {"*", 0};
  82 
  83 /* Return zero if a selector did match */
  84 static int      g_matched = 1;
  85 
  86 /* Sorted list of kstat instances */
  87 static list_t   instances_list;
  88 static list_t   selector_list;
  89 


  90 int
  91 main(int argc, char **argv)
  92 {
  93         ks_selector_t   *nselector;
  94         ks_selector_t   *uselector;
  95         kstat_ctl_t     *kc;
  96         hrtime_t        start_n;
  97         hrtime_t        period_n;
  98         boolean_t       errflg = B_FALSE;
  99         boolean_t       nselflg = B_FALSE;
 100         boolean_t       uselflg = B_FALSE;
 101         char            *q;
 102         int             count = 1;
 103         int             infinite_cycles = 0;
 104         int             interval = 0;
 105         int             n = 0;
 106         int             c, m, tmp;
 107 
 108         (void) setlocale(LC_ALL, "");
 109 #if !defined(TEXT_DOMAIN)               /* Should be defined by cc -D */
 110 #define TEXT_DOMAIN "SYS_TEST"          /* Use this only if it wasn't */
 111 #endif
 112         (void) textdomain(TEXT_DOMAIN);
 113 
 114         /*
 115          * Create the selector list and a dummy default selector to match
 116          * everything. While we process the cmdline options we will add
 117          * selectors to this list.
 118          */
 119         list_create(&selector_list, sizeof (ks_selector_t),
 120             offsetof(ks_selector_t, ks_next));
 121 
 122         nselector = new_selector();
 123 
 124         /*
 125          * Parse named command line arguments.
 126          */
 127         while ((c = getopt(argc, argv, "h?CqjlpT:m:i:n:s:c:")) != EOF)
 128                 switch (c) {
 129                 case 'h':
 130                 case '?':
 131                         usage();
 132                         exit(0);
 133                         break;
 134                 case 'C':
 135                         g_pflg = g_cflg = B_TRUE;
 136                         break;
 137                 case 'q':
 138                         g_qflg = B_TRUE;
 139                         break;
 140                 case 'j':
 141                         g_jflg = B_TRUE;
 142                         break;
 143                 case 'l':
 144                         g_pflg = g_lflg = B_TRUE;
 145                         break;
 146                 case 'p':
 147                         g_pflg = B_TRUE;
 148                         break;
 149                 case 'T':



 150                         switch (*optarg) {
 151                         case 'd':
 152                                 g_timestamp_fmt = DDATE;
 153                                 break;
 154                         case 'u':
 155                                 g_timestamp_fmt = UDATE;
 156                                 break;
 157                         default:
 158                                 errflg = B_TRUE;
 159                         }
 160                         break;
 161                 case 'm':
 162                         nselflg = B_TRUE;
 163                         nselector->ks_module.pstr =
 164                             (char *)ks_safe_strdup(optarg);
 165                         break;
 166                 case 'i':
 167                         nselflg = B_TRUE;
 168                         nselector->ks_instance.pstr =
 169                             (char *)ks_safe_strdup(optarg);
 170                         break;
 171                 case 'n':
 172                         nselflg = B_TRUE;
 173                         nselector->ks_name.pstr =
 174                             (char *)ks_safe_strdup(optarg);
 175                         break;
 176                 case 's':
 177                         nselflg = B_TRUE;
 178                         nselector->ks_statistic.pstr =
 179                             (char *)ks_safe_strdup(optarg);
 180                         break;
 181                 case 'c':
 182                         g_ks_class.pstr =
 183                             (char *)ks_safe_strdup(optarg);
 184                         break;














 185                 default:
 186                         errflg = B_TRUE;
 187                         break;
 188                 }





 189 
 190         if (g_qflg && (g_jflg || g_pflg)) {
 191                 (void) fprintf(stderr, gettext(
 192                     "-q and -lpj are mutually exclusive\n"));
 193                 errflg = B_TRUE;
 194         }
 195 

















 196         if (errflg) {
 197                 usage();
 198                 exit(2);
 199         }
 200 
 201         argc -= optind;
 202         argv += optind;
 203 
 204         /*
 205          * Consume the rest of the command line. Parsing the
 206          * unnamed command line arguments.
 207          */
 208         while (argc--) {
 209                 errno = 0;
 210                 tmp = strtoul(*argv, &q, 10);
 211                 if (tmp == ULONG_MAX && errno == ERANGE) {
 212                         if (n == 0) {
 213                                 (void) fprintf(stderr, gettext(
 214                                     "Interval is too large\n"));
 215                         } else if (n == 1) {


 335                         ks_sleep_until(&start_n, period_n, infinite_cycles,
 336                             &caught_cont);
 337                         (void) kstat_chain_update(kc);
 338                         (void) putchar('\n');
 339                 }
 340         }
 341 
 342         (void) kstat_close(kc);
 343 
 344         return (g_matched);
 345 }
 346 
 347 /*
 348  * Print usage.
 349  */
 350 static void
 351 usage(void)
 352 {
 353         (void) fprintf(stderr, gettext(
 354             "Usage:\n"
 355             "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ]\n"
 356             "      [ -m module ] [ -i instance ] [ -n name ] [ -s statistic ]\n"
 357             "      [ interval [ count ] ]\n"
 358             "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ]\n"
 359             "      [ module[:instance[:name[:statistic]]] ... ]\n"
 360             "      [ interval [ count ] ]\n"));
 361 }
 362 
 363 /*
 364  * Sort compare function.
 365  */
 366 static int
 367 compare_instances(ks_instance_t *l_arg, ks_instance_t *r_arg)
 368 {
 369         int     rval;
 370 
 371         rval = strcasecmp(l_arg->ks_module, r_arg->ks_module);
 372         if (rval == 0) {
 373                 if (l_arg->ks_instance == r_arg->ks_instance) {
 374                         return (strcasecmp(l_arg->ks_name, r_arg->ks_name));
 375                 } else if (l_arg->ks_instance < r_arg->ks_instance) {
 376                         return (-1);
 377                 } else {
 378                         return (1);


 691                         break;
 692                 case KSTAT_TYPE_IO:
 693                         save_io(kp, ksi);
 694                         break;
 695                 case KSTAT_TYPE_TIMER:
 696                         save_timer(kp, ksi);
 697                         break;
 698                 default:
 699                         assert(B_FALSE); /* Invalid type */
 700                         break;
 701                 }
 702         }
 703 }
 704 
 705 /*
 706  * Print the value of a name-value pair.
 707  */
 708 static void
 709 ks_value_print(ks_nvpair_t *nvpair)
 710 {




 711         switch (nvpair->data_type) {
 712         case KSTAT_DATA_CHAR:
 713                 (void) fprintf(stdout, "%s", nvpair->value.c);
 714                 break;
 715         case KSTAT_DATA_INT32:
 716                 (void) fprintf(stdout, "%d", nvpair->value.i32);
 717                 break;
 718         case KSTAT_DATA_UINT32:
 719                 (void) fprintf(stdout, "%u", nvpair->value.ui32);
 720                 break;
 721         case KSTAT_DATA_INT64:
 722                 (void) fprintf(stdout, "%lld", nvpair->value.i64);
 723                 break;
 724         case KSTAT_DATA_UINT64:
 725                 (void) fprintf(stdout, "%llu", nvpair->value.ui64);
 726                 break;
 727         case KSTAT_DATA_STRING:
 728                 (void) fprintf(stdout, "%s", KSTAT_NAMED_STR_PTR(nvpair));
 729                 break;
 730         case KSTAT_DATA_HRTIME:





































 731                 if (nvpair->value.ui64 == 0)
 732                         (void) fprintf(stdout, "0");
 733                 else
 734                         (void) fprintf(stdout, "%.9f",
 735                             nvpair->value.ui64 / 1000000000.0);
 736                 break;
 737         default:




 738                 assert(B_FALSE);
 739         }
 740 }
 741 
 742 /*
 743  * Print a single instance.
 744  */
 745 static void
 746 ks_instance_print(ks_instance_t *ksi, ks_nvpair_t *nvpair)
 747 {
 748         if (g_headerflg) {
 749                 if (!g_pflg) {
 750                         (void) fprintf(stdout, DFLT_FMT,
 751                             ksi->ks_module, ksi->ks_instance,
 752                             ksi->ks_name, ksi->ks_class);
 753                 }
 754                 g_headerflg = B_FALSE;
 755         }
 756 
 757         if (g_pflg) {


 781                     ksi->ks_module, ksi->ks_instance,
 782                     ksi->ks_name, ksi->ks_class,
 783                     ksi->ks_type);
 784 
 785                 if (ksi->ks_snaptime == 0)
 786                         (void) fprintf(stdout, "\t\"snaptime\": 0,\n");
 787                 else
 788                         (void) fprintf(stdout, "\t\"snaptime\": %.9f,\n",
 789                             ksi->ks_snaptime / 1000000000.0);
 790 
 791                 (void) fprintf(stdout, "\t\"data\": {\n");
 792 
 793                 g_headerflg = B_FALSE;
 794         }
 795 
 796         (void) fprintf(stdout, KS_JFMT, nvpair->name);
 797         if (nvpair->data_type == KSTAT_DATA_STRING) {
 798                 (void) putchar('\"');
 799                 ks_value_print(nvpair);
 800                 (void) putchar('\"');












 801         } else {
 802                 ks_value_print(nvpair);
 803         }
 804         if (nvpair != list_tail(&ksi->ks_nvlist))
 805                 (void) putchar(',');
 806 
 807         (void) putchar('\n');
 808 }
 809 
 810 /*
 811  * Print all instances.
 812  */
 813 static void
 814 ks_instances_print(void)
 815 {
 816         ks_selector_t   *selector;
 817         ks_instance_t   *ksi, *ktmp;
 818         ks_nvpair_t     *nvpair, *ntmp;
 819         void            (*ks_print_fn)(ks_instance_t *, ks_nvpair_t *);
 820         char            *ks_number;


1371                 SAVE_INT32_X(ksi, name, fault->type);
1372                 (void) snprintf(name, sizeof (name), "fclass_%d", i);
1373                 SAVE_INT32_X(ksi, name, fault->fclass);
1374                 (void) snprintf(name, sizeof (name), "create_time_%d", i);
1375                 SAVE_HRTIME_X(ksi, name, fault->create_time);
1376                 (void) snprintf(name, sizeof (name), "msg_%d", i);
1377                 SAVE_STRING_X(ksi, name, fault->msg);
1378         }
1379 }
1380 #endif
1381 
1382 static void
1383 save_named(kstat_t *kp, ks_instance_t *ksi)
1384 {
1385         kstat_named_t *knp;
1386         int     n;
1387 
1388         for (n = kp->ks_ndata, knp = KSTAT_NAMED_PTR(kp); n > 0; n--, knp++) {
1389                 switch (knp->data_type) {
1390                 case KSTAT_DATA_CHAR:
1391                         nvpair_insert(ksi, knp->name,
1392                             (ks_value_t *)&knp->value, KSTAT_DATA_CHAR);
1393                         break;
1394                 case KSTAT_DATA_INT32:
1395                         nvpair_insert(ksi, knp->name,
1396                             (ks_value_t *)&knp->value, KSTAT_DATA_INT32);
1397                         break;
1398                 case KSTAT_DATA_UINT32:
1399                         nvpair_insert(ksi, knp->name,
1400                             (ks_value_t *)&knp->value, KSTAT_DATA_UINT32);
1401                         break;
1402                 case KSTAT_DATA_INT64:
1403                         nvpair_insert(ksi, knp->name,
1404                             (ks_value_t *)&knp->value, KSTAT_DATA_INT64);
1405                         break;
1406                 case KSTAT_DATA_UINT64:

1407                         nvpair_insert(ksi, knp->name,
1408                             (ks_value_t *)&knp->value, KSTAT_DATA_UINT64);
1409                         break;
1410                 case KSTAT_DATA_STRING:
1411                         SAVE_STRING_X(ksi, knp->name, KSTAT_NAMED_STR_PTR(knp));
1412                         break;
1413                 default:
1414                         assert(B_FALSE); /* Invalid data type */
1415                         break;
1416                 }
1417         }
1418 }
1419 
1420 static void
1421 save_intr(kstat_t *kp, ks_instance_t *ksi)
1422 {
1423         kstat_intr_t *intr = KSTAT_INTR_PTR(kp);
1424         char    *intr_names[] = {"hard", "soft", "watchdog", "spurious",
1425             "multiple_service"};
1426         int     n;
1427 
1428         for (n = 0; n < KSTAT_NUM_INTRS; n++)
1429                 SAVE_UINT32_X(ksi, intr_names[n], intr->intrs[n]);
1430 }
1431 
1432 static void
1433 save_io(kstat_t *kp, ks_instance_t *ksi)
1434 {
1435         kstat_io_t      *ksio = KSTAT_IO_PTR(kp);
1436 
1437         SAVE_UINT64(ksi, ksio, nread);
1438         SAVE_UINT64(ksi, ksio, nwritten);
1439         SAVE_UINT32(ksi, ksio, reads);
1440         SAVE_UINT32(ksi, ksio, writes);
1441         SAVE_HRTIME(ksi, ksio, wtime);
1442         SAVE_HRTIME(ksi, ksio, wlentime);
1443         SAVE_HRTIME(ksi, ksio, wlastupdate);
1444         SAVE_HRTIME(ksi, ksio, rtime);
1445         SAVE_HRTIME(ksi, ksio, rlentime);
1446         SAVE_HRTIME(ksi, ksio, rlastupdate);
1447         SAVE_UINT32(ksi, ksio, wcnt);
1448         SAVE_UINT32(ksi, ksio, rcnt);
1449 }
1450 
1451 static void
1452 save_timer(kstat_t *kp, ks_instance_t *ksi)
1453 {
1454         kstat_timer_t   *ktimer = KSTAT_TIMER_PTR(kp);
1455 
1456         SAVE_STRING(ksi, ktimer, name);
1457         SAVE_UINT64(ksi, ktimer, num_events);
1458         SAVE_HRTIME(ksi, ktimer, elapsed_time);
1459         SAVE_HRTIME(ksi, ktimer, min_time);
1460         SAVE_HRTIME(ksi, ktimer, max_time);
1461         SAVE_HRTIME(ksi, ktimer, start_time);
1462         SAVE_HRTIME(ksi, ktimer, stop_time);
1463 }


   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2013 David Hoeppner. All rights reserved.
  25  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  26  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  27  * Copyright 2016 Garrett D'Amore
  28  */
  29 
  30 /*
  31  * Display kernel statistics
  32  *
  33  * This is a reimplementation of the perl kstat command originally found
  34  * under usr/src/cmd/kstat/kstat.pl
  35  *
  36  * Incompatibilities:
  37  *      - perl regular expressions replaced with extended REs bracketed by '/'
  38  *
  39  * Flags added:
  40  *      -C      similar to the -p option but value is separated by a colon
  41  *      -h      display help
  42  *      -j      json format
  43  *      -H b    display hrtime as seconds since boot
  44  *      -H d    display hrtime as date
  45  *      -H u    display hrtime as UNIX seconds (since epoch)
  46  *      -H I    display hrtime as ISO-8601 local time
  47  *      -H Z    display hrtime as ISO-8601 UTC
  48  *      -H n    display hrtime as nanoseconds (since epoch)
  49  */
  50 
  51 #include <assert.h>
  52 #include <ctype.h>
  53 #include <errno.h>
  54 #include <kstat.h>
  55 #include <langinfo.h>
  56 #include <libgen.h>
  57 #include <limits.h>
  58 #include <locale.h>
  59 #include <signal.h>
  60 #include <stddef.h>
  61 #include <stdio.h>
  62 #include <stdlib.h>
  63 #include <string.h>
  64 #include <strings.h>
  65 #include <time.h>
  66 #include <unistd.h>
  67 #include <sys/list.h>
  68 #include <sys/time.h>
  69 #include <sys/types.h>
  70 
  71 #include "kstat.h"
  72 #include "statcommon.h"
  73 
  74 char    *cmdname = "kstat";     /* Name of this command */
  75 int     caught_cont = 0;        /* Have caught a SIGCONT */
  76 
  77 static uint_t   g_timestamp_fmt = NODATE;
  78 static uint_t   g_hrtime_fmt = KS_HRFMT_DEFAULT;
  79 
  80 /* Helper flag - header was printed already? */
  81 static boolean_t g_headerflg;
  82 
  83 /* Saved command line options */
  84 static boolean_t g_cflg = B_FALSE;
  85 static boolean_t g_jflg = B_FALSE;
  86 static boolean_t g_lflg = B_FALSE;
  87 static boolean_t g_pflg = B_FALSE;
  88 static boolean_t g_qflg = B_FALSE;
  89 static ks_pattern_t     g_ks_class = {"*", 0};
  90 
  91 /* Return zero if a selector did match */
  92 static int      g_matched = 1;
  93 
  94 /* Sorted list of kstat instances */
  95 static list_t   instances_list;
  96 static list_t   selector_list;
  97 
  98 static hrtime_t hrtime_origin;
  99 
 100 int
 101 main(int argc, char **argv)
 102 {
 103         ks_selector_t   *nselector;
 104         ks_selector_t   *uselector;
 105         kstat_ctl_t     *kc;
 106         hrtime_t        start_n;
 107         hrtime_t        period_n;
 108         boolean_t       errflg = B_FALSE;
 109         boolean_t       nselflg = B_FALSE;
 110         boolean_t       uselflg = B_FALSE;
 111         char            *q;
 112         int             count = 1;
 113         int             infinite_cycles = 0;
 114         int             interval = 0;
 115         int             n = 0;
 116         int             c, m, tmp;
 117 
 118         (void) setlocale(LC_ALL, "");
 119 #if !defined(TEXT_DOMAIN)               /* Should be defined by cc -D */
 120 #define TEXT_DOMAIN "SYS_TEST"          /* Use this only if it wasn't */
 121 #endif
 122         (void) textdomain(TEXT_DOMAIN);
 123 
 124         /*
 125          * Create the selector list and a dummy default selector to match
 126          * everything. While we process the cmdline options we will add
 127          * selectors to this list.
 128          */
 129         list_create(&selector_list, sizeof (ks_selector_t),
 130             offsetof(ks_selector_t, ks_next));
 131 
 132         nselector = new_selector();
 133 
 134         /*
 135          * Parse named command line arguments.
 136          */
 137         while ((c = getopt(argc, argv, "h?CqjlpT:m:i:n:s:c:H:")) != EOF)
 138                 switch (c) {
 139                 case 'h':
 140                 case '?':
 141                         usage();
 142                         exit(0);
 143                         break;
 144                 case 'C':
 145                         g_pflg = g_cflg = B_TRUE;
 146                         break;
 147                 case 'q':
 148                         g_qflg = B_TRUE;
 149                         break;
 150                 case 'j':
 151                         g_jflg = B_TRUE;
 152                         break;
 153                 case 'l':
 154                         g_pflg = g_lflg = B_TRUE;
 155                         break;
 156                 case 'p':
 157                         g_pflg = B_TRUE;
 158                         break;
 159                 case 'T':
 160                         if (strlen(optarg) != 1) {
 161                                 errflg = B_TRUE;
 162                         }
 163                         switch (*optarg) {
 164                         case 'd':
 165                                 g_timestamp_fmt = DDATE;
 166                                 break;
 167                         case 'u':
 168                                 g_timestamp_fmt = UDATE;
 169                                 break;
 170                         default:
 171                                 errflg = B_TRUE;
 172                         }
 173                         break;
 174                 case 'm':
 175                         nselflg = B_TRUE;
 176                         nselector->ks_module.pstr =
 177                             (char *)ks_safe_strdup(optarg);
 178                         break;
 179                 case 'i':
 180                         nselflg = B_TRUE;
 181                         nselector->ks_instance.pstr =
 182                             (char *)ks_safe_strdup(optarg);
 183                         break;
 184                 case 'n':
 185                         nselflg = B_TRUE;
 186                         nselector->ks_name.pstr =
 187                             (char *)ks_safe_strdup(optarg);
 188                         break;
 189                 case 's':
 190                         nselflg = B_TRUE;
 191                         nselector->ks_statistic.pstr =
 192                             (char *)ks_safe_strdup(optarg);
 193                         break;
 194                 case 'c':
 195                         g_ks_class.pstr =
 196                             (char *)ks_safe_strdup(optarg);
 197                         break;
 198                 case 'H':
 199                         switch (*optarg) {
 200                         case 'o':
 201                         case 'b':
 202                         case 'n':
 203                         case 'I':
 204                         case 'Z':
 205                         case 'd':
 206                         case 'u':
 207                                 if (strlen(optarg) != 1) {
 208                                         errflg = B_TRUE;
 209                                 }
 210                                 g_hrtime_fmt = *optarg;
 211                                 break;
 212                         default:
 213                                 errflg = B_TRUE;
 214                                 break;
 215                         }
 216                         break;
 217                 default:
 218                         errflg = B_TRUE;
 219                         break;
 220                 }
 221 
 222         if (g_qflg && (g_jflg || g_pflg)) {
 223                 (void) fprintf(stderr, gettext(
 224                     "-q and -lpj are mutually exclusive\n"));
 225                 errflg = B_TRUE;
 226         }
 227 
 228         switch (g_hrtime_fmt) {
 229         case KS_HRFMT_DEFAULT:
 230         case KS_HRFMT_BOOT:
 231                 break;
 232         default: {
 233                 struct timespec ts;
 234                 if (clock_gettime(CLOCK_REALTIME, &ts) != 0) {
 235                         perror("clock_gettime(CLOCK_REALTIME)");
 236                         exit(3);
 237                 }
 238                 hrtime_origin = ts.tv_sec;
 239                 hrtime_origin *= 1000000000;
 240                 hrtime_origin += ts.tv_nsec;
 241                 hrtime_origin -= gethrtime();
 242         }
 243         }
 244 
 245         if (errflg) {
 246                 usage();
 247                 exit(2);
 248         }
 249 
 250         argc -= optind;
 251         argv += optind;
 252 
 253         /*
 254          * Consume the rest of the command line. Parsing the
 255          * unnamed command line arguments.
 256          */
 257         while (argc--) {
 258                 errno = 0;
 259                 tmp = strtoul(*argv, &q, 10);
 260                 if (tmp == ULONG_MAX && errno == ERANGE) {
 261                         if (n == 0) {
 262                                 (void) fprintf(stderr, gettext(
 263                                     "Interval is too large\n"));
 264                         } else if (n == 1) {


 384                         ks_sleep_until(&start_n, period_n, infinite_cycles,
 385                             &caught_cont);
 386                         (void) kstat_chain_update(kc);
 387                         (void) putchar('\n');
 388                 }
 389         }
 390 
 391         (void) kstat_close(kc);
 392 
 393         return (g_matched);
 394 }
 395 
 396 /*
 397  * Print usage.
 398  */
 399 static void
 400 usage(void)
 401 {
 402         (void) fprintf(stderr, gettext(
 403             "Usage:\n"
 404             "kstat [ -Cjlpq ] [ -T d|u ] [ -H d|n|u|I|Z ] [ -c class ]\n"
 405             "      [ -m module ] [ -i instance ] [ -n name ] [ -s statistic ]\n"
 406             "      [ interval [ count ] ]\n"
 407             "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ] [ -H d|n|u|I|Z ]\n"
 408             "      [ module[:instance[:name[:statistic]]] ... ]\n"
 409             "      [ interval [ count ] ]\n"));
 410 }
 411 
 412 /*
 413  * Sort compare function.
 414  */
 415 static int
 416 compare_instances(ks_instance_t *l_arg, ks_instance_t *r_arg)
 417 {
 418         int     rval;
 419 
 420         rval = strcasecmp(l_arg->ks_module, r_arg->ks_module);
 421         if (rval == 0) {
 422                 if (l_arg->ks_instance == r_arg->ks_instance) {
 423                         return (strcasecmp(l_arg->ks_name, r_arg->ks_name));
 424                 } else if (l_arg->ks_instance < r_arg->ks_instance) {
 425                         return (-1);
 426                 } else {
 427                         return (1);


 740                         break;
 741                 case KSTAT_TYPE_IO:
 742                         save_io(kp, ksi);
 743                         break;
 744                 case KSTAT_TYPE_TIMER:
 745                         save_timer(kp, ksi);
 746                         break;
 747                 default:
 748                         assert(B_FALSE); /* Invalid type */
 749                         break;
 750                 }
 751         }
 752 }
 753 
 754 /*
 755  * Print the value of a name-value pair.
 756  */
 757 static void
 758 ks_value_print(ks_nvpair_t *nvpair)
 759 {
 760         char dstr[64];
 761         char zstr[8];
 762         time_t t;
 763 
 764         switch (nvpair->data_type) {
 765         case KSTAT_DATA_CHAR:
 766                 (void) fprintf(stdout, "%s", nvpair->value.c);
 767                 break;
 768         case KSTAT_DATA_INT32:
 769                 (void) fprintf(stdout, "%d", nvpair->value.i32);
 770                 break;
 771         case KSTAT_DATA_UINT32:
 772                 (void) fprintf(stdout, "%u", nvpair->value.ui32);
 773                 break;
 774         case KSTAT_DATA_INT64:
 775                 (void) fprintf(stdout, "%lld", nvpair->value.i64);
 776                 break;
 777         case KSTAT_DATA_UINT64:
 778                 (void) fprintf(stdout, "%llu", nvpair->value.ui64);
 779                 break;
 780         case KSTAT_DATA_STRING:
 781                 (void) fprintf(stdout, "%s", KSTAT_NAMED_STR_PTR(nvpair));
 782                 break;
 783         case KSTAT_DATA_TIME:
 784                 switch (g_hrtime_fmt) {
 785                 case KS_HRFMT_UNIX:
 786                         (void) fprintf(stdout, "%.9f",
 787                             (nvpair->value.t + hrtime_origin) / 1000000000.0);
 788                         break;
 789                 case KS_HRFMT_NANO:
 790                         (void) fprintf(stdout, "%llu",
 791                             (nvpair->value.t + hrtime_origin));
 792                         break;
 793                 case KS_HRFMT_DATE:
 794                         t = (time_t)
 795                             ((nvpair->value.t + hrtime_origin) / 1000000000);
 796                         (void) strftime(dstr,
 797                             sizeof (dstr), "%+", localtime(&t));
 798                         (void) fprintf(stdout, "%s", dstr);
 799                         break;
 800                 case KS_HRFMT_ZISO:
 801                         t = (time_t)
 802                             ((nvpair->value.t + hrtime_origin) / 1000000000);
 803                         (void) strftime(dstr, sizeof (dstr), "%FT%T",
 804                             gmtime(&t));
 805                         (void) fprintf(stdout, "%s.%06uZ", dstr,
 806                             (unsigned)(nvpair->value.t % 1000000000)/1000);
 807                         break;
 808                 case KS_HRFMT_ISO:
 809                         t = (time_t)
 810                             ((nvpair->value.t + hrtime_origin) / 1000000000);
 811                         (void) strftime(dstr, sizeof (dstr), "%FT%T",
 812                             localtime(&t));
 813                         (void) strftime(zstr, sizeof (zstr), "%z",
 814                             localtime(&t));
 815                         (void) fprintf(stdout, "%s.%06u%s", dstr,
 816                             (unsigned)(nvpair->value.t % 1000000000)/1000,
 817                             zstr);
 818                         break;
 819                 case KS_HRFMT_DEFAULT:
 820                 case KS_HRFMT_BOOT:
 821                         if (nvpair->value.ui64 == 0)
 822                                 (void) fprintf(stdout, "0");
 823                         else
 824                                 (void) fprintf(stdout, "%.9f",
 825                                     nvpair->value.ui64 / 1000000000.0);
 826                         break;
 827                 default:
 828                         abort();
 829                 }
 830                 break;
 831         default:
 832                 assert(B_FALSE);
 833         }
 834 }
 835 
 836 /*
 837  * Print a single instance.
 838  */
 839 static void
 840 ks_instance_print(ks_instance_t *ksi, ks_nvpair_t *nvpair)
 841 {
 842         if (g_headerflg) {
 843                 if (!g_pflg) {
 844                         (void) fprintf(stdout, DFLT_FMT,
 845                             ksi->ks_module, ksi->ks_instance,
 846                             ksi->ks_name, ksi->ks_class);
 847                 }
 848                 g_headerflg = B_FALSE;
 849         }
 850 
 851         if (g_pflg) {


 875                     ksi->ks_module, ksi->ks_instance,
 876                     ksi->ks_name, ksi->ks_class,
 877                     ksi->ks_type);
 878 
 879                 if (ksi->ks_snaptime == 0)
 880                         (void) fprintf(stdout, "\t\"snaptime\": 0,\n");
 881                 else
 882                         (void) fprintf(stdout, "\t\"snaptime\": %.9f,\n",
 883                             ksi->ks_snaptime / 1000000000.0);
 884 
 885                 (void) fprintf(stdout, "\t\"data\": {\n");
 886 
 887                 g_headerflg = B_FALSE;
 888         }
 889 
 890         (void) fprintf(stdout, KS_JFMT, nvpair->name);
 891         if (nvpair->data_type == KSTAT_DATA_STRING) {
 892                 (void) putchar('\"');
 893                 ks_value_print(nvpair);
 894                 (void) putchar('\"');
 895         } else if (nvpair->data_type == KSTAT_DATA_TIME) {
 896                 switch (g_hrtime_fmt) {
 897                 case KS_HRFMT_ISO:
 898                 case KS_HRFMT_ZISO:
 899                 case KS_HRFMT_DATE:
 900                         (void) putchar('\"');
 901                         ks_value_print(nvpair);
 902                         (void) putchar('\"');
 903                         break;
 904                 default:
 905                         ks_value_print(nvpair);
 906                 }
 907         } else {
 908                 ks_value_print(nvpair);
 909         }
 910         if (nvpair != list_tail(&ksi->ks_nvlist))
 911                 (void) putchar(',');
 912 
 913         (void) putchar('\n');
 914 }
 915 
 916 /*
 917  * Print all instances.
 918  */
 919 static void
 920 ks_instances_print(void)
 921 {
 922         ks_selector_t   *selector;
 923         ks_instance_t   *ksi, *ktmp;
 924         ks_nvpair_t     *nvpair, *ntmp;
 925         void            (*ks_print_fn)(ks_instance_t *, ks_nvpair_t *);
 926         char            *ks_number;


1477                 SAVE_INT32_X(ksi, name, fault->type);
1478                 (void) snprintf(name, sizeof (name), "fclass_%d", i);
1479                 SAVE_INT32_X(ksi, name, fault->fclass);
1480                 (void) snprintf(name, sizeof (name), "create_time_%d", i);
1481                 SAVE_HRTIME_X(ksi, name, fault->create_time);
1482                 (void) snprintf(name, sizeof (name), "msg_%d", i);
1483                 SAVE_STRING_X(ksi, name, fault->msg);
1484         }
1485 }
1486 #endif
1487 
1488 static void
1489 save_named(kstat_t *kp, ks_instance_t *ksi)
1490 {
1491         kstat_named_t *knp;
1492         int     n;
1493 
1494         for (n = kp->ks_ndata, knp = KSTAT_NAMED_PTR(kp); n > 0; n--, knp++) {
1495                 switch (knp->data_type) {
1496                 case KSTAT_DATA_CHAR:



1497                 case KSTAT_DATA_INT32:



1498                 case KSTAT_DATA_UINT32:



1499                 case KSTAT_DATA_INT64:



1500                 case KSTAT_DATA_UINT64:
1501                 case KSTAT_DATA_TIME:
1502                         nvpair_insert(ksi, knp->name,
1503                             (ks_value_t *)&knp->value, knp->data_type);
1504                         break;
1505                 case KSTAT_DATA_STRING:
1506                         SAVE_STRING_X(ksi, knp->name, KSTAT_NAMED_STR_PTR(knp));
1507                         break;
1508                 default:
1509                         assert(B_FALSE); /* Invalid data type */
1510                         break;
1511                 }
1512         }
1513 }
1514 
1515 static void
1516 save_intr(kstat_t *kp, ks_instance_t *ksi)
1517 {
1518         kstat_intr_t *intr = KSTAT_INTR_PTR(kp);
1519         char    *intr_names[] = {"hard", "soft", "watchdog", "spurious",
1520             "multiple_service"};
1521         int     n;
1522 
1523         for (n = 0; n < KSTAT_NUM_INTRS; n++)
1524                 SAVE_UINT32_X(ksi, intr_names[n], intr->intrs[n]);
1525 }
1526 
1527 static void
1528 save_io(kstat_t *kp, ks_instance_t *ksi)
1529 {
1530         kstat_io_t      *ksio = KSTAT_IO_PTR(kp);
1531 
1532         SAVE_UINT64(ksi, ksio, nread);
1533         SAVE_UINT64(ksi, ksio, nwritten);
1534         SAVE_UINT32(ksi, ksio, reads);
1535         SAVE_UINT32(ksi, ksio, writes);
1536         SAVE_UINT64(ksi, ksio, wtime);
1537         SAVE_UINT64(ksi, ksio, wlentime);
1538         SAVE_HRTIME(ksi, ksio, wlastupdate);
1539         SAVE_UINT64(ksi, ksio, rtime);
1540         SAVE_UINT64(ksi, ksio, rlentime);
1541         SAVE_HRTIME(ksi, ksio, rlastupdate);
1542         SAVE_UINT32(ksi, ksio, wcnt);
1543         SAVE_UINT32(ksi, ksio, rcnt);
1544 }
1545 
1546 static void
1547 save_timer(kstat_t *kp, ks_instance_t *ksi)
1548 {
1549         kstat_timer_t   *ktimer = KSTAT_TIMER_PTR(kp);
1550 
1551         SAVE_STRING(ksi, ktimer, name);
1552         SAVE_UINT64(ksi, ktimer, num_events);
1553         SAVE_UINT64(ksi, ktimer, elapsed_time);
1554         SAVE_UINT64(ksi, ktimer, min_time);
1555         SAVE_UINT64(ksi, ktimer, max_time);
1556         SAVE_HRTIME(ksi, ktimer, start_time);
1557         SAVE_HRTIME(ksi, ktimer, stop_time);
1558 }