1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   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  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  23  * Copyright 2013 David Hoeppner.  All rights reserved.
  24  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  25  * Copyright 2016 Garrett D'Amore
  26  */
  27 
  28 #ifndef _STAT_KSTAT_H
  29 #define _STAT_KSTAT_H
  30 
  31 /*
  32  * Structures needed by the kstat reader functions.
  33  */
  34 #include <sys/var.h>
  35 #include <sys/utsname.h>
  36 #include <sys/sysinfo.h>
  37 #include <sys/flock.h>
  38 #include <sys/dnlc.h>
  39 #include <regex.h>
  40 #include <nfs/nfs.h>
  41 #include <nfs/nfs_clnt.h>
  42 
  43 #ifdef __sparc
  44 #include <vm/hat_sfmmu.h>
  45 #include <sys/simmstat.h>
  46 #include <sys/sysctrl.h>
  47 #include <sys/fhc.h>
  48 #endif
  49 
  50 typedef union ks_value {
  51         char            c[16];
  52         int32_t         i32;
  53         uint32_t        ui32;
  54         struct {
  55                 union {
  56                         char    *ptr;
  57                         char    __pad[8];
  58                 } addr;
  59                 uint32_t        len;
  60         } str;
  61 
  62         int64_t         i64;
  63         uint64_t        ui64;
  64         hrtime_t        t;
  65 } ks_value_t;
  66 
  67 #define SAVE_HRTIME(I, S, N)                                    \
  68 {                                                               \
  69         ks_value_t v;                                           \
  70         v.ui64 = S->N;                                               \
  71         if (g_hrtime_fmt == KS_HRFMT_DEFAULT) {                 \
  72                 nvpair_insert(I, #N, &v, KSTAT_DATA_UINT64);        \
  73         } else {                                                \
  74                 nvpair_insert(I, #N, &v, KSTAT_DATA_TIME);  \
  75         }                                                       \
  76 }
  77 
  78 #define SAVE_INT32(I, S, N)                             \
  79 {                                                       \
  80         ks_value_t v;                                   \
  81         v.i32 = S->N;                                        \
  82         nvpair_insert(I, #N, &v, KSTAT_DATA_INT32); \
  83 }
  84 
  85 #define SAVE_UINT32(I, S, N)                            \
  86 {                                                       \
  87         ks_value_t v;                                   \
  88         v.ui32 = S->N;                                       \
  89         nvpair_insert(I, #N, &v, KSTAT_DATA_UINT32);        \
  90 }
  91 
  92 #define SAVE_INT64(I, S, N)                             \
  93 {                                                       \
  94         ks_value_t v;                                   \
  95         v.i64 = S->N;                                        \
  96         nvpair_insert(I, #N, &v, KSTAT_DATA_INT64); \
  97 }
  98 
  99 #define SAVE_UINT64(I, S, N)                            \
 100 {                                                       \
 101         ks_value_t v;                                   \
 102         v.ui64 = S->N;                                       \
 103         nvpair_insert(I, #N, &v, KSTAT_DATA_UINT64);        \
 104 }
 105 
 106 /*
 107  * We dont want const "strings" because we free
 108  * the instances later.
 109  */
 110 #define SAVE_STRING(I, S, N)                            \
 111 {                                                       \
 112         ks_value_t v;                                   \
 113         v.str.addr.ptr = safe_strdup(S->N);          \
 114         v.str.len = strlen(S->N);                    \
 115         nvpair_insert(I, #N, &v, KSTAT_DATA_STRING);        \
 116 }
 117 
 118 #define SAVE_HRTIME_X(I, N, V)                          \
 119 {                                                       \
 120         ks_value_t v;                                   \
 121         v.ui64 = V;                                     \
 122         nvpair_insert(I, N, &v, KSTAT_DATA_TIME);   \
 123 }
 124 
 125 #define SAVE_INT32_X(I, N, V)                           \
 126 {                                                       \
 127         ks_value_t v;                                   \
 128         v.i32 = V;                                      \
 129         nvpair_insert(I, N, &v, KSTAT_DATA_INT32);  \
 130 }
 131 
 132 #define SAVE_UINT32_X(I, N, V)                          \
 133 {                                                       \
 134         ks_value_t v;                                   \
 135         v.ui32 = V;                                     \
 136         nvpair_insert(I, N, &v, KSTAT_DATA_UINT32); \
 137 }
 138 
 139 #define SAVE_UINT64_X(I, N, V)                          \
 140 {                                                       \
 141         ks_value_t v;                                   \
 142         v.ui64 = V;                                     \
 143         nvpair_insert(I, N, &v, KSTAT_DATA_UINT64); \
 144 }
 145 
 146 #define SAVE_STRING_X(I, N, V)                          \
 147 {                                                       \
 148         ks_value_t v;                                   \
 149         v.str.addr.ptr = safe_strdup(V);                \
 150         v.str.len = (V) ? strlen(V) : 0;                \
 151         nvpair_insert(I, N, &v, KSTAT_DATA_STRING); \
 152 }
 153 
 154 #define SAVE_CHAR_X(I, N, V)                            \
 155 {                                                       \
 156         ks_value_t v;                                   \
 157         (void) asprintf(&v.str.addr.ptr, "%c", V);  \
 158         v.str.len = 1;                                  \
 159         nvpair_insert(I, N, &v, KSTAT_DATA_STRING); \
 160 }
 161 
 162 #define DFLT_FMT                                        \
 163         "module: %-30.30s  instance: %-6d\n"            \
 164         "name:   %-30.30s  class:    %-.30s\n"
 165 
 166 #define JSON_FMT                                        \
 167         "{\n\t\"module\": \"%s\",\n"                    \
 168         "\t\"instance\": %d,\n"                         \
 169         "\t\"name\": \"%s\",\n"                         \
 170         "\t\"class\": \"%s\",\n"                        \
 171         "\t\"type\": %d,\n"
 172 
 173 #define KS_DFMT "\t%-30s  "
 174 #define KS_JFMT "\t\t\"%s\": "
 175 #define KS_PFMT "%s:%d:%s:%s"
 176 
 177 #define KS_HRFMT_DEFAULT        'o'
 178 #define KS_HRFMT_BOOT           'b'
 179 #define KS_HRFMT_UNIX           'u'
 180 #define KS_HRFMT_DATE           'd'
 181 #define KS_HRFMT_NANO           'n'
 182 #define KS_HRFMT_ISO            'I'
 183 #define KS_HRFMT_ZISO           'Z'
 184 
 185 typedef struct ks_instance {
 186         list_node_t     ks_next;
 187         char            ks_name[KSTAT_STRLEN];
 188         char            ks_module[KSTAT_STRLEN];
 189         char            ks_class[KSTAT_STRLEN];
 190         int             ks_instance;
 191         uchar_t         ks_type;
 192         hrtime_t        ks_snaptime;
 193         list_t          ks_nvlist;
 194 } ks_instance_t;
 195 
 196 typedef struct ks_nvpair {
 197         list_node_t     nv_next;
 198         char            name[KSTAT_STRLEN];
 199         uchar_t         data_type;
 200         ks_value_t      value;
 201 } ks_nvpair_t;
 202 
 203 typedef struct ks_pattern {
 204         char            *pstr;
 205         regex_t         preg;
 206 } ks_pattern_t;
 207 
 208 typedef struct ks_selector {
 209         list_node_t     ks_next;
 210         ks_pattern_t    ks_module;
 211         ks_pattern_t    ks_instance;
 212         ks_pattern_t    ks_name;
 213         ks_pattern_t    ks_statistic;
 214 } ks_selector_t;
 215 
 216 static void     usage(void);
 217 static int      compare_instances(ks_instance_t *, ks_instance_t *);
 218 static void     nvpair_insert(ks_instance_t *, char *, ks_value_t *, uchar_t);
 219 static boolean_t        ks_match(const char *, ks_pattern_t *);
 220 static ks_selector_t    *new_selector(void);
 221 static void     ks_instances_read(kstat_ctl_t *);
 222 static void     ks_value_print(ks_nvpair_t *);
 223 static void     ks_instance_print(ks_instance_t *, ks_nvpair_t *);
 224 static void     ks_instances_print(void);
 225 static char     *ks_safe_strdup(char *);
 226 static void     ks_sleep_until(hrtime_t *, hrtime_t, int, int *);
 227 
 228 /* Raw kstat readers */
 229 static void     save_cpu_stat(kstat_t *, ks_instance_t *);
 230 static void     save_var(kstat_t *, ks_instance_t *);
 231 static void     save_ncstats(kstat_t *, ks_instance_t *);
 232 static void     save_sysinfo(kstat_t *, ks_instance_t *);
 233 static void     save_vminfo(kstat_t *, ks_instance_t *);
 234 static void     save_nfs(kstat_t *, ks_instance_t *);
 235 #ifdef __sparc
 236 static void     save_sfmmu_global_stat(kstat_t *, ks_instance_t *);
 237 static void     save_sfmmu_tsbsize_stat(kstat_t *, ks_instance_t *);
 238 static void     save_simmstat(kstat_t *, ks_instance_t *);
 239 /* Helper function for save_temperature() */
 240 static char     *short_array_to_string(short *, int);
 241 static void     save_temperature(kstat_t *, ks_instance_t *);
 242 static void     save_temp_over(kstat_t *, ks_instance_t *);
 243 static void     save_ps_shadow(kstat_t *, ks_instance_t *);
 244 static void     save_fault_list(kstat_t *, ks_instance_t *);
 245 #endif
 246 
 247 /* Named kstat readers */
 248 static void     save_named(kstat_t *, ks_instance_t *);
 249 static void     save_intr(kstat_t *, ks_instance_t *);
 250 static void     save_io(kstat_t *, ks_instance_t *);
 251 static void     save_timer(kstat_t *, ks_instance_t *);
 252 
 253 /* Typedef for raw kstat reader functions */
 254 typedef void    (*kstat_raw_reader_t)(kstat_t *, ks_instance_t *);
 255 
 256 static struct {
 257         kstat_raw_reader_t fn;
 258         char *name;
 259 } ks_raw_lookup[] = {
 260         /* Function name                kstat name              */
 261         {save_cpu_stat,                 "cpu_stat:cpu_stat"},
 262         {save_var,                      "unix:var"},
 263         {save_ncstats,                  "unix:ncstats"},
 264         {save_sysinfo,                  "unix:sysinfo"},
 265         {save_vminfo,                   "unix:vminfo"},
 266         {save_nfs,                      "nfs:mntinfo"},
 267 #ifdef __sparc
 268         {save_sfmmu_global_stat,        "unix:sfmmu_global_stat"},
 269         {save_sfmmu_tsbsize_stat,       "unix:sfmmu_tsbsize_stat"},
 270         {save_simmstat,                 "unix:simm-status"},
 271         {save_temperature,              "unix:temperature"},
 272         {save_temp_over,                "unix:temperature override"},
 273         {save_ps_shadow,                "unix:ps_shadow"},
 274         {save_fault_list,               "unix:fault_list"},
 275 #endif
 276         {NULL, NULL},
 277 };
 278 
 279 static kstat_raw_reader_t       lookup_raw_kstat_fn(char *, char *);
 280 
 281 #endif /* _STAT_KSTAT_H */