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 /* 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 #include <alloca.h> 27 #include <assert.h> 28 #include <errno.h> 29 #include <langinfo.h> 30 #include <libintl.h> 31 #include <libscf.h> 32 #include <signal.h> 33 #include <stdarg.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <strings.h> 37 #include <sys/fxpriocntl.h> 38 #include <sys/priocntl.h> 39 #include <sys/types.h> 40 #include <time.h> 41 #include <unistd.h> 42 #include <zonestat.h> 43 44 extern char *optarg; 45 extern int optind, opterr, optopt; 46 47 #define ZSTAT_OK 0 48 #define ZSTAT_ERROR 1 49 #define ZSTAT_USAGE 2 50 51 #define ZSTAT_UNIX_TIMESTAMP 1 52 #define ZSTAT_ISO_TIMESTAMP 2 53 #define ZSTAT_DATE_TIMESTAMP 3 54 55 #define ZSTAT_RES_PHYSICAL_MEMORY 0x1 56 #define ZSTAT_RES_VIRTUAL_MEMORY 0x2 57 #define ZSTAT_RES_LOCKED_MEMORY 0x4 58 #define ZSTAT_RES_MEMORY 0x7 59 60 #define ZSTAT_RES_DEFAULT_PSET 0x10 61 #define ZSTAT_RES_PSETS 0x20 62 #define ZSTAT_RES_SUMMARY 0x40 63 64 #define ZSTAT_RES_PROCESSES 0x100 65 #define ZSTAT_RES_LWPS 0x200 66 #define ZSTAT_RES_LOFI 0x400 67 #define ZSTAT_RES_LIMITS 0x700 68 69 #define ZSTAT_RES_SHM_MEMORY 0x1000 70 #define ZSTAT_RES_SHM_IDS 0x2000 71 #define ZSTAT_RES_SEM_IDS 0x4000 72 #define ZSTAT_RES_MSG_IDS 0x8000 73 #define ZSTAT_RES_SYSV 0xF000 74 75 #define ZSTAT_RES_ALL 0xF777 76 77 #define ZONESTAT_PHYSICAL_MEMORY "physical-memory" 78 #define ZONESTAT_VIRTUAL_MEMORY "virtual-memory" 79 #define ZONESTAT_LOCKED_MEMORY "locked-memory" 80 #define ZONESTAT_MEMORY "memory" 81 82 #define ZONESTAT_DEFAULT_PSET "default-pset" 83 #define ZONESTAT_POOL_PSET "pool-pset" 84 #define ZONESTAT_PSRSET_PSET "psrset-pset" 85 #define ZONESTAT_DEDICATED_CPU "dedicated-cpu" 86 #define ZONESTAT_PROCESSOR_SET "processor-set" 87 #define ZONESTAT_PSETS "psets" 88 #define ZONESTAT_SUMMARY "summary" 89 90 #define ZONESTAT_PROCESSES "processes" 91 #define ZONESTAT_LWPS "lwps" 92 #define ZONESTAT_LOFI "lofi" 93 #define ZONESTAT_LIMITS "limits" 94 95 #define ZONESTAT_SHM_MEMORY "shm-memory" 96 #define ZONESTAT_SHM_IDS "shm-ids" 97 #define ZONESTAT_SEM_IDS "sem-ids" 98 #define ZONESTAT_MSG_IDS "msg-ids" 99 #define ZONESTAT_SYSV "sysv" 100 101 #define ZONESTAT_ALL "all" 102 103 #define ZONESTAT_NAME_MEM_DEFAULT "mem_default" 104 #define ZONESTAT_NAME_VM_DEFAULT "vm_default" 105 106 #define ZONESTAT_NAME_AVERAGE "average" 107 #define ZONESTAT_NAME_HIGH "high" 108 109 #define ZONESTAT_NAME_RESOURCE "resource" 110 #define ZONESTAT_NAME_TOTAL "total" 111 #define ZONESTAT_NAME_SYSTEM "system" 112 #define ZONESTAT_NAME_ZONES "zones" 113 #define ZONESTAT_NAME_HEADER "header" 114 #define ZONESTAT_NAME_FOOTER "footer" 115 116 #define ZONESTAT_NAME_NAME "name" 117 #define ZONESTAT_NAME_USED "used" 118 #define ZONESTAT_NAME_CAP "cap" 119 #define ZONESTAT_NAME_PCAP "pcap" 120 #define ZONESTAT_NAME_SHR "shr" 121 #define ZONESTAT_NAME_PSHRU "pshru" 122 #define ZONESTAT_NAME_CPU "cpu" 123 #define ZONESTAT_NAME_PHYSICAL_MEMORY ZONESTAT_PHYSICAL_MEMORY 124 #define ZONESTAT_NAME_VIRTUAL_MEMORY ZONESTAT_VIRTUAL_MEMORY 125 126 #define ZONESTAT_NAME_SYSTEM_LIMIT "system-limit" 127 128 #define ZSTAT_REPORT_FMT_INTERVAL 0 129 #define ZSTAT_REPORT_FMT_TOTAL 1 130 #define ZSTAT_REPORT_FMT_AVERAGE 2 131 #define ZSTAT_REPORT_FMT_HIGH 3 132 #define ZSTAT_REPORT_FMT_END 4 133 134 #define ZSTAT_REPORT_TEXT_INTERVAL "interval" 135 #define ZSTAT_REPORT_TEXT_TOTAL "report-total" 136 #define ZSTAT_REPORT_TEXT_AVERAGE "report-average" 137 #define ZSTAT_REPORT_TEXT_HIGH "report-high" 138 #define ZSTAT_REPORT_TEXT_END "footer" 139 140 #define ZSTAT_DURATION_INF ((int)INT_MAX) 141 #define ZSTAT_INTERVAL_DEFAULT ((int)INT_MAX) 142 #define ZSTAT_REPORT_END ((int)INT_MAX) 143 144 #define ZSTAT_SORT_CPU 1 145 #define ZSTAT_SORT_PHYSICAL 2 146 #define ZSTAT_SORT_VIRTUAL 3 147 #define ZSTAT_SORT_USED 4 148 #define ZSTAT_SORT_CAP 5 149 #define ZSTAT_SORT_PCAP 6 150 #define ZSTAT_SORT_SHR 7 151 #define ZSTAT_SORT_PSHRU 8 152 #define ZSTAT_SORT_NAME 9 153 #define ZSTAT_SORT_MAX 10 154 155 #define ZSTAT_SUM_MIN_ZONENAME 19 156 #define ZSTAT_SUM_HDR_FORMAT "%23s %17s %17s\n" 157 #define ZSTAT_SUM_ZONE_FORMAT "%5s %5s %5s %5s %5s %5s %5s %5s %5s %5s\n" 158 159 #define ZSTAT_CPU_MIN_PSETNAME 22 160 #define ZSTAT_CPU_MIN_ZONENAME 36 161 #define ZSTAT_CPU_RES_FORMAT "%13s %11s %11s\n" 162 #define ZSTAT_CPU_ZONE_FORMAT "%5s %5s %5s %5s %6s %5s %5s\n" 163 164 #define ZSTAT_RESOURCE_MIN_RESNAME 28 165 #define ZSTAT_RESOURCE_MIN_ZONENAME 36 166 #define ZSTAT_RESOURCE_FORMAT "%13s\n" 167 #define ZSTAT_RESOURCE_ZONE_FORMAT "%5s %5s %5s %5s\n" 168 169 #define ZS_UINT64_STRLEN 20 170 #define ZS_PCT_STRLEN 10 171 #define ZS_TIME_STRLEN 20 172 #define ZS_NAME_STRLEN 10 173 174 time_t g_now_time; 175 time_t g_boot_time; 176 time_t g_start_time; 177 time_t g_end_time; 178 int g_interval; 179 int g_count; 180 int g_report_count; 181 time_t g_seconds; 182 183 int g_resources; 184 zs_ctl_t *g_zsctl; 185 boolean_t g_quit = B_FALSE; 186 zs_zone_t **g_zone_list; 187 int g_zone_num; 188 zs_pset_zone_t **g_pz_list; 189 int g_pz_num; 190 zs_pset_t **g_pset_list; 191 int g_pset_num; 192 int g_sort_by; 193 int g_sorts[ZSTAT_SORT_MAX]; 194 int g_sort_summary; 195 size_t g_max_zonename; 196 197 /* Storage for command line arguments. */ 198 char **arg_zonenames; 199 int arg_zonename_count; 200 char **arg_resnames; 201 int arg_resname_count; 202 char **arg_restypes; 203 int arg_restype_count; 204 char ** arg_reports; 205 int arg_report_count; 206 char ** arg_sort_list; 207 int arg_sort_count; 208 char ** arg_line_list; 209 int arg_line_count; 210 211 time_t arg_starttime; 212 time_t arg_endtime; 213 uint_t arg_timestamp = ZSTAT_DATE_TIMESTAMP; 214 int arg_interval = 5; 215 int arg_duration = -1; 216 int arg_report = -1; 217 218 /* Options with or as arguments */ 219 boolean_t opt_zonenames = B_FALSE; 220 boolean_t opt_resnames = B_FALSE; 221 boolean_t opt_restypes = B_FALSE; 222 boolean_t opt_start = B_FALSE; 223 boolean_t opt_end = B_FALSE; 224 boolean_t opt_in = B_FALSE; 225 boolean_t opt_out = B_FALSE; 226 boolean_t opt_timestamp = B_FALSE; 227 boolean_t opt_report = B_FALSE; 228 boolean_t opt_sort = B_FALSE; 229 230 boolean_t opt_report_high = B_FALSE; 231 boolean_t opt_report_total = B_FALSE; 232 boolean_t opt_report_average = B_FALSE; 233 234 boolean_t opt_line_resource = B_FALSE; 235 boolean_t opt_line_total = B_FALSE; 236 boolean_t opt_line_system = B_FALSE; 237 boolean_t opt_line_zones = B_FALSE; 238 boolean_t opt_line_header = B_FALSE; 239 boolean_t opt_line_any = B_FALSE; 240 241 /* Options without arguments */ 242 boolean_t opt_quiet_intervals = B_FALSE; 243 boolean_t opt_parseable = B_FALSE; 244 boolean_t opt_debug = B_FALSE; 245 246 static int 247 zonestat_usage(boolean_t explicit) 248 { 249 FILE *fd = explicit ? stdout : stderr; 250 251 (void) fprintf(fd, gettext("Usage:\n")); 252 (void) fprintf(fd, 253 " zonestat [-z zonelist] [-r reslist] [-n namelist]\n" 254 " [-T u | d | i] [-R reports] [-q] [-p [-P lines]] [-S cols]\n" 255 " interval [duration [report]]\n" 256 "\n"); 257 (void) fprintf(fd, gettext( 258 " Options:\n" 259 " %s Report resources of specified types.\n" 260 " Valid resource types are:\n" 261 " \"%s\"\n" 262 " \"%s\"\n" 263 " \"%s\"\n" 264 " \"%s\"\n" 265 " \"%s\", \"%s\", \"%s\"\n" 266 " \"%s\", \"%s\", \"%s\", \"%s\"\n"), 267 "-r", 268 ZONESTAT_VIRTUAL_MEMORY, ZONESTAT_PHYSICAL_MEMORY, 269 ZONESTAT_LOCKED_MEMORY, ZONESTAT_PROCESSOR_SET, 270 ZONESTAT_PROCESSES, ZONESTAT_LWPS, ZONESTAT_LOFI, 271 ZONESTAT_SHM_MEMORY, ZONESTAT_SHM_IDS, ZONESTAT_SEM_IDS, 272 ZONESTAT_MSG_IDS); 273 274 (void) fprintf(fd, gettext( 275 " The following resource nicknames can also be specified:\n" 276 " \"%s\"\n" 277 " \"%s\"\n" 278 " \"%s\"\n" 279 " \"%s\"\n" 280 " \"%s\"\n" 281 " \"%s\"\n"), 282 ZONESTAT_SUMMARY, ZONESTAT_MEMORY, ZONESTAT_PSETS, 283 ZONESTAT_DEFAULT_PSET, ZONESTAT_LIMITS, ZONESTAT_SYSV); 284 (void) fprintf(fd, gettext( 285 " %s Report resources used by zones\n" 286 " %s Report resources with specific names.\n" 287 " Valid resource names are:\n" 288 " \"%s\"\n" 289 " \"%s\"\n" 290 " Name of a pool processor set\n" 291 " Id of a processor set created with psrset(1m)\n" 292 " Name of a zone using dedicated-cpu\n"), 293 "-z", "-n", 294 ZONESTAT_NAME_MEM_DEFAULT, ZONESTAT_NAME_VM_DEFAULT); 295 (void) printf(gettext( 296 " %s Print timestamp. Valid timestamps are:\n" 297 " \"%s\"\tDate as specifed by date(1) command\n" 298 " \"%s\"\tUnix time as returned by time(2)\n" 299 " \"%s\"\tISO 8601 timestamp \"%s\"\n" 300 " %s Print reports at end or after each report interval.\n" 301 " Valid reports are:\n" 302 " \"%s\"\tUsage of each zone\n" 303 " \"%s\"\tUsage of each zone while running\n" 304 " \"%s\"\tMaximum usage of each zone\n" 305 " %s Quiet. Do not print intervals. Only print reports.\n" 306 " %s Machine parseable output.\n"), 307 "-T", "d", "u", "i", "YYYYMMDDThhmmssZ", 308 "-R", ZONESTAT_NAME_TOTAL, ZONESTAT_NAME_AVERAGE, 309 ZONESTAT_NAME_HIGH, 310 "-q", "-p"); 311 312 (void) printf(gettext( 313 " %s Select desired lines in parseable output.\n" 314 " \"%s\"\tLines describing each resource\n" 315 " \"%s\"\tTotal usage of each resource\n" 316 " \"%s\"\tSystem usage of each resource\n" 317 " \"%s\"\tPer-zone usage of each resource\n" 318 " \"%s\"\tHeader lines between intervals and reports\n"), 319 "-P", ZONESTAT_NAME_RESOURCE, ZONESTAT_NAME_TOTAL, 320 ZONESTAT_NAME_SYSTEM, ZONESTAT_NAME_ZONES, ZONESTAT_NAME_HEADER); 321 322 (void) printf(gettext( 323 " %s Sort output by the specified columns:\n" 324 " \"%s\"\tby name alphanumerically\n" 325 " \"%s\"\tby percent of resource used\n" 326 " \"%s\"\tby configured cap\n" 327 " \"%s\"\tby percent of cap used\n" 328 " \"%s\"\tby shares configured\n" 329 " \"%s\"\tby percent of share used\n" 330 " \"%s\"\tSort summary by cpu\n" 331 " \"%s\"\tSort summary by physical memory\n" 332 " \"%s\"\tSort summary by virtual memory\n"), 333 "-S", ZONESTAT_NAME_NAME, ZONESTAT_NAME_USED, ZONESTAT_NAME_CAP, 334 ZONESTAT_NAME_PCAP, ZONESTAT_NAME_SHR, ZONESTAT_NAME_PSHRU, 335 ZONESTAT_NAME_CPU, ZONESTAT_NAME_PHYSICAL_MEMORY, 336 ZONESTAT_NAME_VIRTUAL_MEMORY); 337 338 if (!explicit) 339 (void) fputs("\n", fd); 340 return (ZSTAT_USAGE); 341 } 342 343 /* PRINTFLIKE1 */ 344 static int 345 zonestat_error(const char *fmt, ...) 346 { 347 va_list alist; 348 349 va_start(alist, fmt); 350 351 (void) fprintf(stderr, "zonestat: Error: "); 352 (void) vfprintf(stderr, fmt, alist); 353 (void) fprintf(stderr, "\n"); 354 va_end(alist); 355 return (ZSTAT_ERROR); 356 } 357 358 static void 359 zonestat_determine_lines() 360 { 361 int i; 362 boolean_t fail = B_FALSE; 363 364 if (arg_line_count == 0) { 365 opt_line_resource = B_TRUE; 366 opt_line_total = B_TRUE; 367 opt_line_system = B_TRUE; 368 opt_line_zones = B_TRUE; 369 opt_line_header = B_TRUE; 370 } 371 for (i = 0; i < arg_line_count; i++) { 372 if (strcmp(arg_line_list[i], ZONESTAT_NAME_RESOURCE) == 0) 373 opt_line_resource = B_TRUE; 374 else if (strcmp(arg_line_list[i], ZONESTAT_NAME_TOTAL) == 0) 375 opt_line_total = B_TRUE; 376 else if (strcmp(arg_line_list[i], ZONESTAT_NAME_SYSTEM) == 0) 377 opt_line_system = B_TRUE; 378 else if (strcmp(arg_line_list[i], ZONESTAT_NAME_ZONES) == 0) 379 opt_line_zones = B_TRUE; 380 else if (strcmp(arg_line_list[i], ZONESTAT_NAME_HEADER) == 0) 381 opt_line_header = B_TRUE; 382 else { 383 (void) zonestat_error(gettext("Unknown -O arg: %s"), 384 arg_line_list[i]); 385 fail = B_TRUE; 386 } 387 } 388 if (fail == B_TRUE) 389 exit(zonestat_usage(B_FALSE)); 390 } 391 392 static void 393 zonestat_determine_reports() 394 { 395 int i; 396 boolean_t fail = B_FALSE; 397 398 for (i = 0; i < arg_report_count; i++) { 399 if (strcmp(arg_reports[i], ZONESTAT_NAME_TOTAL) == 0) 400 opt_report_total = B_TRUE; 401 else if (strcmp(arg_reports[i], ZONESTAT_NAME_AVERAGE) == 0) 402 opt_report_average = B_TRUE; 403 else if (strcmp(arg_reports[i], ZONESTAT_NAME_HIGH) == 0) 404 opt_report_high = B_TRUE; 405 else { 406 (void) zonestat_error(gettext("Unknown -R arg: %s"), 407 arg_reports[i]); 408 fail = B_TRUE; 409 } 410 } 411 if (fail == B_TRUE) 412 exit(zonestat_usage(B_FALSE)); 413 } 414 415 /* 416 * Compares list of -S sort arguments to the list of known sorts. Only 417 * one of cpu, physical memory, and virtual memory can be specified. 418 */ 419 static void 420 zonestat_determine_sort() 421 { 422 int i, count = 0; 423 boolean_t fail = B_FALSE; 424 425 if (arg_sort_count == 0) { 426 g_sort_summary = ZS_RESOURCE_CPU; 427 g_sorts[0] = ZSTAT_SORT_USED; 428 g_sorts[1] = ZSTAT_SORT_NAME; 429 arg_sort_count = 2; 430 return; 431 } 432 433 if (arg_sort_count > ZSTAT_SORT_MAX) 434 exit(zonestat_error(gettext( 435 "Too many -S sort columns specified"))); 436 437 for (i = 0; i < arg_sort_count; i++) { 438 if (strcmp(arg_sort_list[i], ZONESTAT_NAME_NAME) == 0) 439 g_sorts[count++] = ZSTAT_SORT_NAME; 440 else if (strcmp(arg_sort_list[i], ZONESTAT_NAME_USED) == 0) 441 g_sorts[count++] = ZSTAT_SORT_USED; 442 else if (strcmp(arg_sort_list[i], ZONESTAT_NAME_CAP) == 0) 443 g_sorts[count++] = ZSTAT_SORT_CAP; 444 else if (strcmp(arg_sort_list[i], ZONESTAT_NAME_PCAP) == 0) 445 g_sorts[count++] = ZSTAT_SORT_PCAP; 446 else if (strcmp(arg_sort_list[i], ZONESTAT_NAME_SHR) == 0) 447 g_sorts[count++] = ZSTAT_SORT_SHR; 448 else if (strcmp(arg_sort_list[i], ZONESTAT_NAME_PSHRU) == 0) 449 g_sorts[count++] = ZSTAT_SORT_PSHRU; 450 else if (strcmp(arg_sort_list[i], ZONESTAT_NAME_CPU) == 0) { 451 if (g_sort_summary != 0) 452 fail = B_TRUE; 453 g_sort_summary = ZS_RESOURCE_CPU; 454 } else if (strcmp(arg_sort_list[i], 455 ZONESTAT_NAME_PHYSICAL_MEMORY) == 0) { 456 if (g_sort_summary != 0) 457 fail = B_TRUE; 458 g_sort_summary = ZS_RESOURCE_RAM_RSS; 459 } else if (strcmp(arg_sort_list[i], 460 ZONESTAT_NAME_VIRTUAL_MEMORY) == 0) { 461 if (g_sort_summary != 0) 462 fail = B_TRUE; 463 g_sort_summary = ZS_RESOURCE_VM; 464 } else { 465 (void) zonestat_error(gettext("Unknown -S arg: %s"), 466 arg_sort_list[i]); 467 fail = B_TRUE; 468 } 469 } 470 if (g_sort_summary == 0) 471 g_sort_summary = ZS_RESOURCE_CPU; 472 473 if (fail == B_TRUE) { 474 (void) zonestat_error(gettext( 475 "-S: only one of \"%s\", \"%s\", or " 476 "\"%s\" permitted"), "-S", ZONESTAT_NAME_CPU, 477 ZONESTAT_NAME_PHYSICAL_MEMORY, 478 ZONESTAT_NAME_VIRTUAL_MEMORY); 479 exit(zonestat_usage(B_FALSE)); 480 } 481 } 482 483 typedef struct zonestat_resource_struct { 484 char *zr_name; 485 uint_t zr_flag; 486 } zonestat_resource_t; 487 488 489 /* Used to map resource name strings to resource flags */ 490 zonestat_resource_t g_resource_list[] = { 491 ZONESTAT_PHYSICAL_MEMORY, ZSTAT_RES_PHYSICAL_MEMORY, 492 ZONESTAT_VIRTUAL_MEMORY, ZSTAT_RES_VIRTUAL_MEMORY, 493 ZONESTAT_LOCKED_MEMORY, ZSTAT_RES_LOCKED_MEMORY, 494 ZONESTAT_MEMORY, ZSTAT_RES_MEMORY, 495 ZONESTAT_PROCESSOR_SET, ZSTAT_RES_PSETS, 496 ZONESTAT_PSETS, ZSTAT_RES_PSETS, 497 ZONESTAT_DEFAULT_PSET, ZSTAT_RES_DEFAULT_PSET, 498 ZONESTAT_PROCESSES, ZSTAT_RES_PROCESSES, 499 ZONESTAT_LWPS, ZSTAT_RES_LWPS, 500 ZONESTAT_LOFI, ZSTAT_RES_LOFI, 501 ZONESTAT_LIMITS, ZSTAT_RES_LIMITS, 502 ZONESTAT_SHM_MEMORY, ZSTAT_RES_SHM_MEMORY, 503 ZONESTAT_SHM_IDS, ZSTAT_RES_SHM_IDS, 504 ZONESTAT_SEM_IDS, ZSTAT_RES_SEM_IDS, 505 ZONESTAT_MSG_IDS, ZSTAT_RES_MSG_IDS, 506 ZONESTAT_SYSV, ZSTAT_RES_SYSV, 507 ZONESTAT_SUMMARY, ZSTAT_RES_SUMMARY, 508 ZONESTAT_ALL, ZSTAT_RES_ALL 509 }; 510 511 /* 512 * Compares list of resources passed to -r to the known list of 513 * resources. 514 */ 515 static void 516 zonestat_determine_resources() 517 { 518 int i, j, count; 519 boolean_t found, fail = B_FALSE; 520 521 if (arg_restype_count == 0) { 522 g_resources = ZSTAT_RES_SUMMARY; 523 return; 524 } 525 526 count = sizeof (g_resource_list) / sizeof (zonestat_resource_t); 527 528 for (i = 0; i < arg_restype_count; i++) { 529 found = B_FALSE; 530 for (j = 0; j < count; j++) { 531 if (strcmp(arg_restypes[i], g_resource_list[j].zr_name) 532 == 0) { 533 g_resources |= g_resource_list[j].zr_flag; 534 found = B_TRUE; 535 break; 536 } 537 } 538 if (found == B_FALSE) { 539 (void) zonestat_error(gettext("Unknown resource: %s"), 540 arg_restypes[i]); 541 fail = B_TRUE; 542 } 543 } 544 if (fail == B_TRUE) 545 exit(zonestat_usage(B_FALSE)); 546 } 547 548 /* 549 * Returns 1 if the name matches one of the specified zone names. 0 550 * otherwise. Always matches if no zone names were specified. 551 */ 552 static int 553 zonestat_match_zonename(char *name) 554 { 555 int i; 556 557 if (arg_zonename_count == 0) 558 return (1); 559 for (i = 0; i < arg_zonename_count; i++) { 560 if (strcmp(name, arg_zonenames[i]) == 0) 561 return (1); 562 } 563 return (0); 564 } 565 566 /* 567 * compare name to base, ignoring prefix on name. 568 */ 569 static int 570 zonestat_match_with_prefix(char *prefix, char *name, char *base) 571 { 572 size_t prefix_len; 573 574 prefix_len = strlen(prefix); 575 if (strncmp(name, prefix, prefix_len) == 0) { 576 name += prefix_len; 577 if (strcmp(name, base) == 0) 578 return (1); 579 } 580 return (0); 581 } 582 /* 583 * Returns 1 if the resource matches one of the specified resource names. 0 584 * otherwise. Always matches if no resource names were specified. 585 */ 586 static int 587 zonestat_match_resname(char *name) 588 { 589 int i; 590 591 if (arg_resname_count == 0) 592 return (1); 593 for (i = 0; i < arg_resname_count; i++) { 594 595 if (strcmp(name, arg_resnames[i]) == 0) 596 return (1); 597 598 if (zonestat_match_with_prefix("SUNWtmp_", name, 599 arg_resnames[i])) 600 return (1); 601 602 if (zonestat_match_with_prefix("SUNWlegacy_pset_", name, 603 arg_resnames[i])) 604 return (1); 605 } 606 return (0); 607 } 608 609 /* 610 * Format unsigned uint64_t 611 * 612 * 9999 9999 613 * 99.9K 99999 614 * 9999K 9999999 615 * 99.9M 99999999 616 * 9999M 9999999999 617 * 99.9G 99999999999 618 * 9999G 9999999999999 619 * 99.9T 99999999999999 620 * 9999T 9999999999999999 621 * 99.9P 99999999999999999 622 * 9999P 9999999999999999999 623 * 99.9E UINT64_MAX 624 */ 625 static void 626 format_uint64(uint64_t val, char *str, size_t len) 627 { 628 uint64_t high; 629 uint64_t low; 630 631 if (val == UINT64_MAX) { 632 (void) snprintf(str, len, "-"); 633 return; 634 } 635 if (val <= 9999) { 636 (void) snprintf(str, len, "%llu", val); 637 return; 638 } 639 if (val <= 99999) { 640 high = val / 1024; 641 low = val * 10 / 1024 - (high * 10); 642 (void) snprintf(str, len, "%llu%1.1lluK", high, low); 643 return; 644 } 645 val = val / 1024; 646 if (val <= 9999 || opt_parseable) { 647 high = val; 648 (void) snprintf(str, len, "%lluK", high); 649 return; 650 } 651 if (val <= 99999) { 652 high = val / 1024; 653 low = val * 10 / 1024 - (high * 10); 654 (void) snprintf(str, len, "%llu.%1.1lluM", high, low); 655 return; 656 } 657 val = val / 1024; 658 if (val <= 9999) { 659 high = val; 660 (void) snprintf(str, len, "%lluM", high); 661 return; 662 } 663 if (val <= 99999) { 664 high = val / 1024; 665 low = val * 10 / 1024 - (high * 10); 666 (void) snprintf(str, len, "%llu.%1.1lluG", high, low); 667 return; 668 } 669 val = val / 1024; 670 if (val <= 9999) { 671 high = val; 672 (void) snprintf(str, len, "%lluG", high); 673 return; 674 } 675 if (val <= 99999) { 676 high = val / 1024; 677 low = val * 10 / 1024 - (high * 10); 678 (void) snprintf(str, len, "%llu.%1.1lluT", high, low); 679 return; 680 } 681 val = val / 1024; 682 if (val <= 9999) { 683 high = val; 684 (void) snprintf(str, len, "%lluT", high); 685 return; 686 } 687 if (val <= 99999) { 688 high = val / 1024; 689 low = val * 10 / 1024 - (high * 10); 690 (void) snprintf(str, len, "%llu.%1.1lluP", high, low); 691 return; 692 } 693 val = val / 1024; 694 if (val <= 9999) { 695 high = val; 696 (void) snprintf(str, len, "%lluP", high); 697 return; 698 } 699 high = val / 1024; 700 low = val * 10 / 1024 - (high * 10); 701 (void) snprintf(str, len, "%llu.%1.1lluE", high, low); 702 } 703 704 705 static void 706 format_pct(uint_t pct, char *str, size_t len) 707 { 708 uint_t high; 709 uint_t low; 710 711 if (pct == ZS_PCT_NONE) { 712 (void) snprintf(str, len, "-"); 713 return; 714 } 715 /* 716 * pct's are printed as one of: 717 * #.##% 718 * ##.#% 719 * ###% 720 * ####% 721 * 722 * The value is fixed decimal. 10000 equals 100.00 percent. 723 * Percents can exceed 100.00 percent. Percents greater than 724 * 9999% will exceed the 5 column width. 725 */ 726 if (pct <= 999 || opt_parseable) { 727 high = pct / 100; 728 low = pct - (high * 100); 729 (void) snprintf(str, len, "%u.%2.2u%%", high, low); 730 } else if (pct <= 9999) { 731 pct = pct / 10; 732 high = pct / 10; 733 low = pct - (high * 10); 734 (void) snprintf(str, len, "%u.%1.1u%%", high, low); 735 } else { 736 pct = pct / 100; 737 (void) snprintf(str, len, "%u%%", pct); 738 } 739 } 740 /* 741 * Cpu cap is 100 times the number of cpus allocated. It is formatted as a 742 * decimal. Example, a cpu-cap of 50 is 0.50 cpus. 743 * 744 * The cpu cap value can go up to UINT_MAX, so handle all cases even though 745 * the higher ones are nonsense. 746 * 747 * Format Max cpu-cap value for format. 748 * 42.9M 4294967296 749 * 9999K 999999999 750 * 99.9K 9999999 751 * 9999 999999 752 * 999.9 99999 753 * 9.99 999 754 */ 755 void 756 format_cpu(uint64_t cpu, char *str, size_t len) 757 { 758 759 uint64_t high; 760 uint64_t low; 761 762 /* #.## cpus */ 763 if (cpu <= 999 || opt_parseable) { 764 high = cpu / 100; 765 low = cpu - (high * 100); 766 (void) snprintf(str, len, "%llu.%2.2llu", high, low); 767 return; 768 } 769 /* ##.# cpus */ 770 if (cpu <= 99999) { 771 high = cpu / 100; 772 low = cpu - (high * 100); 773 (void) snprintf(str, len, "%llu.%1.1llu", high, low); 774 return; 775 } 776 /* #### cpus */ 777 if (cpu <= 999999) { 778 cpu = cpu / 100; 779 (void) snprintf(str, len, "%llu", cpu); 780 return; 781 } 782 /* ##.#K cpus */ 783 cpu = cpu / 1000; 784 if (cpu <= 99999) { 785 high = cpu / 100; 786 low = cpu - (high * 100); 787 (void) snprintf(str, len, "%llu.%1.1lluK", high, low); 788 return; 789 } 790 /* ####K cpus */ 791 if (cpu <= 999999) { 792 cpu = cpu / 100; 793 (void) snprintf(str, len, "%lluK", cpu); 794 return; 795 } 796 /* ##.#M cpus */ 797 cpu = cpu / 1000; 798 if (cpu <= UINT_MAX) { 799 high = cpu / 100; 800 low = cpu - (high * 100); 801 (void) snprintf(str, len, "%llu.%1.1lluM", high, low); 802 return; 803 } 804 (void) snprintf(str, len, "error", high, low); 805 } 806 807 /* 808 * Format a timetruct as: 809 * HH:MM:SS.SS 810 * 811 * Human readable format omits the fractional seconds. 812 */ 813 static void 814 format_ts(timestruc_t *ts, char *str, size_t len, boolean_t human_readable) 815 { 816 uint64_t secs, mins, hours, pct; 817 818 hours = 0; 819 mins = 0; 820 821 secs = ts->tv_sec; 822 pct = ts->tv_nsec / 1000 / 1000 / 10; 823 while (pct >= 100) { 824 pct -= 100; 825 secs++; 826 } 827 if (secs >= 60) { 828 mins = secs / 60; 829 secs = secs % 60; 830 } 831 if (mins >= 60) { 832 hours = mins / 60; 833 mins = mins % 60; 834 } 835 if (human_readable) 836 (void) snprintf(str, len, "%llu:%2.2llu:%2.2llu", hours, 837 mins, secs); 838 else 839 (void) snprintf(str, len, "%llu-%2.2llu-%2.2llu.%2.2llu", hours, 840 mins, secs, pct); 841 } 842 843 char *g_report_formats[] = { 844 ZSTAT_REPORT_TEXT_INTERVAL, 845 ZSTAT_REPORT_TEXT_TOTAL, 846 ZSTAT_REPORT_TEXT_AVERAGE, 847 ZSTAT_REPORT_TEXT_HIGH, 848 ZSTAT_REPORT_TEXT_END 849 }; 850 851 /* Get the label for the current report type */ 852 static char * 853 zonestat_get_plabel(int format) 854 { 855 if (format >= sizeof (g_report_formats) / sizeof (char *)) 856 exit(zonestat_error(gettext( 857 "Internal error, invalid report format"))); 858 859 return (g_report_formats[format]); 860 } 861 862 #define ZSTAT_CPULINE "----------CPU----------" 863 #define ZSTAT_MEMLINE "----PHYSICAL-----" 864 #define ZSTAT_VMLINE "-----VIRTUAL-----" 865 866 static void 867 zonestat_print_summary_header(size_t namewidth, int report_fmt, uint64_t cpu, 868 uint64_t online, uint64_t mem, uint64_t vm) 869 { 870 char str_cpu[ZS_UINT64_STRLEN]; 871 char str_online[ZS_UINT64_STRLEN]; 872 char str_mem[ZS_UINT64_STRLEN]; 873 char str_vm[ZS_UINT64_STRLEN]; 874 char name_format[ZS_NAME_STRLEN]; 875 char tot_cpu[sizeof (ZSTAT_CPULINE)]; 876 char tot_mem[sizeof (ZSTAT_MEMLINE)]; 877 char tot_vm[sizeof (ZSTAT_VMLINE)]; 878 879 char *label; 880 881 format_uint64(cpu, str_cpu, sizeof (str_cpu)); 882 format_uint64(online, str_online, sizeof (str_online)); 883 format_uint64(mem, str_mem, sizeof (str_mem)); 884 format_uint64(vm, str_vm, sizeof (str_vm)); 885 886 if (opt_parseable) { 887 label = zonestat_get_plabel(report_fmt); 888 (void) printf("%s:%s:[%s]:%s:%s:%s:%s\n", label, 889 ZONESTAT_SUMMARY, ZONESTAT_NAME_RESOURCE, str_cpu, 890 str_online, str_mem, str_vm); 891 return; 892 } 893 894 (void) snprintf(tot_cpu, sizeof (tot_cpu), "Cpus/Online: %s/%s", 895 str_cpu, str_online); 896 897 (void) snprintf(tot_mem, sizeof (tot_mem), "Physical: %s", str_mem); 898 899 (void) snprintf(tot_vm, sizeof (tot_vm), "Virtual: %s", str_vm); 900 901 /* Make first column as wide as longest zonename */ 902 (void) snprintf(name_format, sizeof (name_format), "%%-%ds ", 903 namewidth); 904 /* LINTED */ 905 (void) printf(name_format, "SUMMARY"); 906 (void) printf(ZSTAT_SUM_HDR_FORMAT, tot_cpu, tot_mem, 907 tot_vm); 908 909 /* LINTED */ 910 (void) printf(name_format, ""); 911 (void) printf(ZSTAT_SUM_HDR_FORMAT, ZSTAT_CPULINE, 912 ZSTAT_MEMLINE, ZSTAT_VMLINE); 913 914 (void) snprintf(name_format, sizeof (name_format), "%%%ds ", 915 namewidth); 916 /* LINTED */ 917 (void) printf(name_format, "ZONE"); 918 919 (void) printf(ZSTAT_SUM_ZONE_FORMAT, "USED", "%PART", "%CAP", 920 "%SHRU", "USED", "PCT", "%CAP", "USED", "PCT", "%CAP"); 921 } 922 923 static void 924 zonestat_print_resource__header(size_t namelen, char *restype, char *size) 925 { 926 char name_format[ZS_NAME_STRLEN]; 927 928 if (opt_parseable) 929 return; 930 931 (void) snprintf(name_format, sizeof (name_format), "%%-%ds ", namelen); 932 /* LINTED */ 933 (void) printf(name_format, restype); 934 (void) printf(ZSTAT_RESOURCE_FORMAT, size); 935 } 936 937 static void 938 zonestat_print_resource_zone_header(size_t namelen) 939 { 940 char name_format[ZS_NAME_STRLEN]; 941 942 if (opt_parseable) 943 return; 944 945 (void) snprintf(name_format, sizeof (name_format), "%%%ds ", namelen); 946 /* LINTED */ 947 (void) printf(name_format, "ZONE"); 948 949 (void) printf(ZSTAT_RESOURCE_ZONE_FORMAT, "USED", "PCT", "CAP", "%CAP"); 950 } 951 952 static void 953 zonestat_print_timestamp(time_t t) 954 { 955 static char *fmt = NULL; 956 int len; 957 char dstr[64]; 958 959 /* We only need to retrieve this once per invocation */ 960 961 if (arg_timestamp == ZSTAT_UNIX_TIMESTAMP) { 962 (void) printf("%ld", t); 963 } else if (arg_timestamp == ZSTAT_ISO_TIMESTAMP) { 964 965 len = strftime(dstr, sizeof (dstr), "%Y%m%dT%H%M%SZ", 966 gmtime(&t)); 967 if (len > 0) 968 (void) printf("%s", dstr); 969 970 } else { 971 972 if (fmt == NULL) 973 fmt = nl_langinfo(_DATE_FMT); 974 975 len = strftime(dstr, sizeof (dstr), fmt, localtime(&t)); 976 if (len > 0) 977 (void) printf("%s", dstr); 978 } 979 } 980 981 static void 982 zonestat_print_summary_zone(size_t namewidth, int report_fmt, char *name, 983 uint64_t cused, uint_t ppart, uint_t pccap, uint_t pshru, uint64_t mused, 984 uint_t mpct, uint_t pmcap, uint64_t vused, uint_t vpct, uint_t pvcap) 985 { 986 char *label; 987 988 char str_cused[ZS_UINT64_STRLEN]; 989 char str_ppart[ZS_PCT_STRLEN]; 990 char str_pccap[ZS_PCT_STRLEN]; 991 char str_pshru[ZS_PCT_STRLEN]; 992 char str_mused[ZS_UINT64_STRLEN]; 993 char str_mpct[ZS_PCT_STRLEN]; 994 char str_pmcap[ZS_PCT_STRLEN]; 995 char str_vused[ZS_UINT64_STRLEN]; 996 char str_vpct[ZS_PCT_STRLEN]; 997 char str_pvcap[ZS_PCT_STRLEN]; 998 char name_format[ZS_NAME_STRLEN]; 999 1000 format_cpu(cused, str_cused, sizeof (str_cused)); 1001 format_pct(ppart, str_ppart, sizeof (str_ppart)); 1002 format_pct(pccap, str_pccap, sizeof (str_pccap)); 1003 format_pct(pshru, str_pshru, sizeof (str_pshru)); 1004 format_uint64(mused, str_mused, sizeof (str_mused)); 1005 format_pct(mpct, str_mpct, sizeof (str_mpct)); 1006 format_pct(pmcap, str_pmcap, sizeof (str_pmcap)); 1007 format_uint64(vused, str_vused, sizeof (str_vused)); 1008 format_pct(vpct, str_vpct, sizeof (str_vpct)); 1009 format_pct(pvcap, str_pvcap, sizeof (str_pvcap)); 1010 1011 if (opt_parseable) { 1012 if (opt_timestamp) { 1013 zonestat_print_timestamp(g_now_time); 1014 (void) printf(":"); 1015 } 1016 label = zonestat_get_plabel(report_fmt); 1017 (void) printf("%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n", 1018 label, ZONESTAT_SUMMARY, name, str_cused, str_ppart, 1019 str_pccap, str_pshru, str_mused, str_mpct, str_pmcap, 1020 str_vused, str_vpct, str_pvcap); 1021 return; 1022 } 1023 (void) snprintf(name_format, sizeof (name_format), "%%%ds ", 1024 namewidth); 1025 /* LINTED */ 1026 (void) printf(name_format, name); 1027 (void) printf(ZSTAT_SUM_ZONE_FORMAT, str_cused, str_ppart, 1028 str_pccap, str_pshru, str_mused, str_mpct, str_pmcap, str_vused, 1029 str_vpct, str_pvcap); 1030 } 1031 1032 static void 1033 zonestat_print_resource_(size_t namelen, int report_fmt, char *res, 1034 char *name, uint64_t size) 1035 { 1036 char strsize[ZS_UINT64_STRLEN]; 1037 char *label; 1038 char name_format[ZS_NAME_STRLEN]; 1039 1040 format_uint64(size, strsize, sizeof (strsize)); 1041 if (opt_parseable) { 1042 if (opt_timestamp) { 1043 zonestat_print_timestamp(g_now_time); 1044 (void) printf(":"); 1045 } 1046 label = zonestat_get_plabel(report_fmt); 1047 (void) printf("%s:%s:%s:[%s]:%s\n", label, res, name, 1048 ZONESTAT_NAME_RESOURCE, strsize); 1049 return; 1050 } 1051 1052 (void) snprintf(name_format, sizeof (name_format), "%%-%ds ", namelen); 1053 /* LINTED */ 1054 (void) printf(name_format, name); 1055 (void) printf(ZSTAT_RESOURCE_FORMAT, strsize); 1056 } 1057 1058 static void 1059 zonestat_print_resource_zone(size_t namelen, int report_fmt, char *restype, 1060 char *resname, char *name, uint64_t used, uint_t pct, uint64_t cap, 1061 uint_t pctcap) 1062 { 1063 char strused[ZS_UINT64_STRLEN]; 1064 char strpct[ZS_PCT_STRLEN]; 1065 char strcap[ZS_UINT64_STRLEN]; 1066 char strpctcap[ZS_PCT_STRLEN]; 1067 char name_format[ZS_NAME_STRLEN]; 1068 1069 char *label; 1070 1071 format_uint64(used, strused, sizeof (strused)); 1072 format_pct(pct, strpct, sizeof (strpct)); 1073 if (cap == ZS_LIMIT_NONE) 1074 (void) strlcpy(strcap, "-", sizeof (strcap)); 1075 else 1076 format_uint64(cap, strcap, sizeof (strcap)); 1077 1078 if (pctcap == ZS_PCT_NONE) 1079 (void) strlcpy(strpctcap, "-", sizeof (strpctcap)); 1080 else 1081 format_pct(pctcap, strpctcap, sizeof (strpctcap)); 1082 1083 if (opt_parseable) { 1084 if (opt_timestamp) { 1085 zonestat_print_timestamp(g_now_time); 1086 (void) printf(":"); 1087 } 1088 label = zonestat_get_plabel(report_fmt); 1089 (void) printf("%s:%s:%s:%s:%s:%s:%s:%s\n", label, restype, 1090 resname, name, strused, strpct, strcap, strpctcap); 1091 return; 1092 } 1093 1094 (void) snprintf(name_format, sizeof (name_format), "%%%ds ", namelen); 1095 /* LINTED */ 1096 (void) printf(name_format, name); 1097 (void) printf(ZSTAT_RESOURCE_ZONE_FORMAT, strused, strpct, strcap, 1098 strpctcap); 1099 } 1100 1101 /* 1102 * Not thread safe. 1103 */ 1104 static void 1105 zonestat_qsort(void *base, size_t nel, size_t width, 1106 int (*compar)(const void *, const void *), int by) 1107 { 1108 g_sort_by = by; 1109 g_max_zonename = 0; 1110 qsort(base, nel, width, compar); 1111 } 1112 1113 static int 1114 zonestat_zone_compare_resource(const void *a, const void *b) 1115 { 1116 zs_zone_t *zonea = *(zs_zone_t **)a; 1117 zs_zone_t *zoneb = *(zs_zone_t **)b; 1118 zs_property_t *prop, *propb; 1119 uint64_t resa, resb; 1120 uint_t uinta, uintb; 1121 int i, res; 1122 1123 prop = alloca(zs_property_size()); 1124 propb = alloca(zs_property_size()); 1125 1126 for (i = 0; i < arg_sort_count; i++) { 1127 1128 /* Sort by order of selection */ 1129 switch (g_sorts[i]) { 1130 case ZSTAT_SORT_USED: 1131 resa = zs_resource_used_zone_uint64(zonea, g_sort_by); 1132 resb = zs_resource_used_zone_uint64(zoneb, g_sort_by); 1133 break; 1134 case ZSTAT_SORT_CAP: 1135 resa = zs_zone_limit_uint64(zonea, g_sort_by); 1136 if (resa == ZS_LIMIT_NONE) 1137 resa = 0; 1138 resb = zs_zone_limit_uint64(zoneb, g_sort_by); 1139 if (resb == ZS_LIMIT_NONE) 1140 resb = 0; 1141 break; 1142 case ZSTAT_SORT_PCAP: 1143 uinta = zs_zone_limit_used_pct(zonea, g_sort_by); 1144 uintb = zs_zone_limit_used_pct(zoneb, g_sort_by); 1145 if (uinta == ZS_PCT_NONE) 1146 resa = 0; 1147 else 1148 resa = uinta; 1149 if (uintb == ZS_PCT_NONE) 1150 resb = 0; 1151 else 1152 resb = uintb; 1153 break; 1154 case ZSTAT_SORT_SHR: 1155 zs_zone_property(zonea, ZS_PZ_PROP_CPU_SHARES, prop); 1156 resa = zs_property_uint64(prop); 1157 if (resa == ZS_LIMIT_NONE) 1158 resa = 0; 1159 zs_zone_property(zoneb, ZS_PZ_PROP_CPU_SHARES, prop); 1160 resb = zs_property_uint64(prop); 1161 if (resb == ZS_LIMIT_NONE) 1162 resb = 0; 1163 break; 1164 case ZSTAT_SORT_PSHRU: 1165 uinta = zs_zone_limit_used_pct(zonea, 1166 ZS_LIMIT_CPU_SHARES); 1167 uintb = zs_zone_limit_used_pct(zoneb, 1168 ZS_LIMIT_CPU_SHARES); 1169 if (uinta == ZS_PCT_NONE) 1170 resa = 0; 1171 else 1172 resa = uinta; 1173 if (uintb == ZS_PCT_NONE) 1174 resb = 0; 1175 else 1176 resb = uintb; 1177 break; 1178 case ZSTAT_SORT_NAME: 1179 zs_zone_property(zonea, ZS_ZONE_PROP_NAME, prop); 1180 zs_zone_property(zoneb, ZS_ZONE_PROP_NAME, propb); 1181 1182 res = strcmp(zs_property_string(prop), 1183 zs_property_string(propb)); 1184 if (res != 0) 1185 return (res); 1186 break; 1187 default: 1188 exit(zonestat_error(gettext("Internal sort error"))); 1189 } 1190 if (resa < resb) 1191 return (1); 1192 if (resb < resa) 1193 return (-1); 1194 } 1195 /* No difference, return 0 */ 1196 return (0); 1197 } 1198 /* 1199 * Sort psets. Default pset first, then shared psets, then dedicated 1200 * psets. 1201 */ 1202 static int 1203 zonestat_pset_compare(const void *a, const void *b) 1204 { 1205 zs_pset_t *pseta = *(zs_pset_t **)a; 1206 zs_pset_t *psetb = *(zs_pset_t **)b; 1207 zs_property_t *p; 1208 uint_t typea, typeb; 1209 1210 1211 p = (zs_property_t *)alloca(zs_property_size()); 1212 zs_pset_property(pseta, ZS_PSET_PROP_CPUTYPE, p); 1213 typea = zs_property_uint(p); 1214 zs_pset_property(psetb, ZS_PSET_PROP_CPUTYPE, p); 1215 typeb = zs_property_uint(p); 1216 1217 if (typea == ZS_CPUTYPE_DEFAULT_PSET) 1218 return (-1); 1219 if (typeb == ZS_CPUTYPE_DEFAULT_PSET) 1220 return (1); 1221 if (typea == ZS_CPUTYPE_POOL_PSET) 1222 return (-1); 1223 if (typeb == ZS_CPUTYPE_POOL_PSET) 1224 return (1); 1225 if (typea == ZS_CPUTYPE_PSRSET_PSET) 1226 return (-1); 1227 if (typeb == ZS_CPUTYPE_PSRSET_PSET) 1228 return (1); 1229 1230 return (0); 1231 } 1232 1233 static int 1234 zonestat_pz_compare_usage(const void *a, const void *b) 1235 { 1236 zs_pset_zone_t *zonea = *(zs_pset_zone_t **)a; 1237 zs_pset_zone_t *zoneb = *(zs_pset_zone_t **)b; 1238 zs_property_t *prop, *propb; 1239 uint64_t resa, resb; 1240 uint_t uinta, uintb; 1241 int i, res; 1242 1243 prop = alloca(zs_property_size()); 1244 propb = alloca(zs_property_size()); 1245 1246 for (i = 0; i < arg_sort_count; i++) { 1247 1248 /* Sort by order of selection */ 1249 switch (g_sorts[i]) { 1250 case ZSTAT_SORT_USED: 1251 resa = zs_pset_zone_used_cpus(zonea); 1252 resb = zs_pset_zone_used_cpus(zoneb); 1253 break; 1254 case ZSTAT_SORT_CAP: 1255 zs_pset_zone_property(zonea, ZS_PZ_PROP_CPU_CAP, 1256 prop); 1257 resa = zs_property_uint64(prop); 1258 if (resa == ZS_LIMIT_NONE) 1259 resa = 0; 1260 zs_pset_zone_property(zoneb, ZS_PZ_PROP_CPU_CAP, 1261 prop); 1262 resb = zs_property_uint64(prop); 1263 if (resb == ZS_LIMIT_NONE) 1264 resb = 0; 1265 break; 1266 case ZSTAT_SORT_PCAP: 1267 uinta = zs_pset_zone_used_pct(zonea, ZS_PZ_PCT_CPU_CAP); 1268 uintb = zs_pset_zone_used_pct(zoneb, ZS_PZ_PCT_CPU_CAP); 1269 if (uinta == ZS_PCT_NONE) 1270 resa = 0; 1271 else 1272 resa = uinta; 1273 if (uintb == ZS_PCT_NONE) 1274 resb = 0; 1275 else 1276 resb = uintb; 1277 break; 1278 case ZSTAT_SORT_SHR: 1279 zs_pset_zone_property(zonea, ZS_PZ_PROP_CPU_SHARES, 1280 prop); 1281 resa = zs_property_uint64(prop); 1282 if (resa == ZS_LIMIT_NONE) 1283 resa = 0; 1284 zs_pset_zone_property(zoneb, ZS_PZ_PROP_CPU_SHARES, 1285 prop); 1286 resb = zs_property_uint64(prop); 1287 if (resb == ZS_LIMIT_NONE) 1288 resb = 0; 1289 break; 1290 case ZSTAT_SORT_PSHRU: 1291 uinta = zs_pset_zone_used_pct(zonea, 1292 ZS_PZ_PCT_CPU_SHARES); 1293 uintb = zs_pset_zone_used_pct(zoneb, 1294 ZS_PZ_PCT_CPU_SHARES); 1295 if (uinta == ZS_PCT_NONE) 1296 resa = 0; 1297 else 1298 resa = uinta; 1299 if (uintb == ZS_PCT_NONE) 1300 resb = 0; 1301 else 1302 resb = uintb; 1303 break; 1304 case ZSTAT_SORT_NAME: 1305 zs_zone_property(zs_pset_zone_get_zone(zonea), 1306 ZS_ZONE_PROP_NAME, prop); 1307 zs_zone_property(zs_pset_zone_get_zone(zoneb), 1308 ZS_ZONE_PROP_NAME, propb); 1309 1310 res = strcmp(zs_property_string(prop), 1311 zs_property_string(propb)); 1312 if (res != 0) 1313 return (res); 1314 break; 1315 default: 1316 exit(zonestat_error(gettext("Internal sort error"))); 1317 } 1318 if (resa < resb) 1319 return (1); 1320 if (resb < resa) 1321 return (-1); 1322 } 1323 /* No difference, return 0 */ 1324 return (0); 1325 } 1326 1327 1328 static void 1329 zonestat_print_summary(int report_fmt, zs_usage_t *u) 1330 { 1331 int num, i; 1332 zs_zone_t *z; 1333 uint64_t cpus, online, tot_mem, tot_vm; 1334 uint64_t cused, mused, vused; 1335 uint_t ppart, pshru, pccap, mpct, pmcap, vpct, pvcap; 1336 char zonename[ZS_ZONENAME_MAX]; 1337 zs_property_t *prop; 1338 size_t namewidth = 0, len; 1339 1340 prop = (zs_property_t *)alloca(zs_property_size()); 1341 1342 zs_resource_property(u, ZS_RESOURCE_CPU, ZS_RESOURCE_PROP_CPU_TOTAL, 1343 prop); 1344 cpus = zs_property_uint64(prop); 1345 1346 zs_resource_property(u, ZS_RESOURCE_CPU, 1347 ZS_RESOURCE_PROP_CPU_ONLINE, prop); 1348 online = zs_property_uint64(prop); 1349 1350 tot_mem = zs_resource_total_uint64(u, ZS_RESOURCE_RAM_RSS); 1351 tot_vm = zs_resource_total_uint64(u, ZS_RESOURCE_VM); 1352 1353 again: 1354 num = zs_zone_list(u, g_zone_list, g_zone_num); 1355 if (num > g_zone_num) { 1356 if (g_zone_list != NULL) 1357 free(g_zone_list); 1358 g_zone_list = (zs_zone_t **) malloc(sizeof (zs_zone_t *) * num); 1359 g_zone_num = num; 1360 goto again; 1361 } 1362 1363 /* Find the longest zone name to set output width. */ 1364 namewidth = ZSTAT_SUM_MIN_ZONENAME; 1365 for (i = 0; i < num; i++) { 1366 z = g_zone_list[i]; 1367 (void) zs_zone_property(z, ZS_ZONE_PROP_NAME, prop); 1368 len = strlen(zs_property_string(prop)); 1369 if (len > namewidth) 1370 namewidth = len; 1371 } 1372 zonestat_print_summary_header(namewidth, report_fmt, cpus, online, 1373 tot_mem, tot_vm); 1374 1375 zonestat_qsort(g_zone_list, num, sizeof (zs_zone_t *), 1376 zonestat_zone_compare_resource, g_sort_summary); 1377 1378 cused = zs_resource_used_uint64(u, ZS_RESOURCE_CPU, ZS_USER_ALL); 1379 mused = zs_resource_used_uint64(u, ZS_RESOURCE_RAM_RSS, ZS_USER_ALL); 1380 vused = zs_resource_used_uint64(u, ZS_RESOURCE_VM, ZS_USER_ALL); 1381 1382 ppart = zs_resource_used_pct(u, ZS_RESOURCE_CPU, ZS_USER_ALL); 1383 mpct = zs_resource_used_pct(u, ZS_RESOURCE_RAM_RSS, ZS_USER_ALL); 1384 vpct = zs_resource_used_pct(u, ZS_RESOURCE_VM, ZS_USER_ALL); 1385 1386 if (opt_line_total) { 1387 (void) snprintf(zonename, sizeof (zonename), "[%s]", 1388 ZONESTAT_NAME_TOTAL); 1389 zonestat_print_summary_zone(namewidth, report_fmt, zonename, 1390 cused, ppart, ZS_PCT_NONE, ZS_PCT_NONE, mused, mpct, 1391 ZS_PCT_NONE, vused, vpct, ZS_PCT_NONE); 1392 } 1393 cused = zs_resource_used_uint64(u, ZS_RESOURCE_CPU, ZS_USER_KERNEL); 1394 mused = zs_resource_used_uint64(u, ZS_RESOURCE_RAM_RSS, ZS_USER_KERNEL); 1395 vused = zs_resource_used_uint64(u, ZS_RESOURCE_VM, ZS_USER_KERNEL); 1396 1397 ppart = zs_resource_used_pct(u, ZS_RESOURCE_CPU, ZS_USER_KERNEL); 1398 mpct = zs_resource_used_pct(u, ZS_RESOURCE_RAM_RSS, ZS_USER_KERNEL); 1399 vpct = zs_resource_used_pct(u, ZS_RESOURCE_VM, ZS_USER_KERNEL); 1400 1401 if (opt_line_system) { 1402 (void) snprintf(zonename, sizeof (zonename), "[%s]", 1403 ZONESTAT_NAME_SYSTEM); 1404 zonestat_print_summary_zone(namewidth, report_fmt, zonename, 1405 cused, ppart, ZS_PCT_NONE, ZS_PCT_NONE, mused, mpct, 1406 ZS_PCT_NONE, vused, vpct, ZS_PCT_NONE); 1407 } 1408 for (i = 0; i < num; i++) { 1409 1410 z = g_zone_list[i]; 1411 1412 zs_zone_property(z, ZS_ZONE_PROP_NAME, prop); 1413 (void) strlcpy(zonename, zs_property_string(prop), 1414 sizeof (zonename)); 1415 1416 cused = zs_resource_used_zone_uint64(z, ZS_RESOURCE_CPU); 1417 mused = zs_resource_used_zone_uint64(z, ZS_RESOURCE_RAM_RSS); 1418 vused = zs_resource_used_zone_uint64(z, ZS_RESOURCE_VM); 1419 1420 ppart = zs_resource_used_zone_pct(z, ZS_RESOURCE_CPU); 1421 mpct = zs_resource_used_zone_pct(z, ZS_RESOURCE_RAM_RSS); 1422 vpct = zs_resource_used_zone_pct(z, ZS_RESOURCE_VM); 1423 1424 pshru = zs_zone_limit_used_pct(z, ZS_LIMIT_CPU_SHARES); 1425 pccap = zs_zone_limit_used_pct(z, ZS_LIMIT_CPU); 1426 pmcap = zs_zone_limit_used_pct(z, ZS_LIMIT_RAM_RSS); 1427 pvcap = zs_zone_limit_used_pct(z, ZS_LIMIT_VM); 1428 1429 zonestat_print_summary_zone(namewidth, report_fmt, zonename, 1430 cused, ppart, pccap, pshru, mused, mpct, pmcap, vused, vpct, 1431 pvcap); 1432 } 1433 1434 if (!opt_parseable) 1435 (void) printf("\n"); 1436 (void) fflush(stdout); 1437 } 1438 1439 static void 1440 zonestat_print_res(int report_fmt, char *header, char *sizename, char *resname, 1441 char *name, zs_usage_t *u, int res, int limit) 1442 { 1443 zs_zone_t *zone; 1444 char zonename[ZS_ZONENAME_MAX]; 1445 uint64_t size; 1446 uint64_t used; 1447 uint64_t cap; 1448 uint_t pct; 1449 uint_t pctcap; 1450 zs_property_t *prop; 1451 int num, i; 1452 size_t namelen, len; 1453 1454 prop = (zs_property_t *)alloca(zs_property_size()); 1455 1456 /* See if resource matches specified resource names */ 1457 if (zonestat_match_resname(name) == 0) 1458 return; 1459 1460 namelen = strlen(resname); 1461 if (ZSTAT_RESOURCE_MIN_RESNAME > namelen) 1462 namelen = ZSTAT_RESOURCE_MIN_RESNAME; 1463 1464 zonestat_print_resource__header(namelen, header, sizename); 1465 1466 size = zs_resource_total_uint64(u, res); 1467 1468 if (opt_line_resource) 1469 zonestat_print_resource_(namelen, report_fmt, resname, name, 1470 size); 1471 1472 again: 1473 num = zs_zone_list(u, g_zone_list, g_zone_num); 1474 if (num > g_zone_num) { 1475 if (g_zone_list != NULL) 1476 free(g_zone_list); 1477 g_zone_list = (zs_zone_t **) malloc(sizeof (zs_zone_t *) * num); 1478 g_zone_num = num; 1479 goto again; 1480 } 1481 namelen = ZSTAT_RESOURCE_MIN_ZONENAME; 1482 for (i = 0; i < num; i++) { 1483 zone = g_zone_list[i]; 1484 (void) zs_zone_property(zone, ZS_ZONE_PROP_NAME, prop); 1485 len = strlen(zs_property_string(prop)); 1486 if (len > namelen) 1487 namelen = len; 1488 } 1489 1490 zonestat_print_resource_zone_header(namelen); 1491 1492 used = zs_resource_used_uint64(u, res, ZS_USER_ALL); 1493 pct = zs_resource_used_pct(u, res, ZS_USER_ALL); 1494 1495 if (opt_line_total) { 1496 (void) snprintf(zonename, sizeof (zonename), "[%s]", 1497 ZONESTAT_NAME_TOTAL); 1498 zonestat_print_resource_zone(namelen, report_fmt, resname, 1499 name, zonename, used, pct, ZS_LIMIT_NONE, ZS_PCT_NONE); 1500 } 1501 used = zs_resource_used_uint64(u, res, ZS_USER_KERNEL); 1502 pct = zs_resource_used_pct(u, res, ZS_USER_KERNEL); 1503 1504 if (opt_line_system) { 1505 (void) snprintf(zonename, sizeof (zonename), "[%s]", 1506 ZONESTAT_NAME_SYSTEM); 1507 zonestat_print_resource_zone(namelen, report_fmt, resname, name, 1508 zonename, used, pct, ZS_LIMIT_NONE, ZS_PCT_NONE); 1509 } 1510 zonestat_qsort(g_zone_list, num, sizeof (zs_zone_t *), 1511 zonestat_zone_compare_resource, res); 1512 1513 for (i = 0; i < num; i++) { 1514 1515 zone = g_zone_list[i]; 1516 zs_zone_property(zone, ZS_ZONE_PROP_NAME, prop); 1517 (void) strlcpy(zonename, zs_property_string(prop), 1518 sizeof (zonename)); 1519 1520 if (zonestat_match_zonename(zonename) == 0) 1521 continue; 1522 1523 used = zs_resource_used_zone_uint64(zone, res); 1524 pct = zs_resource_used_zone_pct(zone, res); 1525 1526 cap = zs_zone_limit_uint64(zone, limit); 1527 pctcap = zs_zone_limit_used_pct(zone, limit); 1528 1529 if (opt_line_zones) 1530 zonestat_print_resource_zone(namelen, report_fmt, 1531 resname, name, zonename, used, pct, cap, pctcap); 1532 } 1533 if (!opt_parseable) 1534 (void) printf("\n"); 1535 } 1536 1537 static void 1538 zonestat_print_cpu_res_header(size_t namelen) 1539 { 1540 char name_format[ZS_NAME_STRLEN]; 1541 1542 if (opt_parseable) 1543 return; 1544 1545 (void) snprintf(name_format, sizeof (name_format), "%%-%ds ", namelen); 1546 /* LINTED */ 1547 (void) printf(name_format, "PROCESSOR_SET"); 1548 (void) printf(ZSTAT_CPU_RES_FORMAT, "TYPE", "ONLINE/CPUS", "MIN/MAX"); 1549 } 1550 static void 1551 zonestat_print_cpu_zone_header(size_t namelen) 1552 { 1553 char name_format[ZS_NAME_STRLEN]; 1554 1555 if (opt_parseable) 1556 return; 1557 1558 (void) snprintf(name_format, sizeof (name_format), "%%%ds ", namelen); 1559 /* LINTED */ 1560 (void) printf(name_format, "ZONE"); 1561 1562 (void) printf(ZSTAT_CPU_ZONE_FORMAT, "USED", "PCT", "CAP", 1563 "%CAP", "SHRS", "%SHR", "%SHRU"); 1564 } 1565 1566 static void 1567 zonestat_print_cpu_res(size_t namelen, int report_fmt, char *cputype, 1568 char *name, uint64_t online, uint64_t size, uint64_t min, uint64_t max, 1569 timestruc_t *ts) 1570 { 1571 char online_str[ZS_UINT64_STRLEN]; 1572 char size_str[ZS_UINT64_STRLEN]; 1573 char min_str[ZS_UINT64_STRLEN]; 1574 char max_str[ZS_UINT64_STRLEN]; 1575 char cpus_str[ZS_UINT64_STRLEN + ZS_UINT64_STRLEN + 1]; 1576 char minmax_str[ZS_UINT64_STRLEN + ZS_UINT64_STRLEN + 1]; 1577 char ts_str[ZS_TIME_STRLEN]; 1578 char name_format[ZS_NAME_STRLEN]; 1579 1580 char *label; 1581 1582 format_uint64(online, online_str, sizeof (online_str)); 1583 format_uint64(size, size_str, sizeof (size_str)); 1584 format_uint64(min, min_str, sizeof (min_str)); 1585 format_uint64(max, max_str, sizeof (max_str)); 1586 format_ts(ts, ts_str, sizeof (ts_str), B_FALSE); 1587 1588 if (opt_parseable) { 1589 if (opt_timestamp) { 1590 zonestat_print_timestamp(g_now_time); 1591 (void) printf(":"); 1592 } 1593 label = zonestat_get_plabel(report_fmt); 1594 1595 (void) printf("%s:%s:%s:%s:[%s]:%s:%s:%s:%s:%s\n", label, 1596 ZONESTAT_PROCESSOR_SET, cputype, name, 1597 ZONESTAT_NAME_RESOURCE, online_str, size_str, min_str, 1598 max_str, ts_str); 1599 return; 1600 } 1601 1602 (void) snprintf(cpus_str, sizeof (cpus_str), "%s/%s", online_str, 1603 size_str); 1604 (void) snprintf(minmax_str, sizeof (minmax_str), "%s/%s", min_str, 1605 max_str); 1606 1607 (void) snprintf(name_format, sizeof (name_format), "%%-%ds ", namelen); 1608 /* LINTED */ 1609 (void) printf(name_format, name); 1610 (void) printf(ZSTAT_CPU_RES_FORMAT, cputype, cpus_str, minmax_str); 1611 } 1612 1613 static void 1614 zonestat_print_cpu_zone(size_t namelen, int report_fmt, char *cputype, 1615 char *name, char *zonename, uint64_t used, uint_t pct, uint64_t cap, 1616 uint_t pct_cap, uint64_t shares, uint_t scheds, uint_t pct_shares, 1617 uint_t pct_shares_used, timestruc_t *ts, boolean_t report_conflict) 1618 { 1619 char used_str[ZS_UINT64_STRLEN]; 1620 char pct_str[ZS_PCT_STRLEN]; 1621 char cap_str[ZS_UINT64_STRLEN]; 1622 char pct_cap_str[ZS_PCT_STRLEN]; 1623 char shares_str[ZS_UINT64_STRLEN]; 1624 char pct_shares_str[ZS_PCT_STRLEN]; 1625 char pct_shares_used_str[ZS_PCT_STRLEN]; 1626 char ts_str[ZS_TIME_STRLEN]; 1627 char name_format[ZS_NAME_STRLEN]; 1628 char *label; 1629 1630 format_cpu(used, used_str, sizeof (used_str)); 1631 format_pct(pct, pct_str, sizeof (pct_str)); 1632 format_ts(ts, ts_str, sizeof (ts_str), B_FALSE); 1633 1634 if (cap == ZS_LIMIT_NONE) 1635 (void) strlcpy(cap_str, "-", sizeof (cap_str)); 1636 else 1637 format_cpu(cap, cap_str, sizeof (cap_str)); 1638 1639 if (pct_cap == ZS_PCT_NONE) 1640 (void) strlcpy(pct_cap_str, "-", sizeof (pct_cap_str)); 1641 else 1642 format_pct(pct_cap, pct_cap_str, sizeof (pct_cap_str)); 1643 1644 if ((scheds & ZS_SCHED_CONFLICT) && 1645 (!(scheds & ZS_SCHED_FSS))) 1646 (void) strlcpy(shares_str, "no-fss", sizeof (shares_str)); 1647 else if (shares == ZS_LIMIT_NONE) 1648 (void) strlcpy(shares_str, "-", sizeof (shares_str)); 1649 else if (shares == ZS_SHARES_UNLIMITED) 1650 (void) strlcpy(shares_str, "inf", sizeof (shares_str)); 1651 else 1652 format_uint64(shares, shares_str, sizeof (shares_str)); 1653 1654 if (pct_shares == ZS_PCT_NONE) 1655 (void) strlcpy(pct_shares_str, "-", sizeof (pct_shares_str)); 1656 else 1657 format_pct(pct_shares, pct_shares_str, 1658 sizeof (pct_shares_str)); 1659 1660 if (pct_shares_used == ZS_PCT_NONE) { 1661 (void) strlcpy(pct_shares_used_str, "-", 1662 sizeof (pct_shares_used_str)); 1663 } else { 1664 format_pct(pct_shares_used, pct_shares_used_str, 1665 sizeof (pct_shares_used_str)); 1666 } 1667 if (opt_parseable) { 1668 if (opt_timestamp) { 1669 zonestat_print_timestamp(g_now_time); 1670 (void) printf(":"); 1671 } 1672 label = zonestat_get_plabel(report_fmt); 1673 1674 (void) printf("%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n", label, 1675 ZONESTAT_PROCESSOR_SET, cputype, name, zonename, used_str, 1676 pct_str, cap_str, pct_cap_str, shares_str, pct_shares_str, 1677 pct_shares_used_str, ts_str); 1678 return; 1679 } else { 1680 (void) snprintf(name_format, sizeof (name_format), "%%%ds ", 1681 namelen); 1682 /* LINTED */ 1683 (void) printf(name_format, zonename); 1684 1685 (void) printf(ZSTAT_CPU_ZONE_FORMAT, used_str, 1686 pct_str, cap_str, pct_cap_str, shares_str, pct_shares_str, 1687 pct_shares_used_str); 1688 } 1689 /* Report if zone has mix of schedulers conflicting with FSS */ 1690 if (report_conflict && (scheds & ZS_SCHED_CONFLICT) && 1691 (scheds & ZS_SCHED_FSS)) { 1692 /* LINTED */ 1693 (void) printf(name_format, ""); 1694 (void) printf(" mixed schedulers found:"); 1695 (void) printf(" FSS"); 1696 if (scheds & ZS_SCHED_TS) 1697 (void) printf(", TS"); 1698 if (scheds & ZS_SCHED_IA) 1699 (void) printf(", IA"); 1700 if (scheds & ZS_SCHED_FX) 1701 (void) printf(", FX"); 1702 (void) printf("\n"); 1703 } 1704 } 1705 1706 static void 1707 zonestat_print_pset(int report_fmt, zs_pset_t *pset, char *cputype) 1708 { 1709 zs_pset_zone_t *pz; 1710 zs_zone_t *zone; 1711 uint64_t cpus; 1712 uint64_t size; 1713 uint64_t min; 1714 uint64_t max; 1715 uint_t scheds; 1716 uint64_t used; 1717 uint_t pct; 1718 uint64_t cap; 1719 uint_t pct_cap; 1720 uint64_t shares; 1721 uint_t pct_shares; 1722 uint_t pct_shares_used; 1723 char psetname[ZS_PSETNAME_MAX]; 1724 char zonename[ZS_PSETNAME_MAX]; 1725 char *name; 1726 zs_property_t *prop; 1727 boolean_t zone_match; 1728 int num, i; 1729 timestruc_t ts; 1730 size_t namelen, len; 1731 1732 prop = (zs_property_t *)alloca(zs_property_size()); 1733 1734 zs_pset_property(pset, ZS_PSET_PROP_NAME, prop); 1735 (void) strlcpy(psetname, zs_property_string(prop), sizeof (psetname)); 1736 1737 /* Check if pset contains specified zone */ 1738 if (arg_zonename_count > 0) { 1739 zone_match = B_FALSE; 1740 for (pz = zs_pset_zone_first(pset); pz != NULL; 1741 pz = zs_pset_zone_next(pset, pz)) { 1742 zone = zs_pset_zone_get_zone(pz); 1743 (void) zs_zone_property(zone, ZS_ZONE_PROP_NAME, prop); 1744 (void) strlcpy(zonename, zs_property_string(prop), 1745 sizeof (zonename)); 1746 1747 if (zonestat_match_zonename(zonename) == 1) { 1748 zone_match = B_TRUE; 1749 break; 1750 } 1751 } 1752 if (zone_match == B_FALSE) 1753 return; 1754 } 1755 1756 if (zonestat_match_resname(psetname) == 0) 1757 return; 1758 1759 zs_pset_property(pset, ZS_PSET_PROP_ONLINE, prop); 1760 cpus = zs_property_uint64(prop); 1761 zs_pset_property(pset, ZS_PSET_PROP_SIZE, prop); 1762 size = zs_property_uint64(prop); 1763 zs_pset_property(pset, ZS_PSET_PROP_MIN, prop); 1764 min = zs_property_uint64(prop); 1765 zs_pset_property(pset, ZS_PSET_PROP_MAX, prop); 1766 max = zs_property_uint64(prop); 1767 zs_pset_total_time(pset, &ts); 1768 1769 /* Strip off SUNWtmp_ from pset name */ 1770 name = psetname; 1771 if (strncmp(psetname, "SUNWtmp_", strlen("SUNWtmp_")) == 0) { 1772 name = strchr(psetname, '_'); 1773 name++; 1774 } 1775 1776 /* Strip off SUNWlegacy_pst for psrset psets */ 1777 if (strncmp(psetname, "SUNWlegacy_pset_", 1778 strlen("SUNWlegacy_pset_")) == 0) { 1779 name = strrchr(psetname, '_'); 1780 name++; 1781 } 1782 1783 namelen = strlen(name); 1784 if (ZSTAT_CPU_MIN_PSETNAME > namelen) 1785 namelen = ZSTAT_CPU_MIN_PSETNAME; 1786 1787 zonestat_print_cpu_res_header(namelen); 1788 1789 if (opt_line_resource) 1790 zonestat_print_cpu_res(namelen, report_fmt, cputype, name, cpus, 1791 size, min, max, &ts); 1792 1793 again: 1794 num = zs_pset_zone_list(pset, g_pz_list, g_pz_num); 1795 if (num > g_pz_num) { 1796 if (g_pz_list != NULL) 1797 free(g_pz_list); 1798 g_pz_list = (zs_pset_zone_t **)malloc( 1799 sizeof (zs_pset_zone_t *) * num); 1800 g_pz_num = num; 1801 goto again; 1802 } 1803 1804 /* Find longest zone name in pset */ 1805 namelen = ZSTAT_CPU_MIN_ZONENAME; 1806 for (i = 0; i < num; i++) { 1807 pz = g_pz_list[i]; 1808 zone = zs_pset_zone_get_zone(pz); 1809 zs_zone_property(zone, ZS_ZONE_PROP_NAME, prop); 1810 len = strlen(zs_property_string(prop)); 1811 if (len > namelen) 1812 namelen = len; 1813 } 1814 1815 qsort(g_pz_list, num, sizeof (zs_pset_zone_t *), 1816 zonestat_pz_compare_usage); 1817 1818 zonestat_print_cpu_zone_header(namelen); 1819 1820 zs_pset_property(pset, ZS_PSET_PROP_CPU_SHARES, prop); 1821 shares = zs_property_uint64(prop); 1822 zs_pset_property(pset, ZS_PSET_PROP_SCHEDULERS, prop); 1823 scheds = zs_property_uint(prop); 1824 1825 zs_pset_used_time(pset, ZS_USER_ALL, &ts); 1826 used = zs_pset_used_cpus(pset, ZS_USER_ALL); 1827 pct = zs_pset_used_pct(pset, ZS_USER_ALL); 1828 1829 if (opt_line_total) { 1830 (void) snprintf(zonename, sizeof (zonename), "[%s]", 1831 ZONESTAT_NAME_TOTAL); 1832 zonestat_print_cpu_zone(namelen, report_fmt, cputype, name, 1833 zonename, used, pct, ZS_LIMIT_NONE, ZS_PCT_NONE, shares, 1834 scheds, ZS_PCT_NONE, ZS_PCT_NONE, &ts, B_FALSE); 1835 } 1836 zs_pset_used_time(pset, ZS_USER_KERNEL, &ts); 1837 used = zs_pset_used_cpus(pset, ZS_USER_KERNEL); 1838 pct = zs_pset_used_pct(pset, ZS_USER_KERNEL); 1839 1840 if (opt_line_system) { 1841 (void) snprintf(zonename, sizeof (zonename), "[%s]", 1842 ZONESTAT_NAME_SYSTEM); 1843 zonestat_print_cpu_zone(namelen, report_fmt, cputype, name, 1844 zonename, used, pct, ZS_LIMIT_NONE, ZS_PCT_NONE, 1845 ZS_LIMIT_NONE, 0, ZS_PCT_NONE, ZS_PCT_NONE, &ts, B_FALSE); 1846 } 1847 for (i = 0; i < num; i++) { 1848 1849 pz = g_pz_list[i]; 1850 zone = zs_pset_zone_get_zone(pz); 1851 zs_zone_property(zone, ZS_ZONE_PROP_NAME, prop); 1852 (void) strlcpy(zonename, zs_property_string(prop), 1853 sizeof (zonename)); 1854 1855 if (zonestat_match_zonename(zonename) == 0) 1856 continue; 1857 1858 zs_pset_zone_property(pz, ZS_PZ_PROP_CPU_CAP, prop); 1859 cap = zs_property_uint64(prop); 1860 1861 zs_pset_zone_property(pz, ZS_PZ_PROP_CPU_SHARES, prop); 1862 shares = zs_property_uint64(prop); 1863 zs_pset_zone_property(pz, ZS_PZ_PROP_SCHEDULERS, prop); 1864 scheds = zs_property_uint(prop); 1865 1866 used = zs_pset_zone_used_cpus(pz); 1867 zs_pset_zone_used_time(pz, &ts); 1868 pct = zs_pset_zone_used_pct(pz, ZS_PZ_PCT_PSET); 1869 pct_cap = zs_pset_zone_used_pct(pz, ZS_PZ_PCT_CPU_CAP); 1870 pct_shares = zs_pset_zone_used_pct(pz, ZS_PZ_PCT_PSET_SHARES); 1871 pct_shares_used = zs_pset_zone_used_pct(pz, 1872 ZS_PZ_PCT_CPU_SHARES); 1873 1874 if (opt_line_zones) 1875 zonestat_print_cpu_zone(namelen, report_fmt, cputype, 1876 name, zonename, used, pct, cap, pct_cap, shares, 1877 scheds, pct_shares, pct_shares_used, &ts, B_TRUE); 1878 } 1879 if (!opt_parseable) 1880 (void) printf("\n"); 1881 } 1882 1883 /* ARGSUSED */ 1884 static void 1885 zonestat_quithandler(int sig) 1886 { 1887 g_quit = B_TRUE; 1888 } 1889 1890 static void 1891 zonestat_print_footer(int report_fmt) 1892 { 1893 char *label; 1894 1895 if (!opt_parseable) 1896 return; 1897 1898 if (opt_timestamp) { 1899 zonestat_print_timestamp(g_now_time); 1900 (void) printf(":"); 1901 } 1902 label = zonestat_get_plabel(report_fmt); 1903 (void) printf("%s:%s:", label, ZONESTAT_NAME_FOOTER); 1904 zonestat_print_timestamp(g_now_time); 1905 (void) printf("%d:%ld\n", g_interval, g_seconds); 1906 (void) fflush(stdout); 1907 } 1908 1909 static void 1910 zonestat_print_header(int report_fmt) 1911 { 1912 char *label; 1913 timestruc_t ts; 1914 char string[ZS_TIME_STRLEN]; 1915 1916 if (!opt_parseable) { 1917 1918 /* Human readable header */ 1919 if (opt_timestamp) { 1920 zonestat_print_timestamp(g_now_time); 1921 (void) printf(", "); 1922 } 1923 if (report_fmt == ZSTAT_REPORT_FMT_INTERVAL) { 1924 ts.tv_sec = g_seconds; 1925 ts.tv_nsec = 0; 1926 format_ts(&ts, string, sizeof (string), B_TRUE); 1927 (void) printf("Interval: %d, Duration: %s\n", g_count, 1928 string); 1929 (void) fflush(stdout); 1930 return; 1931 } else { 1932 switch (report_fmt) { 1933 case ZSTAT_REPORT_FMT_TOTAL: 1934 label = "Report: Total Usage"; 1935 break; 1936 case ZSTAT_REPORT_FMT_AVERAGE: 1937 label = "Report: Average Usage"; 1938 break; 1939 case ZSTAT_REPORT_FMT_HIGH: 1940 label = "Report: High Usage"; 1941 break; 1942 default: 1943 exit(zonestat_error(gettext( 1944 "Internal error, invalid header"))); 1945 } 1946 /* Left are the report header formats */ 1947 (void) printf("%s\n", label); 1948 (void) printf(" Start: "); 1949 zonestat_print_timestamp(g_start_time); 1950 (void) printf("\n End: "); 1951 zonestat_print_timestamp(g_end_time); 1952 (void) printf("\n"); 1953 ts.tv_sec = g_seconds; 1954 ts.tv_nsec = 0; 1955 format_ts(&ts, string, sizeof (string), B_TRUE); 1956 (void) printf(" Intervals: %d, Duration: %s\n", 1957 g_count, string); 1958 1959 (void) fflush(stdout); 1960 return; 1961 } 1962 } 1963 1964 if (!opt_line_header) 1965 return; 1966 1967 /* Parseable header */ 1968 if (opt_timestamp) { 1969 zonestat_print_timestamp(g_now_time); 1970 (void) printf(":"); 1971 } 1972 label = zonestat_get_plabel(report_fmt); 1973 1974 (void) printf("%s:%s:", label, ZONESTAT_NAME_HEADER); 1975 if (report_fmt == ZSTAT_REPORT_FMT_INTERVAL) { 1976 (void) printf("since-last-interval:"); 1977 zonestat_print_timestamp(g_now_time); 1978 (void) printf(":%d:%ld\n", g_count, g_seconds); 1979 (void) fflush(stdout); 1980 return; 1981 } 1982 1983 /* Left are the report header formats */ 1984 zonestat_print_timestamp(g_start_time); 1985 (void) printf(":"); 1986 zonestat_print_timestamp(g_end_time); 1987 (void) printf(":"); 1988 (void) printf("%d:%ld\n", g_interval, g_seconds); 1989 (void) fflush(stdout); 1990 } 1991 1992 static void 1993 zonestat_print_psets(int report_fmt, zs_usage_t *u) 1994 { 1995 zs_pset_t *pset; 1996 char *psettype; 1997 uint_t cputype, num, i; 1998 zs_property_t *p; 1999 2000 again: 2001 num = zs_pset_list(u, g_pset_list, g_pset_num); 2002 if (num > g_pset_num) { 2003 if (g_pset_list != NULL) 2004 free(g_pset_list); 2005 g_pset_list = (zs_pset_t **)malloc( 2006 sizeof (zs_pset_t *) * num); 2007 g_pset_num = num; 2008 goto again; 2009 } 2010 2011 /* Sort, default pset first, then pool, psrset, and dedicated psets */ 2012 qsort(g_pset_list, num, sizeof (zs_pset_t *), zonestat_pset_compare); 2013 2014 p = (zs_property_t *)alloca(zs_property_size()); 2015 for (i = 0; i < num; i++) { 2016 pset = g_pset_list[i]; 2017 (void) zs_pset_property(pset, ZS_PSET_PROP_CPUTYPE, p); 2018 cputype = zs_property_uint(p); 2019 if (cputype == ZS_CPUTYPE_DEFAULT_PSET && 2020 (g_resources & (ZSTAT_RES_PSETS | 2021 ZSTAT_RES_DEFAULT_PSET))) { 2022 psettype = ZONESTAT_DEFAULT_PSET; 2023 } else if (cputype == ZS_CPUTYPE_POOL_PSET && 2024 (g_resources & ZSTAT_RES_PSETS)) { 2025 psettype = ZONESTAT_POOL_PSET; 2026 } else if (cputype == ZS_CPUTYPE_PSRSET_PSET && 2027 (g_resources & ZSTAT_RES_PSETS)) { 2028 psettype = ZONESTAT_PSRSET_PSET; 2029 } else if (cputype == ZS_CPUTYPE_DEDICATED && 2030 (g_resources & ZSTAT_RES_PSETS)) { 2031 psettype = ZONESTAT_DEDICATED_CPU; 2032 } else { 2033 continue; 2034 } 2035 zonestat_print_pset(report_fmt, pset, psettype); 2036 } 2037 } 2038 2039 static void 2040 zonestat_print_resources(int report_fmt, zs_usage_t *usage) 2041 { 2042 if (g_resources & ZSTAT_RES_SUMMARY) 2043 zonestat_print_summary(report_fmt, usage); 2044 2045 if (g_resources & ZSTAT_RES_PHYSICAL_MEMORY) 2046 zonestat_print_res(report_fmt, "PHYSICAL-MEMORY", 2047 "SYSTEM MEMORY", ZONESTAT_PHYSICAL_MEMORY, 2048 ZONESTAT_NAME_MEM_DEFAULT, usage, 2049 ZS_RESOURCE_RAM_RSS, ZS_LIMIT_RAM_RSS); 2050 if (g_resources & ZSTAT_RES_VIRTUAL_MEMORY) 2051 zonestat_print_res(report_fmt, "VIRTUAL-MEMORY", 2052 "SYSTEM MEMORY", ZONESTAT_VIRTUAL_MEMORY, 2053 ZONESTAT_NAME_VM_DEFAULT, usage, 2054 ZS_RESOURCE_VM, ZS_LIMIT_VM); 2055 if (g_resources & ZSTAT_RES_LOCKED_MEMORY) 2056 zonestat_print_res(report_fmt, "LOCKED-MEMORY", "SYSTEM MEMORY", 2057 ZONESTAT_LOCKED_MEMORY, ZONESTAT_NAME_MEM_DEFAULT, usage, 2058 ZS_RESOURCE_RAM_LOCKED, ZS_LIMIT_RAM_LOCKED); 2059 2060 if (g_resources & (ZSTAT_RES_PSETS | ZSTAT_RES_DEFAULT_PSET)) 2061 zonestat_print_psets(report_fmt, usage); 2062 2063 if (g_resources & ZSTAT_RES_PROCESSES) 2064 zonestat_print_res(report_fmt, "PROCESSES", "SYSTEM LIMIT", 2065 ZONESTAT_PROCESSES, ZONESTAT_NAME_SYSTEM_LIMIT, 2066 usage, ZS_RESOURCE_PROCESSES, ZS_LIMIT_PROCESSES); 2067 2068 if (g_resources & ZSTAT_RES_LWPS) 2069 zonestat_print_res(report_fmt, "LWPS", "SYSTEM LIMIT", 2070 ZONESTAT_LWPS, ZONESTAT_NAME_SYSTEM_LIMIT, usage, 2071 ZS_RESOURCE_LWPS, ZS_LIMIT_LWPS); 2072 if (g_resources & ZSTAT_RES_LOFI) 2073 zonestat_print_res(report_fmt, "LOFI", "SYSTEM LIMIT", 2074 ZONESTAT_LOFI, ZONESTAT_NAME_SYSTEM_LIMIT, 2075 usage, ZS_RESOURCE_LOFI, ZS_LIMIT_LOFI); 2076 2077 if (g_resources & ZSTAT_RES_SHM_MEMORY) 2078 zonestat_print_res(report_fmt, "SHM_MEMORY", "SYSTEM LIMIT", 2079 ZONESTAT_SHM_MEMORY, ZONESTAT_NAME_SYSTEM_LIMIT, 2080 usage, ZS_RESOURCE_SHM_MEMORY, ZS_LIMIT_SHM_MEMORY); 2081 2082 if (g_resources & ZSTAT_RES_SHM_IDS) 2083 zonestat_print_res(report_fmt, "SHM_IDS", "SYSTEM LIMIT", 2084 ZONESTAT_SHM_IDS, ZONESTAT_NAME_SYSTEM_LIMIT, 2085 usage, ZS_RESOURCE_SHM_IDS, ZS_LIMIT_SHM_IDS); 2086 2087 if (g_resources & ZSTAT_RES_SEM_IDS) 2088 zonestat_print_res(report_fmt, "SEM_IDS", "SYSTEM LIMIT", 2089 ZONESTAT_SEM_IDS, ZONESTAT_NAME_SYSTEM_LIMIT, 2090 usage, ZS_RESOURCE_SEM_IDS, ZS_LIMIT_SEM_IDS); 2091 2092 if (g_resources & ZSTAT_RES_MSG_IDS) 2093 zonestat_print_res(report_fmt, "MSG_IDS", "SYSTEM LIMIT", 2094 ZONESTAT_MSG_IDS, ZONESTAT_NAME_SYSTEM_LIMIT, 2095 usage, ZS_RESOURCE_MSG_IDS, ZS_LIMIT_MSG_IDS); 2096 } 2097 2098 /* 2099 * Adds comma seperated list of names to array of names 2100 * Returns new total number of names. 2101 */ 2102 static size_t 2103 zonestat_parse_names(char *names, char ***namelist, size_t count) 2104 { 2105 size_t num, i; 2106 char *next, *string; 2107 2108 string = strdup(names); 2109 if (string == NULL) 2110 exit(zonestat_error(gettext("Out of Memory"))); 2111 2112 /* count names, delimiting with '\0'. */ 2113 next = string; 2114 num = 1; 2115 while ((next = strchr(next, ',')) != NULL) { 2116 *next++ = '\0'; 2117 num++; 2118 } 2119 2120 /* Resise names array */ 2121 *namelist = realloc(*namelist, sizeof (char *) * (num + count)); 2122 if (*namelist == NULL) 2123 exit(zonestat_error(gettext("Out of Memory"))); 2124 2125 /* add names to names array */ 2126 next = string; 2127 for (i = 0; i < num; i++) { 2128 (*namelist)[count + i] = next; 2129 next += strlen(next) + 1; 2130 } 2131 return (count + num); 2132 } 2133 2134 static int 2135 zonestat_extract_int(char *start, char *end, char **tail) 2136 { 2137 int val; 2138 int save; 2139 2140 save = *end; 2141 *end = '\0'; 2142 errno = 0; 2143 val = strtol(start, tail, 0); 2144 *end = save; 2145 if (errno != 0 || *tail == start) 2146 return (-1); 2147 2148 return (val); 2149 } 2150 2151 /* 2152 * parses and [nh][nm][hs] notation into seconds 2153 */ 2154 static int 2155 zonestat_parse_time(char *string, boolean_t *formatted) 2156 { 2157 int seconds = 0; 2158 int minutes = 0; 2159 int hours = 0; 2160 char *this, *next, *end; 2161 2162 *formatted = B_FALSE; 2163 2164 /* Look for special tokens */ 2165 if (strcmp("default", string) == 0) 2166 return (ZSTAT_INTERVAL_DEFAULT); 2167 2168 if (strcmp("inf", string) == 0) 2169 return (ZSTAT_DURATION_INF); 2170 2171 /* Look for hours */ 2172 this = string; 2173 next = strchr(this, 'h'); 2174 if (next != NULL) { 2175 if ((hours = zonestat_extract_int(this, next, &end)) == -1) 2176 return (-1); 2177 2178 *formatted = B_TRUE; 2179 this = next + 1; 2180 end++; 2181 } 2182 2183 /* Look for minutes delimiter */ 2184 next = strrchr(this, 'm'); 2185 if (next != NULL) { 2186 if ((minutes = zonestat_extract_int(this, next, &end)) == -1) 2187 return (-1); 2188 2189 *formatted = B_TRUE; 2190 this = next + 1; 2191 end++; 2192 } 2193 2194 /* Look for seconds delimiter */ 2195 next = strrchr(this, 's'); 2196 if (next != NULL) { 2197 if ((seconds = zonestat_extract_int(this, next, &end)) == -1) 2198 return (-1); 2199 2200 *formatted = B_TRUE; 2201 this = next + 1; 2202 end++; 2203 } 2204 2205 /* No delimiter found. Treat as seconds */ 2206 if (*formatted == B_FALSE) { 2207 errno = 0; 2208 seconds = strtol(this, &end, 0); 2209 if (errno != 0 || end == this) 2210 return (-1); 2211 } 2212 2213 if (*end != '\0') 2214 return (-1); 2215 2216 seconds += (minutes * 60); 2217 seconds += (hours * 60 * 60); 2218 2219 return (seconds); 2220 } 2221 2222 static void 2223 zonestat_print_reports(zs_usage_set_t *set) 2224 { 2225 zs_usage_t *usage_print; 2226 2227 if (opt_report_total == B_TRUE) { 2228 usage_print = zs_usage_set_compute(set, 2229 ZS_COMPUTE_SET_TOTAL); 2230 zonestat_print_header(ZSTAT_REPORT_FMT_TOTAL); 2231 zonestat_print_resources(ZSTAT_REPORT_FMT_TOTAL, usage_print); 2232 zonestat_print_footer(ZSTAT_REPORT_FMT_TOTAL); 2233 (void) fflush(stdout); 2234 } 2235 if (opt_report_average == B_TRUE) { 2236 usage_print = zs_usage_set_compute(set, 2237 ZS_COMPUTE_SET_AVERAGE); 2238 zonestat_print_header(ZSTAT_REPORT_FMT_AVERAGE); 2239 zonestat_print_resources(ZSTAT_REPORT_FMT_AVERAGE, usage_print); 2240 zonestat_print_footer(ZSTAT_REPORT_FMT_AVERAGE); 2241 (void) fflush(stdout); 2242 } 2243 if (opt_report_high == B_TRUE) { 2244 usage_print = zs_usage_set_compute(set, 2245 ZS_COMPUTE_SET_HIGH); 2246 zonestat_print_header(ZSTAT_REPORT_FMT_HIGH); 2247 zonestat_print_resources(ZSTAT_REPORT_FMT_HIGH, usage_print); 2248 zonestat_print_footer(ZSTAT_REPORT_FMT_HIGH); 2249 (void) fflush(stdout); 2250 } 2251 } 2252 2253 static void 2254 zonestat_set_fx() 2255 { 2256 pcinfo_t pcinfo; 2257 pcparms_t pcparms; 2258 2259 (void) strlcpy(pcinfo.pc_clname, "FX", sizeof (pcinfo.pc_clname)); 2260 if (priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo) == -1) { 2261 return; 2262 } 2263 pcparms.pc_cid = pcinfo.pc_cid; 2264 ((fxparms_t *)pcparms.pc_clparms)->fx_upri = 60; 2265 ((fxparms_t *)pcparms.pc_clparms)->fx_uprilim = 60; 2266 ((fxparms_t *)pcparms.pc_clparms)->fx_tqsecs = 0; 2267 ((fxparms_t *)pcparms.pc_clparms)->fx_tqnsecs = FX_NOCHANGE; 2268 (void) priocntl(P_PID, getpid(), PC_SETPARMS, (caddr_t)&pcparms); 2269 } 2270 2271 static time_t 2272 zonestat_time() 2273 { 2274 time_t t; 2275 2276 t = time(NULL); 2277 if (t < 0 && g_quit == B_FALSE) 2278 exit(zonestat_error(gettext( 2279 "Unable to fetch current time"))); 2280 2281 return (t); 2282 } 2283 2284 int 2285 main(int argc, char *argv[]) 2286 { 2287 int arg; 2288 time_t now, next, start, next_report; 2289 zs_usage_t *usage, *usage_last = NULL, *usage_print; 2290 zs_usage_set_t *set; 2291 boolean_t formatted; 2292 scf_simple_prop_t *prop; 2293 uint64_t *intervalp; 2294 char *not_responding; 2295 2296 /* Process command line options and args */ 2297 while ((arg = getopt(argc, argv, "z:r:n:T:R:qpP:S:D?")) 2298 != EOF) { 2299 switch (arg) { 2300 case 'z': 2301 opt_zonenames = B_TRUE; 2302 arg_zonename_count = zonestat_parse_names(optarg, 2303 &arg_zonenames, arg_zonename_count); 2304 break; 2305 case 'r': 2306 arg_restype_count = zonestat_parse_names(optarg, 2307 &arg_restypes, arg_restype_count); 2308 opt_restypes = B_TRUE; 2309 break; 2310 case 'n': 2311 opt_resnames = B_TRUE; 2312 arg_resname_count = zonestat_parse_names(optarg, 2313 &arg_resnames, arg_resname_count); 2314 break; 2315 case 'R': 2316 opt_report = B_TRUE; 2317 arg_report_count = zonestat_parse_names(optarg, 2318 &arg_reports, arg_report_count); 2319 break; 2320 case 'S': 2321 opt_sort = B_TRUE; 2322 arg_sort_count = zonestat_parse_names(optarg, 2323 &arg_sort_list, arg_sort_count); 2324 break; 2325 case 'T': 2326 opt_timestamp = B_TRUE; 2327 if (strcmp(optarg, "u") == 0) { 2328 arg_timestamp = ZSTAT_UNIX_TIMESTAMP; 2329 } else if (strcmp(optarg, "d") == 0) { 2330 arg_timestamp = ZSTAT_DATE_TIMESTAMP; 2331 } else if (strcmp(optarg, "i") == 0) { 2332 arg_timestamp = ZSTAT_ISO_TIMESTAMP; 2333 } else { 2334 (void) zonestat_error(gettext( 2335 "Invalid -T arg \"%s\". " 2336 "Must be 'u', 'i', or 'd'."), optarg); 2337 return (zonestat_usage(B_FALSE)); 2338 } 2339 break; 2340 case 'q': 2341 opt_quiet_intervals = B_TRUE; 2342 break; 2343 case 'p': 2344 opt_parseable = B_TRUE; 2345 break; 2346 case 'P': 2347 opt_line_any = B_TRUE; 2348 arg_line_count = zonestat_parse_names(optarg, 2349 &arg_line_list, arg_line_count); 2350 break; 2351 case 'D': 2352 opt_debug = B_TRUE; 2353 break; 2354 case '?': 2355 return (zonestat_usage(B_TRUE)); 2356 default: 2357 return (zonestat_usage(B_FALSE)); 2358 } 2359 } 2360 2361 if (opt_line_any & (!opt_parseable)) { 2362 (void) zonestat_error(gettext("-P requires -p")); 2363 return (zonestat_usage(B_FALSE)); 2364 } 2365 2366 if (opt_timestamp && arg_timestamp == ZSTAT_DATE_TIMESTAMP && 2367 opt_parseable) { 2368 (void) zonestat_error(gettext( 2369 "-T d invalid with -p. Use -T [u | i]")); 2370 return (zonestat_usage(B_FALSE)); 2371 2372 } 2373 /* Default to ISO timetamp in parseable output */ 2374 if (!opt_timestamp && opt_parseable) 2375 arg_timestamp = ZSTAT_ISO_TIMESTAMP; 2376 2377 /* Get the interval and count */ 2378 optind++; 2379 if (argc >= optind) { 2380 if ((arg_interval = zonestat_parse_time(argv[optind - 1], 2381 &formatted)) < 0 || arg_interval == 0) { 2382 (void) zonestat_error(gettext( 2383 "Invalid interval: \"%s\""), argv[optind - 1]); 2384 return (zonestat_usage(B_FALSE)); 2385 } 2386 } else { 2387 (void) zonestat_error(gettext("Interval required.")); 2388 return (zonestat_usage(B_FALSE)); 2389 } 2390 2391 if (arg_interval == ZSTAT_INTERVAL_DEFAULT) { 2392 /* Get the configured sample interval */ 2393 prop = scf_simple_prop_get(NULL, 2394 "svc:/system/zones-monitoring:default", "config", 2395 "sample_interval"); 2396 2397 if (prop == NULL) { 2398 return (zonestat_error(gettext( 2399 "Unable to fetch SMF property " 2400 "\"config/sample_interval\""))); 2401 } 2402 if (scf_simple_prop_type(prop) != SCF_TYPE_COUNT) { 2403 return (zonestat_error(gettext("Malformed SMF property " 2404 "\"config/sample_interval\". Must be of type " 2405 "\"count\""))); 2406 } 2407 intervalp = scf_simple_prop_next_count(prop); 2408 arg_interval = *intervalp; 2409 if (arg_interval == 0) 2410 return (zonestat_error(gettext("Malformed SMF property " 2411 "\"config/sample_interval\". Must be greater than" 2412 "zero"))); 2413 2414 scf_simple_prop_free(prop); 2415 } 2416 optind++; 2417 if (argc >= optind) { 2418 if ((arg_duration = zonestat_parse_time(argv[optind - 1], 2419 &formatted)) < 0 || arg_duration == 0) { 2420 (void) zonestat_error(gettext( 2421 "Invalid duration: \"%s\""), argv[optind - 1]); 2422 return (zonestat_usage(B_FALSE)); 2423 } 2424 /* If not formatted [nh][nm][ns], treat as count */ 2425 if (arg_duration != ZSTAT_DURATION_INF && 2426 formatted == B_FALSE) 2427 arg_duration *= arg_interval; 2428 } else { 2429 arg_duration = ZSTAT_DURATION_INF; 2430 } 2431 optind++; 2432 if (argc >= optind) { 2433 if ((arg_report = zonestat_parse_time(argv[optind - 1], 2434 &formatted)) < 0 || arg_report == 0) { 2435 (void) zonestat_error(gettext( 2436 "Invalid report period: \"%s\""), argv[optind - 1]); 2437 return (zonestat_usage(B_FALSE)); 2438 } 2439 /* If not formatted as [nh][nm][ns] treat as count */ 2440 if (formatted == B_FALSE) 2441 arg_report *= arg_interval; 2442 } else { 2443 arg_report = ZSTAT_REPORT_END; 2444 } 2445 2446 if (opt_quiet_intervals && (!opt_report)) { 2447 (void) zonestat_error(gettext("-q requires -R")); 2448 return (zonestat_usage(B_FALSE)); 2449 } 2450 2451 /* Figure out what resources to report on */ 2452 zonestat_determine_resources(); 2453 zonestat_determine_reports(); 2454 zonestat_determine_lines(); 2455 zonestat_determine_sort(); 2456 2457 /* Done parsing args beyond this point */ 2458 2459 (void) signal(SIGINT, zonestat_quithandler); 2460 (void) signal(SIGTERM, zonestat_quithandler); 2461 (void) signal(SIGHUP, zonestat_quithandler); 2462 2463 /* Run at high priority to keep up with busy system */ 2464 zonestat_set_fx(); 2465 2466 not_responding = gettext( 2467 "Zones monitoring service \"svc:/system/zones-monitoring:default\" " 2468 "not enabled or responding."); 2469 2470 /* Open zone statistics */ 2471 g_zsctl = zs_open(); 2472 if (g_zsctl == NULL) { 2473 if (errno == EPERM) 2474 return (zonestat_error(gettext("Permission denied"))); 2475 if (errno == EINTR || errno == ESRCH) { 2476 (void) zonestat_error(not_responding); 2477 return (3); 2478 } 2479 if (errno == ENOTSUP) 2480 return (zonestat_error(gettext( 2481 "Mismatched zonestat version. " 2482 "Re-install system/zones package."))); 2483 2484 return (zonestat_error(gettext( 2485 "Unexpected error. Unable to open zone statistics."))); 2486 } 2487 usage_last = zs_usage_read(g_zsctl); 2488 if (usage_last == NULL) { 2489 if (errno == EINTR && g_quit == B_TRUE) 2490 return (0); 2491 (void) zonestat_error(not_responding); 2492 return (3); 2493 } 2494 set = zs_usage_set_alloc(g_zsctl); 2495 2496 g_start_time = g_now_time = start = now = zonestat_time(); 2497 g_interval = arg_interval; 2498 g_report_count = g_count = g_seconds = 0; 2499 2500 if (opt_quiet_intervals == B_FALSE && opt_parseable == B_FALSE) 2501 (void) printf(gettext( 2502 "Collecting data for first interval...\n")); 2503 2504 for (;;) { 2505 time_t tosleep; 2506 2507 g_now_time = now = zonestat_time(); 2508 2509 if (arg_report != ZSTAT_REPORT_END) 2510 next_report = start + ((g_report_count + 1) * 2511 arg_report); 2512 2513 /* 2514 * Sleep till next interval. 2515 */ 2516 g_count++; 2517 next = g_start_time + (g_count) * g_interval; 2518 /* 2519 * Skip to next interval if due to busy system, zonestat did 2520 * not complete in time. 2521 */ 2522 while (now >= g_start_time + ((g_count + 1) * g_interval)) 2523 g_count++; 2524 2525 while (now < next) { 2526 /* Sleep until at next interval */ 2527 tosleep = next - now; 2528 (void) sleep(tosleep); 2529 now = zonestat_time(); 2530 if (g_quit == B_TRUE) 2531 goto interval_loop_done; 2532 } 2533 2534 g_seconds = now - start; 2535 g_now_time = now; 2536 if ((usage = zs_usage_read(g_zsctl)) == NULL) { 2537 if (errno == EINTR && g_quit == B_TRUE) 2538 break; 2539 (void) zonestat_error(not_responding); 2540 return (3); 2541 } 2542 2543 /* Compute cpu used since last interval */ 2544 usage_print = zs_usage_compute(NULL, usage_last, 2545 usage, ZS_COMPUTE_USAGE_INTERVAL); 2546 if (usage_print == NULL) 2547 (void) zonestat_error(gettext("Out of Memory")); 2548 2549 2550 if (opt_quiet_intervals == B_TRUE) 2551 goto interval_print_end; 2552 2553 zonestat_print_header(ZSTAT_REPORT_FMT_INTERVAL); 2554 zonestat_print_resources(ZSTAT_REPORT_FMT_INTERVAL, 2555 usage_print); 2556 zonestat_print_footer(ZSTAT_REPORT_FMT_INTERVAL); 2557 (void) fflush(stdout); 2558 2559 interval_print_end: 2560 (void) zs_usage_set_add(set, usage_print); 2561 2562 2563 /* Print reports if they are due */ 2564 if (opt_report && arg_report != ZSTAT_REPORT_END && 2565 now >= next_report) { 2566 g_end_time = now; 2567 zonestat_print_reports(set); 2568 zs_usage_set_free(set); 2569 set = zs_usage_set_alloc(); 2570 g_start_time = now; 2571 g_report_count++; 2572 } 2573 zs_usage_free(usage_last); 2574 usage_last = usage; 2575 if (arg_duration != ZSTAT_DURATION_INF && 2576 g_seconds >= arg_duration) 2577 break; 2578 } 2579 interval_loop_done: 2580 2581 /* Print last reports if due */ 2582 g_end_time = g_now_time; 2583 if (opt_report && zs_usage_set_count(set) > 0 && 2584 (arg_report == ZSTAT_REPORT_END || now < next_report)) 2585 zonestat_print_reports(set); 2586 2587 zs_usage_set_free(set); 2588 if (usage_last != NULL) 2589 zs_usage_free(usage_last); 2590 2591 if (g_zsctl != NULL) 2592 zs_close(g_zsctl); 2593 2594 return (0); 2595 } 2596