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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 /*
  26  * This program is strictly for demonstration purposes and not for
  27  * production use. It demonstrates how to access the dynamic memory
  28  * caching statistics and turning variables via the kstat library.
  29  */
  30 
  31 #include <stdio.h>
  32 #include <stdlib.h>
  33 #include <stdarg.h>
  34 #include <stropts.h>
  35 #include <ctype.h>
  36 #include <unistd.h>
  37 #include <memory.h>
  38 #include <string.h>
  39 #include <fcntl.h>
  40 #include <errno.h>
  41 #include <signal.h>
  42 #include <locale.h>
  43 #include <kstat.h>
  44 
  45 #include <sys/types.h>
  46 #include <sys/time.h>
  47 #include <sys/sysinfo.h>
  48 #include <sys/buf.h>
  49 #include <sys/vfs.h>
  50 #include <sys/dnlc.h>
  51 
  52 #define TRUE 1
  53 #define FALSE 0
  54 #define SDBC_KSTAT_MODULE       "sdbc"
  55 #define SDBC_KSTAT_DYNMEM       "dynmem"
  56 
  57 typedef struct {
  58         int instance;
  59         kstat_t *ksp;
  60         } KSTAT_INFO_DEF;
  61 
  62 typedef struct {
  63         kstat_named_t   *knp;
  64         char            *named;
  65         int             newval;
  66         } DYNMEM_KNP_DEFN;
  67 
  68 typedef enum {
  69 MONITOR = 0,
  70 MAXLIST,
  71 AGECT1,
  72 AGECT2,
  73 AGECT3,
  74 SEC1,
  75 SEC2,
  76 SEC3,
  77 PCNT1,
  78 PCNT2,
  79 HDPCNT,
  80 ALLOC,
  81 DEALLOC,
  82 HISTORY,
  83 NODATA,
  84 CAND,
  85 DEALLOCS,
  86 HOSTS,
  87 PESTS,
  88 METAS,
  89 HOLDS,
  90 OTHERS,
  91 NOTAVAIL,
  92 DIRECTIVE,
  93 SIMPLECT
  94 } arglist_id;
  95 
  96 #define NO_VALUE -1
  97 
  98 DYNMEM_KNP_DEFN dynmem_knp[] = {
  99         NULL,   "sdbc_monitor_dynmem",          NO_VALUE,
 100         NULL,   "sdbc_max_dyn_list",            NO_VALUE,
 101         NULL,   "sdbc_cache_aging_ct1",         NO_VALUE,
 102         NULL,   "sdbc_cache_aging_ct2",         NO_VALUE,
 103         NULL,   "sdbc_cache_aging_ct3",         NO_VALUE,
 104         NULL,   "sdbc_cache_aging_sec1",        NO_VALUE,
 105         NULL,   "sdbc_cache_aging_sec2",        NO_VALUE,
 106         NULL,   "sdbc_cache_aging_sec3",        NO_VALUE,
 107         NULL,   "sdbc_cache_aging_pcnt1",       NO_VALUE,
 108         NULL,   "sdbc_cache_aging_pcnt2",       NO_VALUE,
 109         NULL,   "sdbc_max_holds_pcnt",          NO_VALUE,
 110         NULL,   "sdbc_alloc_cnt",               NO_VALUE,
 111         NULL,   "sdbc_dealloc_cnt",             NO_VALUE,
 112         NULL,   "sdbc_history",                 NO_VALUE,
 113         NULL,   "sdbc_nodatas",                 NO_VALUE,
 114         NULL,   "sdbc_candidates",              NO_VALUE,
 115         NULL,   "sdbc_deallocs",                NO_VALUE,
 116         NULL,   "sdbc_hosts",                   NO_VALUE,
 117         NULL,   "sdbc_pests",                   NO_VALUE,
 118         NULL,   "sdbc_metas",                   NO_VALUE,
 119         NULL,   "sdbc_holds",                   NO_VALUE,
 120         NULL,   "sdbc_others",                  NO_VALUE,
 121         NULL,   "sdbc_notavail",                NO_VALUE,
 122         NULL,   "sdbc_process_directive",       NO_VALUE,
 123         NULL,   "sdbc_simplect",                NO_VALUE,
 124         NULL,   NULL,                           NO_VALUE
 125         };
 126 
 127 /*
 128  * Print Usage
 129  */
 130 static void
 131 print_usage()
 132 {
 133         (void) printf("USAGE: wake - wakeup thread, hys - max hysteresis\n");
 134         (void) printf("       mon 1 - monitor shutdown\n");
 135         (void) printf("           2 - monitor thread stats1\n");
 136         (void) printf("           4 - monitor thread stats2\n");
 137         (void) printf("       age1 n - num cyc to full host aging and "
 138             "dealloc\n");
 139         (void) printf("       age2 n - num cyc to full meta aging and "
 140             "dealloc\n");
 141         (void) printf("       age3 n - num cyc to full one pg aging and "
 142             "dealloc\n");
 143         (void) printf("       sec1 n  - sec1 aging time\n");
 144         (void) printf("       sec2 n  - sec2 aging time\n");
 145         (void) printf("       sec3 n  - sec3 aging time\n");
 146         (void) printf("       pcnt1 n  - percent to sec1/sec2 trans\n");
 147         (void) printf("       pcnt2 n  - percent to sec2/sec3 trans\n");
 148         (void) printf("       hdpcnt n  - max percent of cents for holds\n");
 149         (void) printf("       list n  - host+pest max len\n");
 150         (void) printf("No Args - print current settings only\n");
 151 }
 152 
 153 /*
 154  * Main
 155  */
 156 /* ARGSUSED */
 157 #ifdef lint
 158 int
 159 sd_dynmem_lintmain(int argc, char *argv[])
 160 #else
 161 int
 162 main(int argc, char *argv[])
 163 #endif
 164 {
 165         DYNMEM_KNP_DEFN *p_dynmem_knp;
 166         kstat_ctl_t     *kctl;
 167         KSTAT_INFO_DEF  info_ksp;
 168         int             val;
 169         char            **pargs, **cur_pargs;
 170 
 171         /*
 172          * grab and parse argument list
 173          */
 174         p_dynmem_knp = dynmem_knp;
 175         pargs = argv;
 176         while (*pargs) {
 177                 (void) printf("pargs=%x - %s\n", (uint_t)pargs, *pargs);
 178 
 179                 cur_pargs = pargs;
 180                 pargs++;
 181 
 182                 if (strcmp(*cur_pargs, "h") == 0) {
 183                         print_usage();
 184                         return (0);
 185                 }
 186 
 187                 if (strcmp(*cur_pargs, "wake") == 0) {
 188                         if ((p_dynmem_knp+DIRECTIVE)->newval == NO_VALUE)
 189                                 (p_dynmem_knp+DIRECTIVE)->newval = 0;
 190                         (p_dynmem_knp+DIRECTIVE)->newval |= 0x01;
 191                         continue;
 192                 }
 193 
 194                 if (strcmp(*cur_pargs, "hys") == 0) {
 195                         if ((p_dynmem_knp+DIRECTIVE)->newval == NO_VALUE)
 196                                 (p_dynmem_knp+DIRECTIVE)->newval = 0;
 197                         (p_dynmem_knp+DIRECTIVE)->newval |= 0x02;
 198                         continue;
 199                 }
 200 
 201                 if (strcmp (*cur_pargs, "mon") == 0) {
 202                         val = atoi(*pargs);
 203                         (void) printf("errno=%x, %s=%x\n", errno, *cur_pargs,
 204                             val);
 205                         pargs++;
 206                         (p_dynmem_knp+MONITOR)->newval = val;
 207                 }
 208 
 209                 if (strcmp (*cur_pargs, "age1") == 0) {
 210                         val = atoi(*pargs);
 211                         (void) printf("errno=%x, %s=%x\n", errno, *cur_pargs,
 212                             val);
 213                         pargs++;
 214                         (p_dynmem_knp+AGECT1)->newval = val;
 215                 }
 216 
 217                 if (strcmp(*cur_pargs, "age2") == 0) {
 218                         val = atoi(*pargs);
 219                         (void) printf("errno=%x, %s=%x\n", errno, *cur_pargs,
 220                             val);
 221                         pargs++;
 222                         (p_dynmem_knp+AGECT2)->newval = val;
 223                 }
 224 
 225                 if (strcmp(*cur_pargs, "age3") == 0) {
 226                         val = atoi(*pargs);
 227                         (void) printf("errno=%x, %s=%x\n", errno, *cur_pargs,
 228                             val);
 229                         pargs++;
 230                         (p_dynmem_knp+AGECT3)->newval = val;
 231                 }
 232 
 233                 if (strcmp (*cur_pargs, "sec1") == 0) {
 234                         val = atoi(*pargs);
 235                         (void) printf("errno=%x, %s=%x\n", errno, *cur_pargs,
 236                             val);
 237                         pargs++;
 238                         if (val == 0)
 239                                 break;
 240                         else {
 241                                 (p_dynmem_knp+SEC1)->newval = val;
 242                                 continue;
 243                         }
 244                 }
 245 
 246                 if (strcmp(*cur_pargs, "sec2") == 0) {
 247                         val = atoi(*pargs);
 248                         pargs++;
 249                         (void) printf("errno=%x, %s=%x\n", errno, *cur_pargs,
 250                             val);
 251                         if (val == 0)
 252                                 break;
 253                         else {
 254                                 (p_dynmem_knp+SEC2)->newval = val;
 255                                 continue;
 256                         }
 257                 }
 258 
 259                 if (strcmp(*cur_pargs, "sec3") == 0) {
 260                         val = atoi(*pargs);
 261                         pargs++;
 262                         (void) printf("errno=%x, %s=%x\n", errno, *cur_pargs,
 263                             val);
 264                         if (val == 0)
 265                                 break;
 266                         else {
 267                                 (p_dynmem_knp+SEC3)->newval = val;
 268                                 continue;
 269                         }
 270                 }
 271 
 272                 if (strcmp(*cur_pargs, "pcnt1") == 0) {
 273                         val = atoi(*pargs);
 274                         pargs++;
 275                         (void) printf("errno=%x, %s=%x\n", errno, *cur_pargs,
 276                             val);
 277                         if (val == 0)
 278                                 break;
 279                         else {
 280                                 (p_dynmem_knp+PCNT1)->newval = val;
 281                                 continue;
 282                         }
 283                 }
 284 
 285                 if (strcmp(*cur_pargs, "pcnt2") == 0) {
 286                         val = atoi(*pargs);
 287                         pargs++;
 288                         (void) printf("errno=%x, %s=%x\n", errno, *cur_pargs,
 289                             val);
 290                         if (val == 0)
 291                                 break;
 292                         else {
 293                                 (p_dynmem_knp+PCNT2)->newval = val;
 294                                 continue;
 295                         }
 296                 }
 297 
 298                 if (strcmp(*cur_pargs, "hdpcnt") == 0) {
 299                         val = atoi(*pargs);
 300                         pargs++;
 301                         (void) printf("errno=%x, %s=%x\n", errno, *cur_pargs,
 302                             val);
 303                         if (val < 0)
 304                                 break;
 305                         else {
 306                                 (p_dynmem_knp+HDPCNT)->newval = val;
 307                                 continue;
 308                         }
 309                 }
 310 
 311                 if (strcmp(*cur_pargs, "list") == 0) {
 312                         val = atoi(*pargs);
 313                         pargs++;
 314                         (void) printf("errno=%x, %s=%x\n", errno, *cur_pargs,
 315                             val);
 316                         if (val == 0)
 317                                 break;
 318                         else {
 319                                 (p_dynmem_knp+MAXLIST)->newval = val;
 320                                 continue;
 321                         }
 322                 }
 323         }   /* while(*pargs && cl) */
 324 
 325         /*
 326          * open the kstat library
 327          */
 328         kctl = kstat_open();
 329         if (kctl == NULL) {
 330                 (void) printf("kstat_open() failed\n");
 331                 return (1);
 332         }
 333 
 334         /*
 335          * is the name module about
 336          */
 337         info_ksp.instance = 0;
 338         info_ksp.ksp = kstat_lookup(kctl, SDBC_KSTAT_MODULE, 0,
 339             SDBC_KSTAT_DYNMEM);
 340         if (info_ksp.ksp == NULL) {
 341                 (void) printf("No module to report\n");
 342                 return (1);
 343         }
 344 
 345         /*
 346          * using the info get a copy of the data
 347          */
 348         if (kstat_read(kctl, info_ksp.ksp, NULL) == -1) {
 349                 (void) printf("Can't read kstat\n");
 350                 return (1);
 351         }
 352 
 353         /*
 354          * print the current data
 355          */
 356         p_dynmem_knp = dynmem_knp;
 357         while (p_dynmem_knp->named) {
 358                 p_dynmem_knp->knp =
 359                         kstat_data_lookup(info_ksp.ksp, p_dynmem_knp->named);
 360                 if (p_dynmem_knp->knp == NULL) {
 361                         (void) printf("kstat_data_lookup(%s) failed\n",
 362                             p_dynmem_knp->named);
 363                         return (1);
 364                 } else {
 365                         (void) printf("%s: %x\n", p_dynmem_knp->named,
 366                             (uint_t)p_dynmem_knp->knp->value.ul);
 367                         p_dynmem_knp++;
 368                 }
 369         }
 370 
 371         /*
 372          * modify the data and write it back
 373          */
 374         p_dynmem_knp = dynmem_knp;
 375         while (p_dynmem_knp->named) {
 376                 if (p_dynmem_knp->newval != NO_VALUE)
 377                         p_dynmem_knp->knp->value.ul = p_dynmem_knp->newval;
 378                 p_dynmem_knp++;
 379         }
 380 
 381         if (kstat_write(kctl, info_ksp.ksp, NULL) == -1) {
 382                 (void) printf("kstat_write() failed\n");
 383                 return (1);
 384         }
 385 
 386         (void) printf("Finished (h for help)\n");
 387         return (0);
 388 }