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 } 389