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