Print this page
3623 kstat must accept partial stat specification
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/stat/kstat/kstat.c
+++ new/usr/src/cmd/stat/kstat/kstat.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright (c) 2013 David Hoeppner. All rights reserved.
25 25 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
↓ open down ↓ |
25 lines elided |
↑ open up ↑ |
26 26 */
27 27
28 28 /*
29 29 * Display kernel statistics
30 30 *
31 31 * This is a reimplementation of the perl kstat command originally found
32 32 * under usr/src/cmd/kstat/kstat.pl
33 33 *
34 34 * Incompatibilities:
35 35 * - perl regular expressions replaced with extended REs bracketed by '/'
36 - * - options checking is stricter
37 36 *
38 37 * Flags added:
39 38 * -C similar to the -p option but value is separated by a colon
40 39 * -h display help
41 40 * -j json format
42 41 */
43 42
44 43 #include <assert.h>
45 44 #include <ctype.h>
46 45 #include <errno.h>
47 46 #include <kstat.h>
48 47 #include <langinfo.h>
49 48 #include <libgen.h>
50 49 #include <limits.h>
51 50 #include <locale.h>
52 51 #include <signal.h>
53 52 #include <stddef.h>
54 53 #include <stdio.h>
55 54 #include <stdlib.h>
56 55 #include <string.h>
57 56 #include <strings.h>
58 57 #include <time.h>
59 58 #include <unistd.h>
60 59 #include <sys/list.h>
61 60 #include <sys/time.h>
62 61 #include <sys/types.h>
63 62
64 63 #include "kstat.h"
65 64 #include "statcommon.h"
66 65
67 66 char *cmdname = "kstat"; /* Name of this command */
68 67 int caught_cont = 0; /* Have caught a SIGCONT */
69 68
70 69 static uint_t g_timestamp_fmt = NODATE;
71 70
72 71 /* Helper flag - header was printed already? */
73 72 static boolean_t g_headerflg;
74 73
75 74 /* Saved command line options */
76 75 static boolean_t g_cflg = B_FALSE;
77 76 static boolean_t g_jflg = B_FALSE;
78 77 static boolean_t g_lflg = B_FALSE;
79 78 static boolean_t g_pflg = B_FALSE;
80 79 static boolean_t g_qflg = B_FALSE;
81 80 static ks_pattern_t g_ks_class = {"*", 0};
82 81
83 82 /* Return zero if a selector did match */
84 83 static int g_matched = 1;
85 84
86 85 /* Sorted list of kstat instances */
87 86 static list_t instances_list;
88 87 static list_t selector_list;
89 88
90 89 int
91 90 main(int argc, char **argv)
92 91 {
93 92 ks_selector_t *nselector;
94 93 ks_selector_t *uselector;
95 94 kstat_ctl_t *kc;
96 95 hrtime_t start_n;
97 96 hrtime_t period_n;
98 97 boolean_t errflg = B_FALSE;
99 98 boolean_t nselflg = B_FALSE;
100 99 boolean_t uselflg = B_FALSE;
101 100 char *q;
102 101 int count = 1;
103 102 int infinite_cycles = 0;
104 103 int interval = 0;
105 104 int n = 0;
106 105 int c, m, tmp;
107 106
108 107 (void) setlocale(LC_ALL, "");
109 108 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
110 109 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
111 110 #endif
112 111 (void) textdomain(TEXT_DOMAIN);
113 112
114 113 /*
115 114 * Create the selector list and a dummy default selector to match
116 115 * everything. While we process the cmdline options we will add
117 116 * selectors to this list.
118 117 */
119 118 list_create(&selector_list, sizeof (ks_selector_t),
120 119 offsetof(ks_selector_t, ks_next));
121 120
122 121 nselector = new_selector();
123 122
124 123 /*
125 124 * Parse named command line arguments.
126 125 */
127 126 while ((c = getopt(argc, argv, "h?CqjlpT:m:i:n:s:c:")) != EOF)
128 127 switch (c) {
129 128 case 'h':
130 129 case '?':
131 130 usage();
132 131 exit(0);
133 132 break;
134 133 case 'C':
135 134 g_pflg = g_cflg = B_TRUE;
136 135 break;
137 136 case 'q':
138 137 g_qflg = B_TRUE;
139 138 break;
140 139 case 'j':
141 140 g_jflg = B_TRUE;
142 141 break;
143 142 case 'l':
144 143 g_pflg = g_lflg = B_TRUE;
145 144 break;
146 145 case 'p':
147 146 g_pflg = B_TRUE;
148 147 break;
149 148 case 'T':
150 149 switch (*optarg) {
151 150 case 'd':
152 151 g_timestamp_fmt = DDATE;
153 152 break;
154 153 case 'u':
155 154 g_timestamp_fmt = UDATE;
156 155 break;
157 156 default:
158 157 errflg = B_TRUE;
159 158 }
160 159 break;
161 160 case 'm':
162 161 nselflg = B_TRUE;
163 162 nselector->ks_module.pstr =
164 163 (char *)ks_safe_strdup(optarg);
165 164 break;
166 165 case 'i':
167 166 nselflg = B_TRUE;
168 167 nselector->ks_instance.pstr =
169 168 (char *)ks_safe_strdup(optarg);
170 169 break;
171 170 case 'n':
172 171 nselflg = B_TRUE;
173 172 nselector->ks_name.pstr =
174 173 (char *)ks_safe_strdup(optarg);
175 174 break;
176 175 case 's':
177 176 nselflg = B_TRUE;
178 177 nselector->ks_statistic.pstr =
179 178 (char *)ks_safe_strdup(optarg);
180 179 break;
181 180 case 'c':
182 181 g_ks_class.pstr =
183 182 (char *)ks_safe_strdup(optarg);
184 183 break;
185 184 default:
186 185 errflg = B_TRUE;
187 186 break;
188 187 }
189 188
190 189 if (g_qflg && (g_jflg || g_pflg)) {
191 190 (void) fprintf(stderr, gettext(
192 191 "-q and -lpj are mutually exclusive\n"));
193 192 errflg = B_TRUE;
194 193 }
195 194
196 195 if (errflg) {
197 196 usage();
198 197 exit(2);
199 198 }
200 199
201 200 argc -= optind;
202 201 argv += optind;
203 202
204 203 /*
205 204 * Consume the rest of the command line. Parsing the
206 205 * unnamed command line arguments.
207 206 */
208 207 while (argc--) {
209 208 errno = 0;
210 209 tmp = strtoul(*argv, &q, 10);
211 210 if (tmp == ULONG_MAX && errno == ERANGE) {
212 211 if (n == 0) {
213 212 (void) fprintf(stderr, gettext(
214 213 "Interval is too large\n"));
215 214 } else if (n == 1) {
216 215 (void) fprintf(stderr, gettext(
217 216 "Count is too large\n"));
218 217 }
219 218 usage();
220 219 exit(2);
221 220 }
222 221
223 222 if (errno != 0 || *q != '\0') {
224 223 m = 0;
225 224 uselector = new_selector();
226 225 while ((q = (char *)strsep(argv, ":")) != NULL) {
227 226 m++;
228 227 if (m > 4) {
229 228 free(uselector);
230 229 usage();
231 230 exit(2);
232 231 }
233 232
234 233 if (*q != '\0') {
235 234 switch (m) {
236 235 case 1:
237 236 uselector->ks_module.pstr =
238 237 (char *)ks_safe_strdup(q);
239 238 break;
240 239 case 2:
241 240 uselector->ks_instance.pstr =
242 241 (char *)ks_safe_strdup(q);
243 242 break;
244 243 case 3:
245 244 uselector->ks_name.pstr =
246 245 (char *)ks_safe_strdup(q);
247 246 break;
↓ open down ↓ |
201 lines elided |
↑ open up ↑ |
248 247 case 4:
249 248 uselector->ks_statistic.pstr =
250 249 (char *)ks_safe_strdup(q);
251 250 break;
252 251 default:
253 252 assert(B_FALSE);
254 253 }
255 254 }
256 255 }
257 256
258 - if (m < 4) {
259 - free(uselector);
260 - usage();
261 - exit(2);
262 - }
263 -
264 257 uselflg = B_TRUE;
265 258 list_insert_tail(&selector_list, uselector);
266 259 } else {
267 260 if (tmp < 1) {
268 261 if (n == 0) {
269 262 (void) fprintf(stderr, gettext(
270 263 "Interval must be an "
271 264 "integer >= 1"));
272 265 } else if (n == 1) {
273 266 (void) fprintf(stderr, gettext(
274 267 "Count must be an integer >= 1"));
275 268 }
276 269 usage();
277 270 exit(2);
278 271 } else {
279 272 if (n == 0) {
280 273 interval = tmp;
281 274 count = -1;
282 275 } else if (n == 1) {
283 276 count = tmp;
284 277 } else {
285 278 usage();
286 279 exit(2);
287 280 }
288 281 }
289 282 n++;
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
290 283 }
291 284 argv++;
292 285 }
293 286
294 287 /*
295 288 * Check if we founded a named selector on the cmdline.
296 289 */
297 290 if (uselflg) {
298 291 if (nselflg) {
299 292 (void) fprintf(stderr, gettext(
300 - "module:instance:name:statistic and "
293 + "[module[:instance[:name[:statistic]]]] and "
301 294 "-m -i -n -s are mutually exclusive"));
302 295 usage();
303 296 exit(2);
304 297 } else {
305 298 free(nselector);
306 299 }
307 300 } else {
308 301 list_insert_tail(&selector_list, nselector);
309 302 }
310 303
311 304 assert(!list_is_empty(&selector_list));
312 305
313 306 list_create(&instances_list, sizeof (ks_instance_t),
314 307 offsetof(ks_instance_t, ks_next));
315 308
316 309 while ((kc = kstat_open()) == NULL) {
317 310 if (errno == EAGAIN) {
318 311 (void) poll(NULL, 0, 200);
319 312 } else {
320 313 perror("kstat_open");
321 314 exit(3);
322 315 }
323 316 }
324 317
325 318 if (count > 1) {
326 319 if (signal(SIGCONT, cont_handler) == SIG_ERR) {
327 320 (void) fprintf(stderr, gettext(
328 321 "signal failed"));
329 322 exit(3);
330 323 }
331 324 }
332 325
333 326 period_n = (hrtime_t)interval * NANOSEC;
334 327 start_n = gethrtime();
335 328
336 329 while (count == -1 || count-- > 0) {
337 330 ks_instances_read(kc);
338 331 ks_instances_print();
339 332
340 333 if (interval && count) {
341 334 ks_sleep_until(&start_n, period_n, infinite_cycles,
342 335 &caught_cont);
343 336 (void) kstat_chain_update(kc);
344 337 (void) putchar('\n');
345 338 }
346 339 }
347 340
348 341 (void) kstat_close(kc);
349 342
350 343 return (g_matched);
351 344 }
352 345
353 346 /*
354 347 * Print usage.
↓ open down ↓ |
44 lines elided |
↑ open up ↑ |
355 348 */
356 349 static void
357 350 usage(void)
358 351 {
359 352 (void) fprintf(stderr, gettext(
360 353 "Usage:\n"
361 354 "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ]\n"
362 355 " [ -m module ] [ -i instance ] [ -n name ] [ -s statistic ]\n"
363 356 " [ interval [ count ] ]\n"
364 357 "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ]\n"
365 - " [ module:instance:name:statistic ... ]\n"
358 + " [ module[:instance[:name[:statistic]]] ... ]\n"
366 359 " [ interval [ count ] ]\n"));
367 360 }
368 361
369 362 /*
370 363 * Sort compare function.
371 364 */
372 365 static int
373 366 compare_instances(ks_instance_t *l_arg, ks_instance_t *r_arg)
374 367 {
375 368 int rval;
376 369
377 370 rval = strcasecmp(l_arg->ks_module, r_arg->ks_module);
378 371 if (rval == 0) {
379 372 if (l_arg->ks_instance == r_arg->ks_instance) {
380 373 return (strcasecmp(l_arg->ks_name, r_arg->ks_name));
381 374 } else if (l_arg->ks_instance < r_arg->ks_instance) {
382 375 return (-1);
383 376 } else {
384 377 return (1);
385 378 }
386 379 } else {
387 380 return (rval);
388 381 }
389 382 }
390 383
391 384 static char *
392 385 ks_safe_strdup(char *str)
393 386 {
394 387 char *ret;
395 388
396 389 if (str == NULL) {
397 390 return (NULL);
398 391 }
399 392
400 393 while ((ret = strdup(str)) == NULL) {
401 394 if (errno == EAGAIN) {
402 395 (void) poll(NULL, 0, 200);
403 396 } else {
404 397 perror("strdup");
405 398 exit(3);
406 399 }
407 400 }
408 401
409 402 return (ret);
410 403 }
411 404
412 405 static void
413 406 ks_sleep_until(hrtime_t *wakeup, hrtime_t interval, int forever,
414 407 int *caught_cont)
415 408 {
416 409 hrtime_t now, pause, pause_left;
417 410 struct timespec pause_tv;
418 411 int status;
419 412
420 413 now = gethrtime();
421 414 pause = *wakeup + interval - now;
422 415
423 416 if (pause <= 0 || pause < (interval / 4)) {
424 417 if (forever || *caught_cont) {
425 418 *wakeup = now + interval;
426 419 pause = interval;
427 420 } else {
428 421 pause = interval / 2;
429 422 *wakeup += interval;
430 423 }
431 424 } else {
432 425 *wakeup += interval;
433 426 }
434 427
435 428 if (pause < 1000) {
436 429 return;
437 430 }
438 431
439 432 pause_left = pause;
440 433 do {
441 434 pause_tv.tv_sec = pause_left / NANOSEC;
442 435 pause_tv.tv_nsec = pause_left % NANOSEC;
443 436 status = nanosleep(&pause_tv, (struct timespec *)NULL);
444 437 if (status < 0) {
445 438 if (errno == EINTR) {
446 439 now = gethrtime();
447 440 pause_left = *wakeup - now;
448 441 if (pause_left < 1000) {
449 442 return;
450 443 }
451 444 } else {
452 445 perror("nanosleep");
453 446 exit(3);
454 447 }
455 448 }
456 449 } while (status != 0);
457 450 }
458 451
459 452 /*
460 453 * Inserts an instance in the per selector list.
461 454 */
462 455 static void
463 456 nvpair_insert(ks_instance_t *ksi, char *name, ks_value_t *value,
464 457 uchar_t data_type)
465 458 {
466 459 ks_nvpair_t *instance;
467 460 ks_nvpair_t *tmp;
468 461
469 462 instance = (ks_nvpair_t *)malloc(sizeof (ks_nvpair_t));
470 463 if (instance == NULL) {
471 464 perror("malloc");
472 465 exit(3);
473 466 }
474 467
475 468 (void) strlcpy(instance->name, name, KSTAT_STRLEN);
476 469 (void) memcpy(&instance->value, value, sizeof (ks_value_t));
477 470 instance->data_type = data_type;
478 471
479 472 tmp = list_head(&ksi->ks_nvlist);
480 473 while (tmp != NULL && strcasecmp(instance->name, tmp->name) > 0)
481 474 tmp = list_next(&ksi->ks_nvlist, tmp);
482 475
483 476 list_insert_before(&ksi->ks_nvlist, tmp, instance);
484 477 }
485 478
486 479 /*
487 480 * Allocates a new all-matching selector.
488 481 */
489 482 static ks_selector_t *
490 483 new_selector(void)
491 484 {
492 485 ks_selector_t *selector;
493 486
494 487 selector = (ks_selector_t *)malloc(sizeof (ks_selector_t));
495 488 if (selector == NULL) {
496 489 perror("malloc");
497 490 exit(3);
498 491 }
499 492
500 493 list_link_init(&selector->ks_next);
501 494
502 495 selector->ks_module.pstr = "*";
503 496 selector->ks_instance.pstr = "*";
504 497 selector->ks_name.pstr = "*";
505 498 selector->ks_statistic.pstr = "*";
506 499
507 500 return (selector);
508 501 }
509 502
510 503 /*
511 504 * This function was taken from the perl kstat module code - please
512 505 * see for further comments there.
513 506 */
514 507 static kstat_raw_reader_t
515 508 lookup_raw_kstat_fn(char *module, char *name)
516 509 {
517 510 char key[KSTAT_STRLEN * 2];
518 511 register char *f, *t;
519 512 int n = 0;
520 513
521 514 for (f = module, t = key; *f != '\0'; f++, t++) {
522 515 while (*f != '\0' && isdigit(*f))
523 516 f++;
524 517 *t = *f;
525 518 }
526 519 *t++ = ':';
527 520
528 521 for (f = name; *f != '\0'; f++, t++) {
529 522 while (*f != '\0' && isdigit(*f))
530 523 f++;
531 524 *t = *f;
532 525 }
533 526 *t = '\0';
534 527
535 528 while (ks_raw_lookup[n].fn != NULL) {
536 529 if (strncmp(ks_raw_lookup[n].name, key, strlen(key)) == 0)
537 530 return (ks_raw_lookup[n].fn);
538 531 n++;
539 532 }
540 533
541 534 return (0);
542 535 }
543 536
544 537 /*
545 538 * Match a string against a shell glob or extended regular expression.
546 539 */
547 540 static boolean_t
548 541 ks_match(const char *str, ks_pattern_t *pattern)
549 542 {
550 543 int regcode;
551 544 char *regstr;
552 545 char *errbuf;
553 546 size_t bufsz;
554 547
555 548 if (pattern->pstr != NULL && gmatch(pattern->pstr, "/*/") != 0) {
556 549 /* All regex patterns are strdup'd copies */
557 550 regstr = pattern->pstr + 1;
558 551 *(strrchr(regstr, '/')) = '\0';
559 552
560 553 regcode = regcomp(&pattern->preg, regstr,
561 554 REG_EXTENDED | REG_NOSUB);
562 555 if (regcode != 0) {
563 556 bufsz = regerror(regcode, NULL, NULL, 0);
564 557 if (bufsz != 0) {
565 558 errbuf = malloc(bufsz);
566 559 if (errbuf == NULL) {
567 560 perror("malloc");
568 561 exit(3);
569 562 }
570 563 (void) regerror(regcode, NULL, errbuf, bufsz);
571 564 (void) fprintf(stderr, "kstat: %s\n", errbuf);
572 565 }
573 566 usage();
574 567 exit(2);
575 568 }
576 569
577 570 pattern->pstr = NULL;
578 571 }
579 572
580 573 if (pattern->pstr == NULL) {
581 574 return (regexec(&pattern->preg, str, 0, NULL, 0) == 0);
582 575 }
583 576
584 577 return ((gmatch(str, pattern->pstr) != 0));
585 578 }
586 579
587 580 /*
588 581 * Iterate over all kernel statistics and save matches.
589 582 */
590 583 static void
591 584 ks_instances_read(kstat_ctl_t *kc)
592 585 {
593 586 kstat_raw_reader_t save_raw = NULL;
594 587 kid_t id;
595 588 ks_selector_t *selector;
596 589 ks_instance_t *ksi;
597 590 ks_instance_t *tmp;
598 591 kstat_t *kp;
599 592 boolean_t skip;
600 593
601 594 for (kp = kc->kc_chain; kp != NULL; kp = kp->ks_next) {
602 595 /* Don't bother storing the kstat headers */
603 596 if (strncmp(kp->ks_name, "kstat_", 6) == 0) {
604 597 continue;
605 598 }
606 599
607 600 /* Don't bother storing raw stats we don't understand */
608 601 if (kp->ks_type == KSTAT_TYPE_RAW) {
609 602 save_raw = lookup_raw_kstat_fn(kp->ks_module,
610 603 kp->ks_name);
611 604 if (save_raw == NULL) {
612 605 #ifdef REPORT_UNKNOWN
613 606 (void) fprintf(stderr,
614 607 "Unknown kstat type %s:%d:%s - "
615 608 "%d of size %d\n", kp->ks_module,
616 609 kp->ks_instance, kp->ks_name,
617 610 kp->ks_ndata, kp->ks_data_size);
618 611 #endif
619 612 continue;
620 613 }
621 614 }
622 615
623 616 /*
624 617 * Iterate over the list of selectors and skip
625 618 * instances we dont want. We filter for statistics
626 619 * later, as we dont know them yet.
627 620 */
628 621 skip = B_TRUE;
629 622 selector = list_head(&selector_list);
630 623 while (selector != NULL) {
631 624 if (ks_match(kp->ks_module, &selector->ks_module) ||
632 625 ks_match(kp->ks_name, &selector->ks_name)) {
633 626 skip = B_FALSE;
634 627 break;
635 628 }
636 629 selector = list_next(&selector_list, selector);
637 630 }
638 631
639 632 if (skip) {
640 633 continue;
641 634 }
642 635
643 636 /*
644 637 * Allocate a new instance and fill in the values
645 638 * we know so far.
646 639 */
647 640 ksi = (ks_instance_t *)malloc(sizeof (ks_instance_t));
648 641 if (ksi == NULL) {
649 642 perror("malloc");
650 643 exit(3);
651 644 }
652 645
653 646 list_link_init(&ksi->ks_next);
654 647
655 648 (void) strlcpy(ksi->ks_module, kp->ks_module, KSTAT_STRLEN);
656 649 (void) strlcpy(ksi->ks_name, kp->ks_name, KSTAT_STRLEN);
657 650 (void) strlcpy(ksi->ks_class, kp->ks_class, KSTAT_STRLEN);
658 651
659 652 ksi->ks_instance = kp->ks_instance;
660 653 ksi->ks_snaptime = kp->ks_snaptime;
661 654 ksi->ks_type = kp->ks_type;
662 655
663 656 list_create(&ksi->ks_nvlist, sizeof (ks_nvpair_t),
664 657 offsetof(ks_nvpair_t, nv_next));
665 658
666 659 SAVE_HRTIME_X(ksi, "crtime", kp->ks_crtime);
667 660 SAVE_HRTIME_X(ksi, "snaptime", kp->ks_snaptime);
668 661 if (g_pflg) {
669 662 SAVE_STRING_X(ksi, "class", kp->ks_class);
670 663 }
671 664
672 665 /* Insert this instance into a sorted list */
673 666 tmp = list_head(&instances_list);
674 667 while (tmp != NULL && compare_instances(ksi, tmp) > 0)
675 668 tmp = list_next(&instances_list, tmp);
676 669
677 670 list_insert_before(&instances_list, tmp, ksi);
678 671
679 672 /* Read the actual statistics */
680 673 id = kstat_read(kc, kp, NULL);
681 674 if (id == -1) {
682 675 #ifdef REPORT_UNKNOWN
683 676 perror("kstat_read");
684 677 #endif
685 678 continue;
686 679 }
687 680
688 681 switch (kp->ks_type) {
689 682 case KSTAT_TYPE_RAW:
690 683 save_raw(kp, ksi);
691 684 break;
692 685 case KSTAT_TYPE_NAMED:
693 686 save_named(kp, ksi);
694 687 break;
695 688 case KSTAT_TYPE_INTR:
696 689 save_intr(kp, ksi);
697 690 break;
698 691 case KSTAT_TYPE_IO:
699 692 save_io(kp, ksi);
700 693 break;
701 694 case KSTAT_TYPE_TIMER:
702 695 save_timer(kp, ksi);
703 696 break;
704 697 default:
705 698 assert(B_FALSE); /* Invalid type */
706 699 break;
707 700 }
708 701 }
709 702 }
710 703
711 704 /*
712 705 * Print the value of a name-value pair.
713 706 */
714 707 static void
715 708 ks_value_print(ks_nvpair_t *nvpair)
716 709 {
717 710 switch (nvpair->data_type) {
718 711 case KSTAT_DATA_CHAR:
719 712 (void) fprintf(stdout, "%s", nvpair->value.c);
720 713 break;
721 714 case KSTAT_DATA_INT32:
722 715 (void) fprintf(stdout, "%d", nvpair->value.i32);
723 716 break;
724 717 case KSTAT_DATA_UINT32:
725 718 (void) fprintf(stdout, "%u", nvpair->value.ui32);
726 719 break;
727 720 case KSTAT_DATA_INT64:
728 721 (void) fprintf(stdout, "%lld", nvpair->value.i64);
729 722 break;
730 723 case KSTAT_DATA_UINT64:
731 724 (void) fprintf(stdout, "%llu", nvpair->value.ui64);
732 725 break;
733 726 case KSTAT_DATA_STRING:
734 727 (void) fprintf(stdout, "%s", KSTAT_NAMED_STR_PTR(nvpair));
735 728 break;
736 729 case KSTAT_DATA_HRTIME:
737 730 if (nvpair->value.ui64 == 0)
738 731 (void) fprintf(stdout, "0");
739 732 else
740 733 (void) fprintf(stdout, "%.9f",
741 734 nvpair->value.ui64 / 1000000000.0);
742 735 break;
743 736 default:
744 737 assert(B_FALSE);
745 738 }
746 739 }
747 740
748 741 /*
749 742 * Print a single instance.
750 743 */
751 744 static void
752 745 ks_instance_print(ks_instance_t *ksi, ks_nvpair_t *nvpair)
753 746 {
754 747 if (g_headerflg) {
755 748 if (!g_pflg) {
756 749 (void) fprintf(stdout, DFLT_FMT,
757 750 ksi->ks_module, ksi->ks_instance,
758 751 ksi->ks_name, ksi->ks_class);
759 752 }
760 753 g_headerflg = B_FALSE;
761 754 }
762 755
763 756 if (g_pflg) {
764 757 (void) fprintf(stdout, KS_PFMT,
765 758 ksi->ks_module, ksi->ks_instance,
766 759 ksi->ks_name, nvpair->name);
767 760 if (!g_lflg) {
768 761 (void) putchar(g_cflg ? ':': '\t');
769 762 ks_value_print(nvpair);
770 763 }
771 764 } else {
772 765 (void) fprintf(stdout, KS_DFMT, nvpair->name);
773 766 ks_value_print(nvpair);
774 767 }
775 768
776 769 (void) putchar('\n');
777 770 }
778 771
779 772 /*
780 773 * Print a single instance in JSON format.
781 774 */
782 775 static void
783 776 ks_instance_print_json(ks_instance_t *ksi, ks_nvpair_t *nvpair)
784 777 {
785 778 if (g_headerflg) {
786 779 (void) fprintf(stdout, JSON_FMT,
787 780 ksi->ks_module, ksi->ks_instance,
788 781 ksi->ks_name, ksi->ks_class,
789 782 ksi->ks_type);
790 783
791 784 if (ksi->ks_snaptime == 0)
792 785 (void) fprintf(stdout, "\t\"snaptime\": 0,\n");
793 786 else
794 787 (void) fprintf(stdout, "\t\"snaptime\": %.9f,\n",
795 788 ksi->ks_snaptime / 1000000000.0);
796 789
797 790 (void) fprintf(stdout, "\t\"data\": {\n");
798 791
799 792 g_headerflg = B_FALSE;
800 793 }
801 794
802 795 (void) fprintf(stdout, KS_JFMT, nvpair->name);
803 796 if (nvpair->data_type == KSTAT_DATA_STRING) {
804 797 (void) putchar('\"');
805 798 ks_value_print(nvpair);
806 799 (void) putchar('\"');
807 800 } else {
808 801 ks_value_print(nvpair);
809 802 }
810 803 if (nvpair != list_tail(&ksi->ks_nvlist))
811 804 (void) putchar(',');
812 805
813 806 (void) putchar('\n');
814 807 }
815 808
816 809 /*
817 810 * Print all instances.
818 811 */
819 812 static void
820 813 ks_instances_print(void)
821 814 {
822 815 ks_selector_t *selector;
823 816 ks_instance_t *ksi, *ktmp;
824 817 ks_nvpair_t *nvpair, *ntmp;
825 818 void (*ks_print_fn)(ks_instance_t *, ks_nvpair_t *);
826 819 char *ks_number;
827 820
828 821 if (g_timestamp_fmt != NODATE)
829 822 print_timestamp(g_timestamp_fmt);
830 823
831 824 if (g_jflg) {
832 825 ks_print_fn = &ks_instance_print_json;
833 826 (void) putchar('[');
834 827 } else {
835 828 ks_print_fn = &ks_instance_print;
836 829 }
837 830
838 831 /* Iterate over each selector */
839 832 selector = list_head(&selector_list);
840 833 while (selector != NULL) {
841 834
842 835 /* Iterate over each instance */
843 836 for (ksi = list_head(&instances_list); ksi != NULL;
844 837 ksi = list_next(&instances_list, ksi)) {
845 838
846 839 (void) asprintf(&ks_number, "%d", ksi->ks_instance);
847 840 if (!(ks_match(ksi->ks_module, &selector->ks_module) &&
848 841 ks_match(ksi->ks_name, &selector->ks_name) &&
849 842 ks_match(ks_number, &selector->ks_instance) &&
850 843 ks_match(ksi->ks_class, &g_ks_class))) {
851 844 free(ks_number);
852 845 continue;
853 846 }
854 847
855 848 free(ks_number);
856 849
857 850 /* Finally iterate over each statistic */
858 851 g_headerflg = B_TRUE;
859 852 for (nvpair = list_head(&ksi->ks_nvlist);
860 853 nvpair != NULL;
861 854 nvpair = list_next(&ksi->ks_nvlist, nvpair)) {
862 855 if (!ks_match(nvpair->name,
863 856 &selector->ks_statistic))
864 857 continue;
865 858
866 859 g_matched = 0;
867 860 if (!g_qflg)
868 861 (*ks_print_fn)(ksi, nvpair);
869 862 }
870 863
871 864 if (!g_headerflg) {
872 865 if (g_jflg) {
873 866 (void) fprintf(stdout, "\t}\n}");
874 867 if (ksi != list_tail(&instances_list))
875 868 (void) putchar(',');
876 869 } else if (!g_pflg) {
877 870 (void) putchar('\n');
878 871 }
879 872 }
880 873 }
881 874
882 875 selector = list_next(&selector_list, selector);
883 876 }
884 877
885 878 if (g_jflg)
886 879 (void) fprintf(stdout, "]\n");
887 880
888 881 (void) fflush(stdout);
889 882
890 883 /* Free the instances list */
891 884 ksi = list_head(&instances_list);
892 885 while (ksi != NULL) {
893 886 nvpair = list_head(&ksi->ks_nvlist);
894 887 while (nvpair != NULL) {
895 888 ntmp = nvpair;
896 889 nvpair = list_next(&ksi->ks_nvlist, nvpair);
897 890 list_remove(&ksi->ks_nvlist, ntmp);
898 891 if (ntmp->data_type == KSTAT_DATA_STRING)
899 892 free(ntmp->value.str.addr.ptr);
900 893 free(ntmp);
901 894 }
902 895
903 896 ktmp = ksi;
904 897 ksi = list_next(&instances_list, ksi);
905 898 list_remove(&instances_list, ktmp);
906 899 list_destroy(&ktmp->ks_nvlist);
907 900 free(ktmp);
908 901 }
909 902 }
910 903
911 904 static void
912 905 save_cpu_stat(kstat_t *kp, ks_instance_t *ksi)
913 906 {
914 907 cpu_stat_t *stat;
915 908 cpu_sysinfo_t *sysinfo;
916 909 cpu_syswait_t *syswait;
917 910 cpu_vminfo_t *vminfo;
918 911
919 912 stat = (cpu_stat_t *)(kp->ks_data);
920 913 sysinfo = &stat->cpu_sysinfo;
921 914 syswait = &stat->cpu_syswait;
922 915 vminfo = &stat->cpu_vminfo;
923 916
924 917 SAVE_UINT32_X(ksi, "idle", sysinfo->cpu[CPU_IDLE]);
925 918 SAVE_UINT32_X(ksi, "user", sysinfo->cpu[CPU_USER]);
926 919 SAVE_UINT32_X(ksi, "kernel", sysinfo->cpu[CPU_KERNEL]);
927 920 SAVE_UINT32_X(ksi, "wait", sysinfo->cpu[CPU_WAIT]);
928 921 SAVE_UINT32_X(ksi, "wait_io", sysinfo->cpu[W_IO]);
929 922 SAVE_UINT32_X(ksi, "wait_swap", sysinfo->cpu[W_SWAP]);
930 923 SAVE_UINT32_X(ksi, "wait_pio", sysinfo->cpu[W_PIO]);
931 924 SAVE_UINT32(ksi, sysinfo, bread);
932 925 SAVE_UINT32(ksi, sysinfo, bwrite);
933 926 SAVE_UINT32(ksi, sysinfo, lread);
934 927 SAVE_UINT32(ksi, sysinfo, lwrite);
935 928 SAVE_UINT32(ksi, sysinfo, phread);
936 929 SAVE_UINT32(ksi, sysinfo, phwrite);
937 930 SAVE_UINT32(ksi, sysinfo, pswitch);
938 931 SAVE_UINT32(ksi, sysinfo, trap);
939 932 SAVE_UINT32(ksi, sysinfo, intr);
940 933 SAVE_UINT32(ksi, sysinfo, syscall);
941 934 SAVE_UINT32(ksi, sysinfo, sysread);
942 935 SAVE_UINT32(ksi, sysinfo, syswrite);
943 936 SAVE_UINT32(ksi, sysinfo, sysfork);
944 937 SAVE_UINT32(ksi, sysinfo, sysvfork);
945 938 SAVE_UINT32(ksi, sysinfo, sysexec);
946 939 SAVE_UINT32(ksi, sysinfo, readch);
947 940 SAVE_UINT32(ksi, sysinfo, writech);
948 941 SAVE_UINT32(ksi, sysinfo, rcvint);
949 942 SAVE_UINT32(ksi, sysinfo, xmtint);
950 943 SAVE_UINT32(ksi, sysinfo, mdmint);
951 944 SAVE_UINT32(ksi, sysinfo, rawch);
952 945 SAVE_UINT32(ksi, sysinfo, canch);
953 946 SAVE_UINT32(ksi, sysinfo, outch);
954 947 SAVE_UINT32(ksi, sysinfo, msg);
955 948 SAVE_UINT32(ksi, sysinfo, sema);
956 949 SAVE_UINT32(ksi, sysinfo, namei);
957 950 SAVE_UINT32(ksi, sysinfo, ufsiget);
958 951 SAVE_UINT32(ksi, sysinfo, ufsdirblk);
959 952 SAVE_UINT32(ksi, sysinfo, ufsipage);
960 953 SAVE_UINT32(ksi, sysinfo, ufsinopage);
961 954 SAVE_UINT32(ksi, sysinfo, inodeovf);
962 955 SAVE_UINT32(ksi, sysinfo, fileovf);
963 956 SAVE_UINT32(ksi, sysinfo, procovf);
964 957 SAVE_UINT32(ksi, sysinfo, intrthread);
965 958 SAVE_UINT32(ksi, sysinfo, intrblk);
966 959 SAVE_UINT32(ksi, sysinfo, idlethread);
967 960 SAVE_UINT32(ksi, sysinfo, inv_swtch);
968 961 SAVE_UINT32(ksi, sysinfo, nthreads);
969 962 SAVE_UINT32(ksi, sysinfo, cpumigrate);
970 963 SAVE_UINT32(ksi, sysinfo, xcalls);
971 964 SAVE_UINT32(ksi, sysinfo, mutex_adenters);
972 965 SAVE_UINT32(ksi, sysinfo, rw_rdfails);
973 966 SAVE_UINT32(ksi, sysinfo, rw_wrfails);
974 967 SAVE_UINT32(ksi, sysinfo, modload);
975 968 SAVE_UINT32(ksi, sysinfo, modunload);
976 969 SAVE_UINT32(ksi, sysinfo, bawrite);
977 970 #ifdef STATISTICS /* see header file */
978 971 SAVE_UINT32(ksi, sysinfo, rw_enters);
979 972 SAVE_UINT32(ksi, sysinfo, win_uo_cnt);
980 973 SAVE_UINT32(ksi, sysinfo, win_uu_cnt);
981 974 SAVE_UINT32(ksi, sysinfo, win_so_cnt);
982 975 SAVE_UINT32(ksi, sysinfo, win_su_cnt);
983 976 SAVE_UINT32(ksi, sysinfo, win_suo_cnt);
984 977 #endif
985 978
986 979 SAVE_INT32(ksi, syswait, iowait);
987 980 SAVE_INT32(ksi, syswait, swap);
988 981 SAVE_INT32(ksi, syswait, physio);
989 982
990 983 SAVE_UINT32(ksi, vminfo, pgrec);
991 984 SAVE_UINT32(ksi, vminfo, pgfrec);
992 985 SAVE_UINT32(ksi, vminfo, pgin);
993 986 SAVE_UINT32(ksi, vminfo, pgpgin);
994 987 SAVE_UINT32(ksi, vminfo, pgout);
995 988 SAVE_UINT32(ksi, vminfo, pgpgout);
996 989 SAVE_UINT32(ksi, vminfo, swapin);
997 990 SAVE_UINT32(ksi, vminfo, pgswapin);
998 991 SAVE_UINT32(ksi, vminfo, swapout);
999 992 SAVE_UINT32(ksi, vminfo, pgswapout);
1000 993 SAVE_UINT32(ksi, vminfo, zfod);
1001 994 SAVE_UINT32(ksi, vminfo, dfree);
1002 995 SAVE_UINT32(ksi, vminfo, scan);
1003 996 SAVE_UINT32(ksi, vminfo, rev);
1004 997 SAVE_UINT32(ksi, vminfo, hat_fault);
1005 998 SAVE_UINT32(ksi, vminfo, as_fault);
1006 999 SAVE_UINT32(ksi, vminfo, maj_fault);
1007 1000 SAVE_UINT32(ksi, vminfo, cow_fault);
1008 1001 SAVE_UINT32(ksi, vminfo, prot_fault);
1009 1002 SAVE_UINT32(ksi, vminfo, softlock);
1010 1003 SAVE_UINT32(ksi, vminfo, kernel_asflt);
1011 1004 SAVE_UINT32(ksi, vminfo, pgrrun);
1012 1005 SAVE_UINT32(ksi, vminfo, execpgin);
1013 1006 SAVE_UINT32(ksi, vminfo, execpgout);
1014 1007 SAVE_UINT32(ksi, vminfo, execfree);
1015 1008 SAVE_UINT32(ksi, vminfo, anonpgin);
1016 1009 SAVE_UINT32(ksi, vminfo, anonpgout);
1017 1010 SAVE_UINT32(ksi, vminfo, anonfree);
1018 1011 SAVE_UINT32(ksi, vminfo, fspgin);
1019 1012 SAVE_UINT32(ksi, vminfo, fspgout);
1020 1013 SAVE_UINT32(ksi, vminfo, fsfree);
1021 1014 }
1022 1015
1023 1016 static void
1024 1017 save_var(kstat_t *kp, ks_instance_t *ksi)
1025 1018 {
1026 1019 struct var *var = (struct var *)(kp->ks_data);
1027 1020
1028 1021 assert(kp->ks_data_size == sizeof (struct var));
1029 1022
1030 1023 SAVE_INT32(ksi, var, v_buf);
1031 1024 SAVE_INT32(ksi, var, v_call);
1032 1025 SAVE_INT32(ksi, var, v_proc);
1033 1026 SAVE_INT32(ksi, var, v_maxupttl);
1034 1027 SAVE_INT32(ksi, var, v_nglobpris);
1035 1028 SAVE_INT32(ksi, var, v_maxsyspri);
1036 1029 SAVE_INT32(ksi, var, v_clist);
1037 1030 SAVE_INT32(ksi, var, v_maxup);
1038 1031 SAVE_INT32(ksi, var, v_hbuf);
1039 1032 SAVE_INT32(ksi, var, v_hmask);
1040 1033 SAVE_INT32(ksi, var, v_pbuf);
1041 1034 SAVE_INT32(ksi, var, v_sptmap);
1042 1035 SAVE_INT32(ksi, var, v_maxpmem);
1043 1036 SAVE_INT32(ksi, var, v_autoup);
1044 1037 SAVE_INT32(ksi, var, v_bufhwm);
1045 1038 }
1046 1039
1047 1040 static void
1048 1041 save_ncstats(kstat_t *kp, ks_instance_t *ksi)
1049 1042 {
1050 1043 struct ncstats *ncstats = (struct ncstats *)(kp->ks_data);
1051 1044
1052 1045 assert(kp->ks_data_size == sizeof (struct ncstats));
1053 1046
1054 1047 SAVE_INT32(ksi, ncstats, hits);
1055 1048 SAVE_INT32(ksi, ncstats, misses);
1056 1049 SAVE_INT32(ksi, ncstats, enters);
1057 1050 SAVE_INT32(ksi, ncstats, dbl_enters);
1058 1051 SAVE_INT32(ksi, ncstats, long_enter);
1059 1052 SAVE_INT32(ksi, ncstats, long_look);
1060 1053 SAVE_INT32(ksi, ncstats, move_to_front);
1061 1054 SAVE_INT32(ksi, ncstats, purges);
1062 1055 }
1063 1056
1064 1057 static void
1065 1058 save_sysinfo(kstat_t *kp, ks_instance_t *ksi)
1066 1059 {
1067 1060 sysinfo_t *sysinfo = (sysinfo_t *)(kp->ks_data);
1068 1061
1069 1062 assert(kp->ks_data_size == sizeof (sysinfo_t));
1070 1063
1071 1064 SAVE_UINT32(ksi, sysinfo, updates);
1072 1065 SAVE_UINT32(ksi, sysinfo, runque);
1073 1066 SAVE_UINT32(ksi, sysinfo, runocc);
1074 1067 SAVE_UINT32(ksi, sysinfo, swpque);
1075 1068 SAVE_UINT32(ksi, sysinfo, swpocc);
1076 1069 SAVE_UINT32(ksi, sysinfo, waiting);
1077 1070 }
1078 1071
1079 1072 static void
1080 1073 save_vminfo(kstat_t *kp, ks_instance_t *ksi)
1081 1074 {
1082 1075 vminfo_t *vminfo = (vminfo_t *)(kp->ks_data);
1083 1076
1084 1077 assert(kp->ks_data_size == sizeof (vminfo_t));
1085 1078
1086 1079 SAVE_UINT64(ksi, vminfo, freemem);
1087 1080 SAVE_UINT64(ksi, vminfo, swap_resv);
1088 1081 SAVE_UINT64(ksi, vminfo, swap_alloc);
1089 1082 SAVE_UINT64(ksi, vminfo, swap_avail);
1090 1083 SAVE_UINT64(ksi, vminfo, swap_free);
1091 1084 SAVE_UINT64(ksi, vminfo, updates);
1092 1085 }
1093 1086
1094 1087 static void
1095 1088 save_nfs(kstat_t *kp, ks_instance_t *ksi)
1096 1089 {
1097 1090 struct mntinfo_kstat *mntinfo = (struct mntinfo_kstat *)(kp->ks_data);
1098 1091
1099 1092 assert(kp->ks_data_size == sizeof (struct mntinfo_kstat));
1100 1093
1101 1094 SAVE_STRING(ksi, mntinfo, mik_proto);
1102 1095 SAVE_UINT32(ksi, mntinfo, mik_vers);
1103 1096 SAVE_UINT32(ksi, mntinfo, mik_flags);
1104 1097 SAVE_UINT32(ksi, mntinfo, mik_secmod);
1105 1098 SAVE_UINT32(ksi, mntinfo, mik_curread);
1106 1099 SAVE_UINT32(ksi, mntinfo, mik_curwrite);
1107 1100 SAVE_INT32(ksi, mntinfo, mik_timeo);
1108 1101 SAVE_INT32(ksi, mntinfo, mik_retrans);
1109 1102 SAVE_UINT32(ksi, mntinfo, mik_acregmin);
1110 1103 SAVE_UINT32(ksi, mntinfo, mik_acregmax);
1111 1104 SAVE_UINT32(ksi, mntinfo, mik_acdirmin);
1112 1105 SAVE_UINT32(ksi, mntinfo, mik_acdirmax);
1113 1106 SAVE_UINT32_X(ksi, "lookup_srtt", mntinfo->mik_timers[0].srtt);
1114 1107 SAVE_UINT32_X(ksi, "lookup_deviate", mntinfo->mik_timers[0].deviate);
1115 1108 SAVE_UINT32_X(ksi, "lookup_rtxcur", mntinfo->mik_timers[0].rtxcur);
1116 1109 SAVE_UINT32_X(ksi, "read_srtt", mntinfo->mik_timers[1].srtt);
1117 1110 SAVE_UINT32_X(ksi, "read_deviate", mntinfo->mik_timers[1].deviate);
1118 1111 SAVE_UINT32_X(ksi, "read_rtxcur", mntinfo->mik_timers[1].rtxcur);
1119 1112 SAVE_UINT32_X(ksi, "write_srtt", mntinfo->mik_timers[2].srtt);
1120 1113 SAVE_UINT32_X(ksi, "write_deviate", mntinfo->mik_timers[2].deviate);
1121 1114 SAVE_UINT32_X(ksi, "write_rtxcur", mntinfo->mik_timers[2].rtxcur);
1122 1115 SAVE_UINT32(ksi, mntinfo, mik_noresponse);
1123 1116 SAVE_UINT32(ksi, mntinfo, mik_failover);
1124 1117 SAVE_UINT32(ksi, mntinfo, mik_remap);
1125 1118 SAVE_STRING(ksi, mntinfo, mik_curserver);
1126 1119 }
1127 1120
1128 1121 #ifdef __sparc
1129 1122 static void
1130 1123 save_sfmmu_global_stat(kstat_t *kp, ks_instance_t *ksi)
1131 1124 {
1132 1125 struct sfmmu_global_stat *sfmmug =
1133 1126 (struct sfmmu_global_stat *)(kp->ks_data);
1134 1127
1135 1128 assert(kp->ks_data_size == sizeof (struct sfmmu_global_stat));
1136 1129
1137 1130 SAVE_INT32(ksi, sfmmug, sf_tsb_exceptions);
1138 1131 SAVE_INT32(ksi, sfmmug, sf_tsb_raise_exception);
1139 1132 SAVE_INT32(ksi, sfmmug, sf_pagefaults);
1140 1133 SAVE_INT32(ksi, sfmmug, sf_uhash_searches);
1141 1134 SAVE_INT32(ksi, sfmmug, sf_uhash_links);
1142 1135 SAVE_INT32(ksi, sfmmug, sf_khash_searches);
1143 1136 SAVE_INT32(ksi, sfmmug, sf_khash_links);
1144 1137 SAVE_INT32(ksi, sfmmug, sf_swapout);
1145 1138 SAVE_INT32(ksi, sfmmug, sf_tsb_alloc);
1146 1139 SAVE_INT32(ksi, sfmmug, sf_tsb_allocfail);
1147 1140 SAVE_INT32(ksi, sfmmug, sf_tsb_sectsb_create);
1148 1141 SAVE_INT32(ksi, sfmmug, sf_scd_1sttsb_alloc);
1149 1142 SAVE_INT32(ksi, sfmmug, sf_scd_2ndtsb_alloc);
1150 1143 SAVE_INT32(ksi, sfmmug, sf_scd_1sttsb_allocfail);
1151 1144 SAVE_INT32(ksi, sfmmug, sf_scd_2ndtsb_allocfail);
1152 1145 SAVE_INT32(ksi, sfmmug, sf_tteload8k);
1153 1146 SAVE_INT32(ksi, sfmmug, sf_tteload64k);
1154 1147 SAVE_INT32(ksi, sfmmug, sf_tteload512k);
1155 1148 SAVE_INT32(ksi, sfmmug, sf_tteload4m);
1156 1149 SAVE_INT32(ksi, sfmmug, sf_tteload32m);
1157 1150 SAVE_INT32(ksi, sfmmug, sf_tteload256m);
1158 1151 SAVE_INT32(ksi, sfmmug, sf_tsb_load8k);
1159 1152 SAVE_INT32(ksi, sfmmug, sf_tsb_load4m);
1160 1153 SAVE_INT32(ksi, sfmmug, sf_hblk_hit);
1161 1154 SAVE_INT32(ksi, sfmmug, sf_hblk8_ncreate);
1162 1155 SAVE_INT32(ksi, sfmmug, sf_hblk8_nalloc);
1163 1156 SAVE_INT32(ksi, sfmmug, sf_hblk1_ncreate);
1164 1157 SAVE_INT32(ksi, sfmmug, sf_hblk1_nalloc);
1165 1158 SAVE_INT32(ksi, sfmmug, sf_hblk_slab_cnt);
1166 1159 SAVE_INT32(ksi, sfmmug, sf_hblk_reserve_cnt);
1167 1160 SAVE_INT32(ksi, sfmmug, sf_hblk_recurse_cnt);
1168 1161 SAVE_INT32(ksi, sfmmug, sf_hblk_reserve_hit);
1169 1162 SAVE_INT32(ksi, sfmmug, sf_get_free_success);
1170 1163 SAVE_INT32(ksi, sfmmug, sf_get_free_throttle);
1171 1164 SAVE_INT32(ksi, sfmmug, sf_get_free_fail);
1172 1165 SAVE_INT32(ksi, sfmmug, sf_put_free_success);
1173 1166 SAVE_INT32(ksi, sfmmug, sf_put_free_fail);
1174 1167 SAVE_INT32(ksi, sfmmug, sf_pgcolor_conflict);
1175 1168 SAVE_INT32(ksi, sfmmug, sf_uncache_conflict);
1176 1169 SAVE_INT32(ksi, sfmmug, sf_unload_conflict);
1177 1170 SAVE_INT32(ksi, sfmmug, sf_ism_uncache);
1178 1171 SAVE_INT32(ksi, sfmmug, sf_ism_recache);
1179 1172 SAVE_INT32(ksi, sfmmug, sf_recache);
1180 1173 SAVE_INT32(ksi, sfmmug, sf_steal_count);
1181 1174 SAVE_INT32(ksi, sfmmug, sf_pagesync);
1182 1175 SAVE_INT32(ksi, sfmmug, sf_clrwrt);
1183 1176 SAVE_INT32(ksi, sfmmug, sf_pagesync_invalid);
1184 1177 SAVE_INT32(ksi, sfmmug, sf_kernel_xcalls);
1185 1178 SAVE_INT32(ksi, sfmmug, sf_user_xcalls);
1186 1179 SAVE_INT32(ksi, sfmmug, sf_tsb_grow);
1187 1180 SAVE_INT32(ksi, sfmmug, sf_tsb_shrink);
1188 1181 SAVE_INT32(ksi, sfmmug, sf_tsb_resize_failures);
1189 1182 SAVE_INT32(ksi, sfmmug, sf_tsb_reloc);
1190 1183 SAVE_INT32(ksi, sfmmug, sf_user_vtop);
1191 1184 SAVE_INT32(ksi, sfmmug, sf_ctx_inv);
1192 1185 SAVE_INT32(ksi, sfmmug, sf_tlb_reprog_pgsz);
1193 1186 SAVE_INT32(ksi, sfmmug, sf_region_remap_demap);
1194 1187 SAVE_INT32(ksi, sfmmug, sf_create_scd);
1195 1188 SAVE_INT32(ksi, sfmmug, sf_join_scd);
1196 1189 SAVE_INT32(ksi, sfmmug, sf_leave_scd);
1197 1190 SAVE_INT32(ksi, sfmmug, sf_destroy_scd);
1198 1191 }
1199 1192 #endif
1200 1193
1201 1194 #ifdef __sparc
1202 1195 static void
1203 1196 save_sfmmu_tsbsize_stat(kstat_t *kp, ks_instance_t *ksi)
1204 1197 {
1205 1198 struct sfmmu_tsbsize_stat *sfmmut;
1206 1199
1207 1200 assert(kp->ks_data_size == sizeof (struct sfmmu_tsbsize_stat));
1208 1201 sfmmut = (struct sfmmu_tsbsize_stat *)(kp->ks_data);
1209 1202
1210 1203 SAVE_INT32(ksi, sfmmut, sf_tsbsz_8k);
1211 1204 SAVE_INT32(ksi, sfmmut, sf_tsbsz_16k);
1212 1205 SAVE_INT32(ksi, sfmmut, sf_tsbsz_32k);
1213 1206 SAVE_INT32(ksi, sfmmut, sf_tsbsz_64k);
1214 1207 SAVE_INT32(ksi, sfmmut, sf_tsbsz_128k);
1215 1208 SAVE_INT32(ksi, sfmmut, sf_tsbsz_256k);
1216 1209 SAVE_INT32(ksi, sfmmut, sf_tsbsz_512k);
1217 1210 SAVE_INT32(ksi, sfmmut, sf_tsbsz_1m);
1218 1211 SAVE_INT32(ksi, sfmmut, sf_tsbsz_2m);
1219 1212 SAVE_INT32(ksi, sfmmut, sf_tsbsz_4m);
1220 1213 }
1221 1214 #endif
1222 1215
1223 1216 #ifdef __sparc
1224 1217 static void
1225 1218 save_simmstat(kstat_t *kp, ks_instance_t *ksi)
1226 1219 {
1227 1220 uchar_t *simmstat;
1228 1221 char *simm_buf;
1229 1222 char *list = NULL;
1230 1223 int i;
1231 1224
1232 1225 assert(kp->ks_data_size == sizeof (uchar_t) * SIMM_COUNT);
1233 1226
1234 1227 for (i = 0, simmstat = (uchar_t *)(kp->ks_data); i < SIMM_COUNT - 1;
1235 1228 i++, simmstat++) {
1236 1229 if (list == NULL) {
1237 1230 (void) asprintf(&simm_buf, "%d,", *simmstat);
1238 1231 } else {
1239 1232 (void) asprintf(&simm_buf, "%s%d,", list, *simmstat);
1240 1233 free(list);
1241 1234 }
1242 1235 list = simm_buf;
1243 1236 }
1244 1237
1245 1238 (void) asprintf(&simm_buf, "%s%d", list, *simmstat);
1246 1239 SAVE_STRING_X(ksi, "status", simm_buf);
1247 1240 free(list);
1248 1241 free(simm_buf);
1249 1242 }
1250 1243 #endif
1251 1244
1252 1245 #ifdef __sparc
1253 1246 /*
1254 1247 * Helper function for save_temperature().
1255 1248 */
1256 1249 static char *
1257 1250 short_array_to_string(short *shortp, int len)
1258 1251 {
1259 1252 char *list = NULL;
1260 1253 char *list_buf;
1261 1254
1262 1255 for (; len > 1; len--, shortp++) {
1263 1256 if (list == NULL) {
1264 1257 (void) asprintf(&list_buf, "%hd,", *shortp);
1265 1258 } else {
1266 1259 (void) asprintf(&list_buf, "%s%hd,", list, *shortp);
1267 1260 free(list);
1268 1261 }
1269 1262 list = list_buf;
1270 1263 }
1271 1264
1272 1265 (void) asprintf(&list_buf, "%s%hd", list, *shortp);
1273 1266 free(list);
1274 1267 return (list_buf);
1275 1268 }
1276 1269
1277 1270 static void
1278 1271 save_temperature(kstat_t *kp, ks_instance_t *ksi)
1279 1272 {
1280 1273 struct temp_stats *temps = (struct temp_stats *)(kp->ks_data);
1281 1274 char *buf;
1282 1275
1283 1276 assert(kp->ks_data_size == sizeof (struct temp_stats));
1284 1277
1285 1278 SAVE_UINT32(ksi, temps, index);
1286 1279
1287 1280 buf = short_array_to_string(temps->l1, L1_SZ);
1288 1281 SAVE_STRING_X(ksi, "l1", buf);
1289 1282 free(buf);
1290 1283
1291 1284 buf = short_array_to_string(temps->l2, L2_SZ);
1292 1285 SAVE_STRING_X(ksi, "l2", buf);
1293 1286 free(buf);
1294 1287
1295 1288 buf = short_array_to_string(temps->l3, L3_SZ);
1296 1289 SAVE_STRING_X(ksi, "l3", buf);
1297 1290 free(buf);
1298 1291
1299 1292 buf = short_array_to_string(temps->l4, L4_SZ);
1300 1293 SAVE_STRING_X(ksi, "l4", buf);
1301 1294 free(buf);
1302 1295
1303 1296 buf = short_array_to_string(temps->l5, L5_SZ);
1304 1297 SAVE_STRING_X(ksi, "l5", buf);
1305 1298 free(buf);
1306 1299
1307 1300 SAVE_INT32(ksi, temps, max);
1308 1301 SAVE_INT32(ksi, temps, min);
1309 1302 SAVE_INT32(ksi, temps, state);
1310 1303 SAVE_INT32(ksi, temps, temp_cnt);
1311 1304 SAVE_INT32(ksi, temps, shutdown_cnt);
1312 1305 SAVE_INT32(ksi, temps, version);
1313 1306 SAVE_INT32(ksi, temps, trend);
1314 1307 SAVE_INT32(ksi, temps, override);
1315 1308 }
1316 1309 #endif
1317 1310
1318 1311 #ifdef __sparc
1319 1312 static void
1320 1313 save_temp_over(kstat_t *kp, ks_instance_t *ksi)
1321 1314 {
1322 1315 short *sh = (short *)(kp->ks_data);
1323 1316 char *value;
1324 1317
1325 1318 assert(kp->ks_data_size == sizeof (short));
1326 1319
1327 1320 (void) asprintf(&value, "%hu", *sh);
1328 1321 SAVE_STRING_X(ksi, "override", value);
1329 1322 free(value);
1330 1323 }
1331 1324 #endif
1332 1325
1333 1326 #ifdef __sparc
1334 1327 static void
1335 1328 save_ps_shadow(kstat_t *kp, ks_instance_t *ksi)
1336 1329 {
1337 1330 uchar_t *uchar = (uchar_t *)(kp->ks_data);
1338 1331
1339 1332 assert(kp->ks_data_size == SYS_PS_COUNT);
1340 1333
1341 1334 SAVE_CHAR_X(ksi, "core_0", *uchar++);
1342 1335 SAVE_CHAR_X(ksi, "core_1", *uchar++);
1343 1336 SAVE_CHAR_X(ksi, "core_2", *uchar++);
1344 1337 SAVE_CHAR_X(ksi, "core_3", *uchar++);
1345 1338 SAVE_CHAR_X(ksi, "core_4", *uchar++);
1346 1339 SAVE_CHAR_X(ksi, "core_5", *uchar++);
1347 1340 SAVE_CHAR_X(ksi, "core_6", *uchar++);
1348 1341 SAVE_CHAR_X(ksi, "core_7", *uchar++);
1349 1342 SAVE_CHAR_X(ksi, "pps_0", *uchar++);
1350 1343 SAVE_CHAR_X(ksi, "clk_33", *uchar++);
1351 1344 SAVE_CHAR_X(ksi, "clk_50", *uchar++);
1352 1345 SAVE_CHAR_X(ksi, "v5_p", *uchar++);
1353 1346 SAVE_CHAR_X(ksi, "v12_p", *uchar++);
1354 1347 SAVE_CHAR_X(ksi, "v5_aux", *uchar++);
1355 1348 SAVE_CHAR_X(ksi, "v5_p_pch", *uchar++);
1356 1349 SAVE_CHAR_X(ksi, "v12_p_pch", *uchar++);
1357 1350 SAVE_CHAR_X(ksi, "v3_pch", *uchar++);
1358 1351 SAVE_CHAR_X(ksi, "v5_pch", *uchar++);
1359 1352 SAVE_CHAR_X(ksi, "p_fan", *uchar++);
1360 1353 }
1361 1354 #endif
1362 1355
1363 1356 #ifdef __sparc
1364 1357 static void
1365 1358 save_fault_list(kstat_t *kp, ks_instance_t *ksi)
1366 1359 {
1367 1360 struct ft_list *fault;
1368 1361 char name[KSTAT_STRLEN + 7];
1369 1362 int i;
1370 1363
1371 1364 for (i = 1, fault = (struct ft_list *)(kp->ks_data);
1372 1365 i <= 999999 && i <= kp->ks_data_size / sizeof (struct ft_list);
1373 1366 i++, fault++) {
1374 1367 (void) snprintf(name, sizeof (name), "unit_%d", i);
1375 1368 SAVE_INT32_X(ksi, name, fault->unit);
1376 1369 (void) snprintf(name, sizeof (name), "type_%d", i);
1377 1370 SAVE_INT32_X(ksi, name, fault->type);
1378 1371 (void) snprintf(name, sizeof (name), "fclass_%d", i);
1379 1372 SAVE_INT32_X(ksi, name, fault->fclass);
1380 1373 (void) snprintf(name, sizeof (name), "create_time_%d", i);
1381 1374 SAVE_HRTIME_X(ksi, name, fault->create_time);
1382 1375 (void) snprintf(name, sizeof (name), "msg_%d", i);
1383 1376 SAVE_STRING_X(ksi, name, fault->msg);
1384 1377 }
1385 1378 }
1386 1379 #endif
1387 1380
1388 1381 static void
1389 1382 save_named(kstat_t *kp, ks_instance_t *ksi)
1390 1383 {
1391 1384 kstat_named_t *knp;
1392 1385 int n;
1393 1386
1394 1387 for (n = kp->ks_ndata, knp = KSTAT_NAMED_PTR(kp); n > 0; n--, knp++) {
1395 1388 switch (knp->data_type) {
1396 1389 case KSTAT_DATA_CHAR:
1397 1390 nvpair_insert(ksi, knp->name,
1398 1391 (ks_value_t *)&knp->value, KSTAT_DATA_CHAR);
1399 1392 break;
1400 1393 case KSTAT_DATA_INT32:
1401 1394 nvpair_insert(ksi, knp->name,
1402 1395 (ks_value_t *)&knp->value, KSTAT_DATA_INT32);
1403 1396 break;
1404 1397 case KSTAT_DATA_UINT32:
1405 1398 nvpair_insert(ksi, knp->name,
1406 1399 (ks_value_t *)&knp->value, KSTAT_DATA_UINT32);
1407 1400 break;
1408 1401 case KSTAT_DATA_INT64:
1409 1402 nvpair_insert(ksi, knp->name,
1410 1403 (ks_value_t *)&knp->value, KSTAT_DATA_INT64);
1411 1404 break;
1412 1405 case KSTAT_DATA_UINT64:
1413 1406 nvpair_insert(ksi, knp->name,
1414 1407 (ks_value_t *)&knp->value, KSTAT_DATA_UINT64);
1415 1408 break;
1416 1409 case KSTAT_DATA_STRING:
1417 1410 SAVE_STRING_X(ksi, knp->name, KSTAT_NAMED_STR_PTR(knp));
1418 1411 break;
1419 1412 default:
1420 1413 assert(B_FALSE); /* Invalid data type */
1421 1414 break;
1422 1415 }
1423 1416 }
1424 1417 }
1425 1418
1426 1419 static void
1427 1420 save_intr(kstat_t *kp, ks_instance_t *ksi)
1428 1421 {
1429 1422 kstat_intr_t *intr = KSTAT_INTR_PTR(kp);
1430 1423 char *intr_names[] = {"hard", "soft", "watchdog", "spurious",
1431 1424 "multiple_service"};
1432 1425 int n;
1433 1426
1434 1427 for (n = 0; n < KSTAT_NUM_INTRS; n++)
1435 1428 SAVE_UINT32_X(ksi, intr_names[n], intr->intrs[n]);
1436 1429 }
1437 1430
1438 1431 static void
1439 1432 save_io(kstat_t *kp, ks_instance_t *ksi)
1440 1433 {
1441 1434 kstat_io_t *ksio = KSTAT_IO_PTR(kp);
1442 1435
1443 1436 SAVE_UINT64(ksi, ksio, nread);
1444 1437 SAVE_UINT64(ksi, ksio, nwritten);
1445 1438 SAVE_UINT32(ksi, ksio, reads);
1446 1439 SAVE_UINT32(ksi, ksio, writes);
1447 1440 SAVE_HRTIME(ksi, ksio, wtime);
1448 1441 SAVE_HRTIME(ksi, ksio, wlentime);
1449 1442 SAVE_HRTIME(ksi, ksio, wlastupdate);
1450 1443 SAVE_HRTIME(ksi, ksio, rtime);
1451 1444 SAVE_HRTIME(ksi, ksio, rlentime);
1452 1445 SAVE_HRTIME(ksi, ksio, rlastupdate);
1453 1446 SAVE_UINT32(ksi, ksio, wcnt);
1454 1447 SAVE_UINT32(ksi, ksio, rcnt);
1455 1448 }
1456 1449
1457 1450 static void
1458 1451 save_timer(kstat_t *kp, ks_instance_t *ksi)
1459 1452 {
1460 1453 kstat_timer_t *ktimer = KSTAT_TIMER_PTR(kp);
1461 1454
1462 1455 SAVE_STRING(ksi, ktimer, name);
1463 1456 SAVE_UINT64(ksi, ktimer, num_events);
1464 1457 SAVE_HRTIME(ksi, ktimer, elapsed_time);
1465 1458 SAVE_HRTIME(ksi, ktimer, min_time);
1466 1459 SAVE_HRTIME(ksi, ktimer, max_time);
1467 1460 SAVE_HRTIME(ksi, ktimer, start_time);
1468 1461 SAVE_HRTIME(ksi, ktimer, stop_time);
1469 1462 }
↓ open down ↓ |
1094 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX