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