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
print_usage()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
sd_dynmem_lintmain(int argc,char * argv[])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