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 <door.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <stddef.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <strings.h>
35 #include <sys/mman.h>
36 #include <sys/socket.h>
37 #include <sys/stat.h>
38 #include <sys/types.h>
39 #include <unistd.h>
40 #include <zonestat.h>
41 #include <zonestat_impl.h>
42
43 #define ZSD_PCT_INT 10000
44 #define ZSD_PCT_DOUBLE 10000.0
45
46 #define ZSD_ONE_CPU 100
47
48 #ifndef MIN
49 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
50 #endif
51 #ifndef MAX
52 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
53 #endif
54
55 #define ZS_MAXTS(a, b) ((b).tv_sec > (a).tv_sec || \
56 ((b).tv_sec == (a).tv_sec && (b).tv_nsec > (a).tv_nsec) ? (b) : (a))
57
58
59 /* Compute max, treating ZS_LIMIT_NONE as zero */
60 #define ZS_MAXOF(a, b) { \
61 if ((b) != ZS_LIMIT_NONE) { \
62 if ((a) == ZS_LIMIT_NONE) \
63 (a) = (b); \
64 else if ((b) > (a)) \
65 (b) = (a); \
66 } \
67 }
68
69 /* Add two caps together, treating ZS_LIMIT_NONE as zero */
70 #define ZS_ADD_CAP(a, b) { \
71 if ((b) != ZS_LIMIT_NONE) { \
72 if ((a) == ZS_LIMIT_NONE) \
73 (a) = (b); \
74 else \
75 (a) += (b); \
76 } \
77 }
78
79 #define ZS_MAXOFTS(a, b) { \
80 if ((b).tv_sec > (a).tv_sec) (a) = (b); \
81 else if ((b).tv_nsec > (a).tv_nsec) (a) = (b); }
82
83 /*
84 * Functions for reading and manipulating resource usage.
85 */
86 static int
zs_connect_zonestatd()87 zs_connect_zonestatd()
88 {
89 int fd;
90
91 fd = open(ZS_DOOR_PATH, O_RDONLY);
92 return (fd);
93 }
94
95 static zs_zone_t *
zs_lookup_zone_byid(zs_usage_t * u,zoneid_t zid)96 zs_lookup_zone_byid(zs_usage_t *u, zoneid_t zid)
97 {
98 zs_zone_t *zone;
99
100 for (zone = list_head(&u->zsu_zone_list); zone != NULL;
101 zone = list_next(&u->zsu_zone_list, zone)) {
102 if (zone->zsz_id == zid)
103 return (zone);
104 }
105 return (NULL);
106 }
107
108 static zs_zone_t *
zs_lookup_zone_byname(zs_usage_t * u,char * name)109 zs_lookup_zone_byname(zs_usage_t *u, char *name)
110 {
111 zs_zone_t *zone;
112
113 for (zone = list_head(&u->zsu_zone_list); zone != NULL;
114 zone = list_next(&u->zsu_zone_list, zone)) {
115 if (strcmp(zone->zsz_name, name) == 0)
116 return (zone);
117 }
118 return (NULL);
119 }
120
121 static zs_usage_t *
zs_usage_alloc()122 zs_usage_alloc()
123 {
124 zs_usage_t *u;
125 zs_system_t *s;
126
127 u = (zs_usage_t *)calloc(sizeof (zs_usage_t), 1);
128 if (u == NULL)
129 return (NULL);
130
131 s = (zs_system_t *)calloc(sizeof (zs_system_t), 1);
132 if (s == NULL) {
133 free(u);
134 return (NULL);
135 }
136
137 u->zsu_mmap = B_FALSE;
138 u->zsu_system = s;
139 list_create(&u->zsu_zone_list, sizeof (zs_zone_t),
140 offsetof(zs_zone_t, zsz_next));
141 list_create(&u->zsu_pset_list, sizeof (zs_pset_t),
142 offsetof(zs_pset_t, zsp_next));
143
144 return (u);
145 }
146
147 static void
zs_zone_add_usage(zs_zone_t * old,zs_zone_t * new,int func)148 zs_zone_add_usage(zs_zone_t *old, zs_zone_t *new, int func)
149 {
150
151 if (func == ZS_COMPUTE_USAGE_HIGH) {
152
153 /* Compute max of caps */
154 ZS_MAXOF(old->zsz_cpu_cap, new->zsz_cpu_cap);
155 ZS_MAXOF(old->zsz_cpu_shares, new->zsz_cpu_shares);
156 ZS_MAXOF(old->zsz_ram_cap, new->zsz_ram_cap);
157 ZS_MAXOF(old->zsz_locked_cap, new->zsz_locked_cap);
158 ZS_MAXOF(old->zsz_vm_cap, new->zsz_vm_cap);
159 ZS_MAXOF(old->zsz_processes_cap, new->zsz_processes_cap);
160 ZS_MAXOF(old->zsz_lwps_cap, new->zsz_lwps_cap);
161 ZS_MAXOF(old->zsz_shm_cap, new->zsz_shm_cap);
162 ZS_MAXOF(old->zsz_shmids_cap, new->zsz_shmids_cap);
163 ZS_MAXOF(old->zsz_semids_cap, new->zsz_semids_cap);
164 ZS_MAXOF(old->zsz_msgids_cap, new->zsz_msgids_cap);
165 ZS_MAXOF(old->zsz_lofi_cap, new->zsz_lofi_cap);
166
167 /* Compute max memory and limit usages */
168 ZS_MAXOF(old->zsz_usage_ram, new->zsz_usage_ram);
169 ZS_MAXOF(old->zsz_usage_locked, new->zsz_usage_locked);
170 ZS_MAXOF(old->zsz_usage_ram, new->zsz_usage_ram);
171
172 ZS_MAXOF(old->zsz_processes, new->zsz_processes);
173 ZS_MAXOF(old->zsz_lwps, new->zsz_lwps);
174 ZS_MAXOF(old->zsz_shm, new->zsz_shm);
175 ZS_MAXOF(old->zsz_shmids, new->zsz_shmids);
176 ZS_MAXOF(old->zsz_semids, new->zsz_semids);
177 ZS_MAXOF(old->zsz_msgids, new->zsz_msgids);
178 ZS_MAXOF(old->zsz_lofi, new->zsz_lofi);
179
180 ZS_MAXOF(old->zsz_cpus_online, new->zsz_cpus_online);
181
182 ZS_MAXOFTS(old->zsz_cpu_usage, new->zsz_cpu_usage);
183 ZS_MAXOFTS(old->zsz_pset_time, new->zsz_pset_time);
184 ZS_MAXOFTS(old->zsz_cap_time, new->zsz_cap_time);
185 ZS_MAXOFTS(old->zsz_share_time, new->zsz_share_time);
186 return;
187 }
188
189 ZS_ADD_CAP(old->zsz_cpu_cap, new->zsz_cpu_cap);
190 ZS_ADD_CAP(old->zsz_ram_cap, new->zsz_ram_cap);
191 ZS_ADD_CAP(old->zsz_locked_cap, new->zsz_locked_cap);
192 ZS_ADD_CAP(old->zsz_vm_cap, new->zsz_vm_cap);
193 ZS_ADD_CAP(old->zsz_processes_cap, new->zsz_processes_cap);
194 ZS_ADD_CAP(old->zsz_lwps_cap, new->zsz_lwps_cap);
195 ZS_ADD_CAP(old->zsz_shm_cap, new->zsz_shm_cap);
196 ZS_ADD_CAP(old->zsz_shmids_cap, new->zsz_shmids_cap);
197 ZS_ADD_CAP(old->zsz_semids_cap, new->zsz_semids_cap);
198 ZS_ADD_CAP(old->zsz_msgids_cap, new->zsz_msgids_cap);
199 ZS_ADD_CAP(old->zsz_lofi_cap, new->zsz_lofi_cap);
200
201 /* Add in memory and limit usages */
202 old->zsz_usage_ram += new->zsz_usage_ram;
203 old->zsz_usage_locked += new->zsz_usage_locked;
204 old->zsz_usage_vm += new->zsz_usage_vm;
205
206 old->zsz_processes += new->zsz_processes;
207 old->zsz_lwps += new->zsz_lwps;
208 old->zsz_shm += new->zsz_shm;
209 old->zsz_shmids += new->zsz_shmids;
210 old->zsz_semids += new->zsz_semids;
211 old->zsz_msgids += new->zsz_msgids;
212 old->zsz_lofi += new->zsz_lofi;
213
214 old->zsz_cpus_online += new->zsz_cpus_online;
215 old->zsz_cpu_shares += new->zsz_cpu_shares;
216
217 TIMESTRUC_ADD_TIMESTRUC(old->zsz_cpu_usage, new->zsz_cpu_usage);
218 TIMESTRUC_ADD_TIMESTRUC(old->zsz_pset_time, new->zsz_pset_time);
219 TIMESTRUC_ADD_TIMESTRUC(old->zsz_cap_time, new->zsz_cap_time);
220 TIMESTRUC_ADD_TIMESTRUC(old->zsz_share_time, new->zsz_share_time);
221 }
222
223 static int
zs_usage_compute_zones(zs_usage_t * ures,zs_usage_t * uold,zs_usage_t * unew,int func)224 zs_usage_compute_zones(zs_usage_t *ures, zs_usage_t *uold, zs_usage_t *unew,
225 int func)
226 {
227 zs_system_t *sres;
228 zs_zone_t *zold, *znew, *zres;
229
230 sres = ures->zsu_system;
231 /*
232 * Walk zones, assume lists are always sorted the same. Include
233 * all zones that exist in the new usage.
234 */
235 zold = list_head(&uold->zsu_zone_list);
236 znew = list_head(&unew->zsu_zone_list);
237
238 while (zold != NULL && znew != NULL) {
239
240 int cmp;
241
242 cmp = strcmp(zold->zsz_name, znew->zsz_name);
243 if (cmp > 0) {
244 /*
245 * Old interval does not contain zone in new
246 * interval. Zone is new. Add zone to result.
247 */
248 if (ures != unew) {
249 zres = (zs_zone_t *)calloc(sizeof (zs_zone_t),
250 1);
251 if (zres == NULL)
252 return (-1);
253 *zres = *znew;
254
255 zres->zsz_system = sres;
256 list_link_init(&zres->zsz_next);
257 zres->zsz_intervals = 0;
258 if (ures == uold)
259 list_insert_before(&uold->zsu_zone_list,
260 zold, zres);
261 else
262 list_insert_tail(&ures->zsu_zone_list,
263 zres);
264
265 } else {
266 zres = znew;
267 }
268
269 if (func == ZS_COMPUTE_USAGE_AVERAGE)
270 zres->zsz_intervals++;
271
272 znew = list_next(&unew->zsu_zone_list, znew);
273 continue;
274
275 } else if (cmp < 0) {
276 /*
277 * Start interval contains zones that is not in the
278 * end interval. This zone is gone. Leave zone in
279 * old usage, but do not add it to result usage
280 */
281 zold = list_next(&uold->zsu_zone_list, zold);
282 continue;
283 }
284
285 /* Zone is in both start and end interval. Compute interval */
286 if (ures == uold) {
287 zres = zold;
288 } else if (ures == unew) {
289 zres = znew;
290 } else {
291 /* add zone to new usage */
292 zres = (zs_zone_t *)calloc(sizeof (zs_zone_t), 1);
293 if (zres == NULL)
294 return (-1);
295 *zres = *znew;
296 zres->zsz_system = sres;
297 list_insert_tail(&ures->zsu_zone_list, zres);
298 }
299 if (func == ZS_COMPUTE_USAGE_AVERAGE)
300 zres->zsz_intervals++;
301 if (func == ZS_COMPUTE_USAGE_INTERVAL) {
302 /*
303 * If zone is in the old interval, but has been
304 * rebooted, don't subtract its old interval usage
305 */
306 if (zres->zsz_hrstart > uold->zsu_hrtime) {
307 znew = list_next(&unew->zsu_zone_list, znew);
308 zold = list_next(&uold->zsu_zone_list, zold);
309 continue;
310 }
311 TIMESTRUC_DELTA(zres->zsz_cpu_usage,
312 znew->zsz_cpu_usage, zold->zsz_cpu_usage);
313 TIMESTRUC_DELTA(zres->zsz_cap_time, znew->zsz_cap_time,
314 zold->zsz_cap_time);
315 TIMESTRUC_DELTA(zres->zsz_share_time,
316 znew->zsz_share_time, zold->zsz_share_time);
317 TIMESTRUC_DELTA(zres->zsz_pset_time,
318 znew->zsz_pset_time, zold->zsz_pset_time);
319 } else {
320 zs_zone_add_usage(zres, znew, func);
321 }
322 znew = list_next(&unew->zsu_zone_list, znew);
323 zold = list_next(&uold->zsu_zone_list, zold);
324 }
325
326 if (ures == unew)
327 return (0);
328
329 /* Add in any remaining zones in the new interval */
330 while (znew != NULL) {
331 zres = (zs_zone_t *)calloc(sizeof (zs_zone_t), 1);
332 if (zres == NULL)
333 return (-1);
334 *zres = *znew;
335 zres->zsz_system = sres;
336 if (func == ZS_COMPUTE_USAGE_AVERAGE)
337 zres->zsz_intervals++;
338 if (ures == uold)
339 list_insert_tail(&uold->zsu_zone_list, zres);
340 else
341 list_insert_tail(&ures->zsu_zone_list, zres);
342
343 znew = list_next(&unew->zsu_zone_list, znew);
344 }
345 return (0);
346 }
347
348 static void
zs_pset_zone_add_usage(zs_pset_zone_t * old,zs_pset_zone_t * new,int func)349 zs_pset_zone_add_usage(zs_pset_zone_t *old, zs_pset_zone_t *new, int func)
350 {
351 if (func == ZS_COMPUTE_USAGE_HIGH) {
352 ZS_MAXOF(old->zspz_cpu_shares, new->zspz_cpu_shares);
353 ZS_MAXOFTS(old->zspz_cpu_usage, new->zspz_cpu_usage);
354 return;
355 }
356 old->zspz_cpu_shares += new->zspz_cpu_shares;
357 TIMESTRUC_ADD_TIMESTRUC(old->zspz_cpu_usage, new->zspz_cpu_usage);
358 }
359
360 static int
zs_usage_compute_pset_usage(zs_usage_t * uold,zs_usage_t * ures,zs_pset_t * pres,zs_pset_t * pold,zs_pset_t * pnew,int func)361 zs_usage_compute_pset_usage(zs_usage_t *uold, zs_usage_t *ures,
362 zs_pset_t *pres, zs_pset_t *pold, zs_pset_t *pnew, int func)
363 {
364 zs_pset_zone_t *puold, *punew, *pures;
365
366 /*
367 * Walk psets usages, assume lists are always sorted the same. Include
368 * all pset usages that exist in the new pset.
369 */
370 if (pold == NULL)
371 puold = NULL;
372 else
373 puold = list_head(&pold->zsp_usage_list);
374 punew = list_head(&pnew->zsp_usage_list);
375
376 while (puold != NULL && punew != NULL) {
377
378 int cmp;
379
380 cmp = strcmp(puold->zspz_zone->zsz_name,
381 punew->zspz_zone->zsz_name);
382 if (cmp > 0) {
383 /*
384 * Old interval does not contain usage new
385 * interval. Usage is new.
386 */
387 if (pres != pnew) {
388 pures = (zs_pset_zone_t *)malloc(
389 sizeof (zs_pset_zone_t));
390 if (pures == NULL)
391 return (-1);
392 *pures = *punew;
393
394 pures->zspz_pset = pres;
395 pures->zspz_zone = zs_lookup_zone_byname(ures,
396 punew->zspz_zone->zsz_name);
397 assert(pures->zspz_zone != NULL);
398 pures->zspz_intervals = 0;
399 if (pres == pold)
400 list_insert_before(
401 &pold->zsp_usage_list, puold,
402 pures);
403 else
404 list_insert_tail(&pres->zsp_usage_list,
405 pures);
406 } else {
407 pures = punew;
408 }
409 if (func == ZS_COMPUTE_USAGE_AVERAGE)
410 pures->zspz_intervals++;
411 else if (func == ZS_COMPUTE_USAGE_TOTAL) {
412 /* Add pset's time so far to the zone usage */
413 TIMESTRUC_ADD_TIMESTRUC(
414 pures->zspz_zone->zsz_pset_time,
415 pres->zsp_total_time);
416 pures->zspz_zone->zsz_cpus_online +=
417 pres->zsp_online;
418 }
419
420 punew = list_next(&pnew->zsp_usage_list, punew);
421 continue;
422 } else if (cmp < 0) {
423
424 /*
425 * Old interval contains pset_zone that is not in the
426 * new interval. This zone is no longer using the
427 * pset. Leave pset_zone in old interval, but do not
428 * add it to result usage.
429 *
430 * For total utilization, add pset time to zone that
431 * has run in this pset before.
432 */
433 if (func == ZS_COMPUTE_USAGE_TOTAL) {
434 /* Add new pset time to the zone usage */
435 TIMESTRUC_ADD_TIMESTRUC(
436 puold->zspz_zone->zsz_pset_time,
437 pnew->zsp_total_time);
438 puold->zspz_zone->zsz_cpus_online +=
439 pnew->zsp_online;
440 }
441 puold = list_next(&pold->zsp_usage_list, puold);
442 continue;
443 }
444 /*
445 * Zone is using pset in both start and end interval. Compute
446 * interval
447 */
448 if (pres == pold) {
449 pures = puold;
450 } else if (pres == pnew) {
451 pures = punew;
452 } else {
453 pures = (zs_pset_zone_t *)malloc(
454 sizeof (zs_pset_zone_t));
455 if (pures == NULL)
456 return (-1);
457 *pures = *punew;
458 pures->zspz_pset = pres;
459 pures->zspz_zone = zs_lookup_zone_byname(ures,
460 punew->zspz_zone->zsz_name);
461 assert(pures->zspz_zone != NULL);
462 list_insert_tail(&pres->zsp_usage_list, pures);
463 }
464 if (func == ZS_COMPUTE_USAGE_AVERAGE)
465 pures->zspz_intervals++;
466
467 if (func == ZS_COMPUTE_USAGE_INTERVAL) {
468 /*
469 * If pset usage has been destroyed and re-created
470 * since start interval, don't subtract the start
471 * interval.
472 */
473 if (punew->zspz_hrstart > uold->zsu_hrtime) {
474 punew = list_next(&pnew->zsp_usage_list, punew);
475 puold = list_next(&pold->zsp_usage_list, puold);
476 continue;
477 }
478 TIMESTRUC_DELTA(pures->zspz_cpu_usage,
479 punew->zspz_cpu_usage, puold->zspz_cpu_usage);
480 } else {
481 zs_pset_zone_add_usage(pures, punew, func);
482 }
483 punew = list_next(&pnew->zsp_usage_list, punew);
484 puold = list_next(&pold->zsp_usage_list, puold);
485 }
486 if (func == ZS_COMPUTE_USAGE_TOTAL) {
487 while (puold != NULL) {
488 TIMESTRUC_ADD_TIMESTRUC(
489 puold->zspz_zone->zsz_pset_time,
490 pnew->zsp_total_time);
491 puold->zspz_zone->zsz_cpus_online +=
492 pnew->zsp_online;
493 puold = list_next(&pold->zsp_usage_list, puold);
494 }
495 }
496
497 /* No need to add new pset zone usages if result pset is new pset */
498 if (pres == pnew)
499 return (0);
500
501 /* Add in any remaining new psets in the new interval */
502 while (punew != NULL) {
503 pures = (zs_pset_zone_t *)calloc(sizeof (zs_pset_zone_t), 1);
504 if (pures == NULL)
505 return (-1);
506 *pures = *punew;
507 pures->zspz_pset = pres;
508 pures->zspz_zone = zs_lookup_zone_byname(ures,
509 punew->zspz_zone->zsz_name);
510 assert(pures->zspz_zone != NULL);
511 if (func == ZS_COMPUTE_USAGE_AVERAGE)
512 pures->zspz_intervals++;
513 if (pres == pold)
514 list_insert_tail(&pold->zsp_usage_list, pures);
515 else
516 list_insert_tail(&pres->zsp_usage_list, pures);
517
518 punew = list_next(&pnew->zsp_usage_list, punew);
519 }
520 return (0);
521 }
522
523 static void
zs_pset_add_usage(zs_pset_t * old,zs_pset_t * new,int func)524 zs_pset_add_usage(zs_pset_t *old, zs_pset_t *new, int func)
525 {
526
527 if (func == ZS_COMPUTE_USAGE_HIGH) {
528 ZS_MAXOF(old->zsp_online, new->zsp_online);
529 ZS_MAXOF(old->zsp_size, new->zsp_size);
530 ZS_MAXOF(old->zsp_min, new->zsp_min);
531 ZS_MAXOF(old->zsp_max, new->zsp_max);
532 ZS_MAXOF(old->zsp_importance, new->zsp_importance);
533 ZS_MAXOF(old->zsp_cpu_shares, new->zsp_cpu_shares);
534 ZS_MAXOFTS(old->zsp_total_time, new->zsp_total_time);
535 ZS_MAXOFTS(old->zsp_usage_kern, new->zsp_usage_kern);
536 ZS_MAXOFTS(old->zsp_usage_zones, new->zsp_usage_zones);
537 return;
538 }
539 old->zsp_online += new->zsp_online;
540 old->zsp_size += new->zsp_size;
541 old->zsp_min += new->zsp_min;
542 old->zsp_max += new->zsp_max;
543 old->zsp_importance += new->zsp_importance;
544 old->zsp_cpu_shares += new->zsp_cpu_shares;
545 TIMESTRUC_ADD_TIMESTRUC(old->zsp_total_time, new->zsp_total_time);
546 TIMESTRUC_ADD_TIMESTRUC(old->zsp_usage_kern, new->zsp_usage_kern);
547 TIMESTRUC_ADD_TIMESTRUC(old->zsp_usage_zones, new->zsp_usage_zones);
548 }
549
550 static int
zs_usage_compute_psets(zs_usage_t * ures,zs_usage_t * uold,zs_usage_t * unew,int func)551 zs_usage_compute_psets(zs_usage_t *ures, zs_usage_t *uold, zs_usage_t *unew,
552 int func)
553 {
554 zs_pset_t *pold, *pnew, *pres;
555
556 /*
557 * Walk psets, assume lists are always sorted the same. Include
558 * all psets that exist at the end of the interval.
559 */
560 pold = list_head(&uold->zsu_pset_list);
561 pnew = list_head(&unew->zsu_pset_list);
562
563 while (pold != NULL && pnew != NULL) {
564
565 int cmp;
566
567 cmp = strcmp(pold->zsp_name, pnew->zsp_name);
568 if (cmp > 0) {
569 /*
570 * Old interval does not contain pset in new
571 * interval. Pset is new.
572 */
573 if (ures != unew) {
574 pres = (zs_pset_t *)malloc(sizeof (zs_pset_t));
575 if (pres == NULL)
576 return (-1);
577 *pres = *pnew;
578 pres->zsp_intervals = 0;
579 list_create(&pres->zsp_usage_list,
580 sizeof (zs_pset_zone_t),
581 offsetof(zs_pset_zone_t, zspz_next));
582
583 if (ures == uold)
584 list_insert_before(&uold->zsu_pset_list,
585 pold, pres);
586 else
587 list_insert_tail(&ures->zsu_pset_list,
588 pres);
589
590 } else {
591 pres = pnew;
592 }
593 if (zs_usage_compute_pset_usage(uold, ures, pres,
594 NULL, pnew, func) != 0)
595 return (-1);
596
597 if (func == ZS_COMPUTE_USAGE_AVERAGE ||
598 func == ZS_COMPUTE_USAGE_TOTAL)
599 pres->zsp_intervals++;
600 pnew = list_next(&unew->zsu_pset_list, pnew);
601 continue;
602
603 } else if (cmp < 0) {
604 /*
605 * Start interval contains psets that is not in the
606 * end interval. This pset is gone. Leave pset in
607 * old usage, but do not add it to result usage.
608 */
609 pold = list_next(&uold->zsu_pset_list, pold);
610 continue;
611 }
612
613 /* Pset is in both start and end interval. Compute interval */
614 if (ures == uold) {
615 pres = pold;
616 } else if (ures == unew) {
617 pres = pnew;
618 } else {
619 pres = (zs_pset_t *)calloc(sizeof (zs_pset_t), 1);
620 if (pres == NULL)
621 return (-1);
622
623 *pres = *pnew;
624 list_create(&pres->zsp_usage_list,
625 sizeof (zs_pset_zone_t),
626 offsetof(zs_pset_zone_t, zspz_next));
627 list_insert_tail(&ures->zsu_pset_list, pres);
628 }
629 if (func == ZS_COMPUTE_USAGE_AVERAGE ||
630 func == ZS_COMPUTE_USAGE_TOTAL)
631 pres->zsp_intervals++;
632 if (func == ZS_COMPUTE_USAGE_INTERVAL) {
633 /*
634 * If pset as been destroyed and re-created since start
635 * interval, don't subtract the start interval.
636 */
637 if (pnew->zsp_hrstart > uold->zsu_hrtime) {
638 goto usages;
639 }
640 TIMESTRUC_DELTA(pres->zsp_total_time,
641 pnew->zsp_total_time, pold->zsp_total_time);
642
643 TIMESTRUC_DELTA(pres->zsp_usage_kern,
644 pnew->zsp_usage_kern, pold->zsp_usage_kern);
645 TIMESTRUC_DELTA(pres->zsp_usage_zones,
646 pnew->zsp_usage_zones, pold->zsp_usage_zones);
647 } else {
648 zs_pset_add_usage(pres, pnew, func);
649 }
650 usages:
651 if (zs_usage_compute_pset_usage(uold, ures, pres, pold,
652 pnew, func) != 0)
653 return (-1);
654
655 pnew = list_next(&unew->zsu_pset_list, pnew);
656 pold = list_next(&uold->zsu_pset_list, pold);
657 }
658
659 if (ures == unew)
660 return (0);
661
662 /* Add in any remaining psets in the new interval */
663 while (pnew != NULL) {
664 pres = (zs_pset_t *)calloc(sizeof (zs_pset_t), 1);
665 if (pres == NULL)
666 return (-1);
667 *pres = *pnew;
668 list_create(&pres->zsp_usage_list,
669 sizeof (zs_pset_zone_t),
670 offsetof(zs_pset_zone_t, zspz_next));
671 if (func == ZS_COMPUTE_USAGE_AVERAGE ||
672 func == ZS_COMPUTE_USAGE_TOTAL)
673 pres->zsp_intervals++;
674 if (ures == uold)
675 list_insert_tail(&uold->zsu_pset_list, pres);
676 else
677 list_insert_tail(&ures->zsu_pset_list, pres);
678
679 if (zs_usage_compute_pset_usage(uold, ures, pres, NULL,
680 pnew, func) != 0)
681 return (-1);
682
683 pnew = list_next(&unew->zsu_pset_list, pnew);
684 }
685 return (0);
686 }
687
688 static int
zs_zone_name(zs_zone_t * zone,char * name,size_t len)689 zs_zone_name(zs_zone_t *zone, char *name, size_t len)
690 {
691 return (strlcpy(name, zone->zsz_name, len));
692 }
693
694 static zoneid_t
zs_zone_id(zs_zone_t * zone)695 zs_zone_id(zs_zone_t *zone)
696 {
697 return (zone->zsz_id);
698 }
699
700 static uint_t
zs_zone_iptype(zs_zone_t * zone)701 zs_zone_iptype(zs_zone_t *zone)
702 {
703 return (zone->zsz_iptype);
704 }
705
706 static uint_t
zs_zone_cputype(zs_zone_t * zone)707 zs_zone_cputype(zs_zone_t *zone)
708 {
709 return (zone->zsz_cputype);
710 }
711
712 static int
zs_zone_poolname(zs_zone_t * zone,char * name,size_t len)713 zs_zone_poolname(zs_zone_t *zone, char *name, size_t len)
714 {
715 return (strlcpy(name, zone->zsz_pool, len));
716 }
717
718 static int
zs_zone_psetname(zs_zone_t * zone,char * name,size_t len)719 zs_zone_psetname(zs_zone_t *zone, char *name, size_t len)
720 {
721 return (strlcpy(name, zone->zsz_pset, len));
722 }
723
724 static uint_t
zs_zone_schedulers(zs_zone_t * zone)725 zs_zone_schedulers(zs_zone_t *zone)
726 {
727 return (zone->zsz_scheds);
728 }
729
730 static uint64_t
zs_ts_used_scale(timestruc_t * total,timestruc_t * used,uint64_t scale,boolean_t cap_at_100)731 zs_ts_used_scale(timestruc_t *total, timestruc_t *used, uint64_t scale,
732 boolean_t cap_at_100)
733 {
734 double dtotal, dused, pct, dscale;
735
736 /* If no time yet, treat as zero */
737 if (total->tv_sec == 0 && total->tv_nsec == 0)
738 return (0);
739
740 dtotal = (double)total->tv_sec +
741 ((double)total->tv_nsec / (double)NANOSEC);
742 dused = (double)used->tv_sec +
743 ((double)used->tv_nsec / (double)NANOSEC);
744
745 dscale = (double)scale;
746 pct = dused / dtotal * dscale;
747 if (cap_at_100 && pct > dscale)
748 pct = dscale;
749
750 return ((uint_t)pct);
751 }
752
753 /*
754 * Convert total and used time into percent used.
755 */
756 static uint_t
zs_ts_used_pct(timestruc_t * total,timestruc_t * used,boolean_t cap_at_100)757 zs_ts_used_pct(timestruc_t *total, timestruc_t *used, boolean_t cap_at_100)
758 {
759 return ((uint_t)zs_ts_used_scale(total, used, ZSD_PCT_INT, cap_at_100));
760 }
761
762 /*
763 * Convert total and used time, plus number of cpus, into number of cpus
764 * used, where 100 equals 1 cpu used.
765 */
766 static uint64_t
zs_ts_used_cpus(timestruc_t * total,timestruc_t * used,uint_t ncpus,boolean_t cap_at_100)767 zs_ts_used_cpus(timestruc_t *total, timestruc_t *used, uint_t ncpus,
768 boolean_t cap_at_100)
769 {
770 return (zs_ts_used_scale(total, used, ncpus * ZSD_ONE_CPU, cap_at_100));
771 }
772
773 static uint64_t
zs_zone_cpu_shares(zs_zone_t * zone)774 zs_zone_cpu_shares(zs_zone_t *zone)
775 {
776 /* No processes found in FSS */
777 if ((zone->zsz_scheds & ZS_SCHED_FSS) == 0)
778 return (ZS_LIMIT_NONE);
779
780 return (zone->zsz_cpu_shares);
781 }
782
783 static uint64_t
zs_zone_cpu_cap(zs_zone_t * zone)784 zs_zone_cpu_cap(zs_zone_t *zone)
785 {
786 return (zone->zsz_cpu_cap);
787 }
788
789 static uint64_t
zs_zone_cpu_cap_used(zs_zone_t * zone)790 zs_zone_cpu_cap_used(zs_zone_t *zone)
791 {
792 if (zone->zsz_cpu_cap == ZS_LIMIT_NONE)
793 return (ZS_LIMIT_NONE);
794
795 return (zs_ts_used_cpus(&zone->zsz_cap_time, &zone->zsz_cpu_usage,
796 zone->zsz_cpus_online, B_TRUE));
797 }
798
799 static uint64_t
zs_zone_cpu_shares_used(zs_zone_t * zone)800 zs_zone_cpu_shares_used(zs_zone_t *zone)
801 {
802 if (zone->zsz_cpu_shares == ZS_LIMIT_NONE)
803 return (ZS_LIMIT_NONE);
804
805 if (zone->zsz_cpu_shares == ZS_SHARES_UNLIMITED)
806 return (ZS_LIMIT_NONE);
807
808 if ((zone->zsz_scheds & ZS_SCHED_FSS) == 0)
809 return (ZS_LIMIT_NONE);
810
811 return (zs_ts_used_scale(&zone->zsz_share_time, &zone->zsz_cpu_usage,
812 zone->zsz_cpu_shares, B_FALSE));
813 }
814
815 static void
zs_zone_cpu_cap_time(zs_zone_t * zone,timestruc_t * ts)816 zs_zone_cpu_cap_time(zs_zone_t *zone, timestruc_t *ts)
817 {
818 *ts = zone->zsz_cap_time;
819 }
820
821 static void
zs_zone_cpu_share_time(zs_zone_t * zone,timestruc_t * ts)822 zs_zone_cpu_share_time(zs_zone_t *zone, timestruc_t *ts)
823 {
824 *ts = zone->zsz_share_time;
825 }
826
827 static void
zs_zone_cpu_cap_time_used(zs_zone_t * zone,timestruc_t * ts)828 zs_zone_cpu_cap_time_used(zs_zone_t *zone, timestruc_t *ts)
829 {
830 *ts = zone->zsz_cpu_usage;
831 }
832
833 static void
zs_zone_cpu_share_time_used(zs_zone_t * zone,timestruc_t * ts)834 zs_zone_cpu_share_time_used(zs_zone_t *zone, timestruc_t *ts)
835 {
836 *ts = zone->zsz_cpu_usage;
837 }
838
839
840 static uint64_t
zs_uint64_used_scale(uint64_t total,uint64_t used,uint64_t scale,boolean_t cap_at_100)841 zs_uint64_used_scale(uint64_t total, uint64_t used, uint64_t scale,
842 boolean_t cap_at_100)
843 {
844 double dtotal, dused, pct, dscale;
845
846 /* If no time yet, treat as zero */
847 if (total == 0)
848 return (0);
849
850 dtotal = (double)total;
851 dused = (double)used;
852
853 dscale = (double)scale;
854 pct = dused / dtotal * dscale;
855 if (cap_at_100 && pct > dscale)
856 pct = dscale;
857
858 return ((uint64_t)pct);
859 }
860
861 /*
862 * Convert a total and used value into a percent used.
863 */
864 static uint_t
zs_uint64_used_pct(uint64_t total,uint64_t used,boolean_t cap_at_100)865 zs_uint64_used_pct(uint64_t total, uint64_t used, boolean_t cap_at_100)
866 {
867 return ((uint_t)zs_uint64_used_scale(total, used, ZSD_PCT_INT,
868 cap_at_100));
869 }
870
871 static uint_t
zs_zone_cpu_cap_pct(zs_zone_t * zone)872 zs_zone_cpu_cap_pct(zs_zone_t *zone)
873 {
874 if (zone->zsz_cpu_cap == ZS_LIMIT_NONE)
875 return (ZS_PCT_NONE);
876
877 return (zs_ts_used_pct(&zone->zsz_cap_time, &zone->zsz_cpu_usage,
878 B_TRUE));
879 }
880
881 static uint_t
zs_zone_cpu_shares_pct(zs_zone_t * zone)882 zs_zone_cpu_shares_pct(zs_zone_t *zone)
883 {
884 if (zone->zsz_cpu_shares == ZS_LIMIT_NONE)
885 return (ZS_PCT_NONE);
886
887 if (zone->zsz_cpu_shares == ZS_SHARES_UNLIMITED)
888 return (ZS_PCT_NONE);
889
890 if ((zone->zsz_scheds & ZS_SCHED_FSS) == 0)
891 return (ZS_PCT_NONE);
892
893 return (zs_ts_used_pct(&zone->zsz_share_time, &zone->zsz_cpu_usage,
894 B_FALSE));
895 }
896
897 static uint64_t
zs_zone_physical_memory_cap(zs_zone_t * zone)898 zs_zone_physical_memory_cap(zs_zone_t *zone)
899 {
900 return (zone->zsz_ram_cap);
901 }
902
903 static uint64_t
zs_zone_virtual_memory_cap(zs_zone_t * zone)904 zs_zone_virtual_memory_cap(zs_zone_t *zone)
905 {
906 return (zone->zsz_vm_cap);
907 }
908
909 static uint64_t
zs_zone_locked_memory_cap(zs_zone_t * zone)910 zs_zone_locked_memory_cap(zs_zone_t *zone)
911 {
912 return (zone->zsz_locked_cap);
913 }
914
915 static uint64_t
zs_zone_physical_memory_cap_used(zs_zone_t * zone)916 zs_zone_physical_memory_cap_used(zs_zone_t *zone)
917 {
918 if (zone->zsz_ram_cap == ZS_LIMIT_NONE)
919 return (ZS_LIMIT_NONE);
920
921 return (zone->zsz_usage_ram);
922 }
923
924 static uint64_t
zs_zone_virtual_memory_cap_used(zs_zone_t * zone)925 zs_zone_virtual_memory_cap_used(zs_zone_t *zone)
926 {
927 if (zone->zsz_vm_cap == ZS_LIMIT_NONE)
928 return (ZS_LIMIT_NONE);
929
930 return (zone->zsz_usage_vm);
931 }
932
933 static uint64_t
zs_zone_locked_memory_cap_used(zs_zone_t * zone)934 zs_zone_locked_memory_cap_used(zs_zone_t *zone)
935 {
936 if (zone->zsz_locked_cap == ZS_LIMIT_NONE)
937 return (ZS_LIMIT_NONE);
938
939 return (zone->zsz_usage_locked);
940 }
941
942 static int
zs_pset_name(zs_pset_t * pset,char * name,size_t len)943 zs_pset_name(zs_pset_t *pset, char *name, size_t len)
944 {
945 return (strlcpy(name, pset->zsp_name, len));
946 }
947
948 static psetid_t
zs_pset_id(zs_pset_t * pset)949 zs_pset_id(zs_pset_t *pset)
950 {
951 return (pset->zsp_id);
952 }
953
954 static uint64_t
zs_pset_size(zs_pset_t * pset)955 zs_pset_size(zs_pset_t *pset)
956 {
957 return (pset->zsp_size);
958 }
959
960 static uint64_t
zs_pset_online(zs_pset_t * pset)961 zs_pset_online(zs_pset_t *pset)
962 {
963 return (pset->zsp_online);
964 }
965
966 uint64_t
zs_pset_min(zs_pset_t * pset)967 zs_pset_min(zs_pset_t *pset)
968 {
969 return (pset->zsp_min);
970 }
971
972 uint64_t
zs_pset_max(zs_pset_t * pset)973 zs_pset_max(zs_pset_t *pset)
974 {
975 return (pset->zsp_max);
976 }
977
978 static uint_t
zs_pset_schedulers(zs_pset_t * pset)979 zs_pset_schedulers(zs_pset_t *pset)
980 {
981 return (pset->zsp_scheds);
982 }
983
984 static uint_t
zs_pset_zone_schedulers(zs_pset_zone_t * pz)985 zs_pset_zone_schedulers(zs_pset_zone_t *pz)
986 {
987 return (pz->zspz_scheds);
988 }
989
990 static uint64_t
zs_pset_cpu_shares(zs_pset_t * pset)991 zs_pset_cpu_shares(zs_pset_t *pset)
992 {
993 if (!(pset->zsp_scheds & ZS_SCHED_FSS))
994 return (ZS_LIMIT_NONE);
995
996 return (pset->zsp_cpu_shares);
997 }
998
999 static uint64_t
zs_pset_zone_cpu_shares(zs_pset_zone_t * pz)1000 zs_pset_zone_cpu_shares(zs_pset_zone_t *pz)
1001 {
1002 if (!(pz->zspz_scheds & ZS_SCHED_FSS))
1003 return (ZS_LIMIT_NONE);
1004
1005 return (pz->zspz_cpu_shares);
1006 }
1007
1008 static uint_t
zs_pset_cputype(zs_pset_t * pset)1009 zs_pset_cputype(zs_pset_t *pset)
1010 {
1011 return (pset->zsp_cputype);
1012 }
1013
1014 static void
zs_pset_usage_all(zs_pset_t * pset,timestruc_t * ts)1015 zs_pset_usage_all(zs_pset_t *pset, timestruc_t *ts)
1016 {
1017 timestruc_t tot;
1018
1019 tot = pset->zsp_usage_kern;
1020 TIMESTRUC_ADD_TIMESTRUC(tot, pset->zsp_usage_zones);
1021 *ts = tot;
1022 }
1023
1024 static void
zs_pset_usage_idle(zs_pset_t * pset,timestruc_t * ts)1025 zs_pset_usage_idle(zs_pset_t *pset, timestruc_t *ts)
1026 {
1027 timestruc_t tot, time, idle;
1028
1029 tot = pset->zsp_usage_kern;
1030 TIMESTRUC_ADD_TIMESTRUC(tot, pset->zsp_usage_zones);
1031 time = pset->zsp_total_time;
1032 TIMESTRUC_DELTA(idle, time, tot);
1033 *ts = idle;
1034 }
1035
1036 static void
zs_pset_usage_kernel(zs_pset_t * pset,timestruc_t * ts)1037 zs_pset_usage_kernel(zs_pset_t *pset, timestruc_t *ts)
1038 {
1039 *ts = pset->zsp_usage_kern;
1040 }
1041
1042 static void
zs_pset_usage_zones(zs_pset_t * pset,timestruc_t * ts)1043 zs_pset_usage_zones(zs_pset_t *pset, timestruc_t *ts)
1044 {
1045 *ts = pset->zsp_usage_zones;
1046 }
1047
1048 static uint_t
zs_pset_usage_all_pct(zs_pset_t * pset)1049 zs_pset_usage_all_pct(zs_pset_t *pset)
1050 {
1051 timestruc_t tot;
1052
1053 tot = pset->zsp_usage_kern;
1054 TIMESTRUC_ADD_TIMESTRUC(tot, pset->zsp_usage_zones);
1055
1056 return (zs_ts_used_pct(&pset->zsp_total_time, &tot, B_TRUE));
1057 }
1058
1059 static uint_t
zs_pset_usage_idle_pct(zs_pset_t * pset)1060 zs_pset_usage_idle_pct(zs_pset_t *pset)
1061 {
1062 timestruc_t tot, idle;
1063
1064 tot = pset->zsp_usage_kern;
1065 TIMESTRUC_ADD_TIMESTRUC(tot, pset->zsp_usage_zones);
1066 TIMESTRUC_DELTA(idle, pset->zsp_total_time, tot);
1067
1068 return (zs_ts_used_pct(&pset->zsp_total_time, &idle, B_TRUE));
1069 }
1070
1071 static uint_t
zs_pset_usage_kernel_pct(zs_pset_t * pset)1072 zs_pset_usage_kernel_pct(zs_pset_t *pset)
1073 {
1074 return (zs_ts_used_pct(&pset->zsp_total_time, &pset->zsp_usage_kern,
1075 B_TRUE));
1076 }
1077
1078 static uint_t
zs_pset_usage_zones_pct(zs_pset_t * pset)1079 zs_pset_usage_zones_pct(zs_pset_t *pset)
1080 {
1081 return (zs_ts_used_pct(&pset->zsp_total_time, &pset->zsp_usage_zones,
1082 B_TRUE));
1083 }
1084
1085 static uint_t
zs_pset_usage_all_cpus(zs_pset_t * pset)1086 zs_pset_usage_all_cpus(zs_pset_t *pset)
1087 {
1088 timestruc_t tot;
1089
1090 tot = pset->zsp_usage_kern;
1091 TIMESTRUC_ADD_TIMESTRUC(tot, pset->zsp_usage_zones);
1092 return (zs_ts_used_cpus(&pset->zsp_total_time, &tot, pset->zsp_online,
1093 B_TRUE));
1094 }
1095
1096 static uint_t
zs_pset_usage_idle_cpus(zs_pset_t * pset)1097 zs_pset_usage_idle_cpus(zs_pset_t *pset)
1098 {
1099 timestruc_t tot, idle;
1100
1101 tot = pset->zsp_usage_kern;
1102 TIMESTRUC_ADD_TIMESTRUC(tot, pset->zsp_usage_zones);
1103 TIMESTRUC_DELTA(idle, pset->zsp_total_time, tot);
1104
1105 return (zs_ts_used_cpus(&pset->zsp_total_time, &tot, pset->zsp_online,
1106 B_TRUE));
1107 }
1108
1109 static uint_t
zs_pset_usage_kernel_cpus(zs_pset_t * pset)1110 zs_pset_usage_kernel_cpus(zs_pset_t *pset)
1111 {
1112 return (zs_ts_used_cpus(&pset->zsp_total_time, &pset->zsp_usage_kern,
1113 pset->zsp_online, B_TRUE));
1114 }
1115
1116 static uint64_t
zs_pset_usage_zones_cpus(zs_pset_t * pset)1117 zs_pset_usage_zones_cpus(zs_pset_t *pset)
1118 {
1119 return (zs_ts_used_cpus(&pset->zsp_total_time, &pset->zsp_usage_zones,
1120 pset->zsp_online, B_TRUE));
1121 }
1122
1123 static void
zs_pset_zone_usage_time(zs_pset_zone_t * pz,timestruc_t * t)1124 zs_pset_zone_usage_time(zs_pset_zone_t *pz, timestruc_t *t)
1125 {
1126 *t = pz->zspz_cpu_usage;
1127 }
1128
1129 static uint_t
zs_pset_zone_usage_cpus(zs_pset_zone_t * pz)1130 zs_pset_zone_usage_cpus(zs_pset_zone_t *pz)
1131 {
1132 return (zs_ts_used_cpus(&pz->zspz_pset->zsp_total_time,
1133 &pz->zspz_cpu_usage, pz->zspz_pset->zsp_online, B_TRUE));
1134 }
1135
1136 static uint_t
zs_pset_zone_usage_pct_pset(zs_pset_zone_t * pz)1137 zs_pset_zone_usage_pct_pset(zs_pset_zone_t *pz)
1138 {
1139 return (zs_ts_used_pct(&pz->zspz_pset->zsp_total_time,
1140 &pz->zspz_cpu_usage, B_TRUE));
1141 }
1142
1143 static uint64_t
zs_pset_zone_cpu_cap(zs_pset_zone_t * pz)1144 zs_pset_zone_cpu_cap(zs_pset_zone_t *pz)
1145 {
1146 return (pz->zspz_zone->zsz_cpu_cap);
1147 }
1148
1149 static uint_t
zs_pset_zone_usage_pct_cpu_cap(zs_pset_zone_t * pz)1150 zs_pset_zone_usage_pct_cpu_cap(zs_pset_zone_t *pz)
1151 {
1152 zs_zone_t *zone = pz->zspz_zone;
1153
1154 if (zone->zsz_cpu_cap == ZS_LIMIT_NONE) {
1155 return (ZS_PCT_NONE);
1156 }
1157 return (zs_ts_used_pct(&zone->zsz_cap_time,
1158 &pz->zspz_cpu_usage, B_TRUE));
1159 }
1160
1161 /*
1162 * Return the fraction of total shares for a pset allocated to the zone.
1163 */
1164 static uint_t
zs_pset_zone_usage_pct_pset_shares(zs_pset_zone_t * pz)1165 zs_pset_zone_usage_pct_pset_shares(zs_pset_zone_t *pz)
1166 {
1167 zs_pset_t *pset = pz->zspz_pset;
1168
1169 if (!(pz->zspz_scheds & ZS_SCHED_FSS))
1170 return (ZS_PCT_NONE);
1171
1172 if (pz->zspz_cpu_shares == ZS_LIMIT_NONE)
1173 return (ZS_PCT_NONE);
1174
1175 if (pz->zspz_cpu_shares == ZS_SHARES_UNLIMITED)
1176 return (ZS_PCT_NONE);
1177
1178 if (pz->zspz_pset->zsp_cpu_shares == 0)
1179 return (0);
1180
1181 if (pz->zspz_cpu_shares == 0)
1182 return (0);
1183
1184 return (zs_uint64_used_pct(pset->zsp_cpu_shares, pz->zspz_cpu_shares,
1185 B_TRUE));
1186 }
1187
1188 /*
1189 * Of a zones shares, what percent of cpu time is it using. For instance,
1190 * if a zone has 50% of shares, and is using 50% of the cpu time, then it is
1191 * using 100% of its share.
1192 */
1193 static uint_t
zs_pset_zone_usage_pct_cpu_shares(zs_pset_zone_t * pz)1194 zs_pset_zone_usage_pct_cpu_shares(zs_pset_zone_t *pz)
1195 {
1196 timestruc_t tot, time;
1197 double sharefactor;
1198 double total;
1199 double used;
1200 double pct;
1201
1202 if (!(pz->zspz_scheds & ZS_SCHED_FSS))
1203 return (ZS_PCT_NONE);
1204
1205 if (pz->zspz_cpu_shares == ZS_LIMIT_NONE)
1206 return (ZS_PCT_NONE);
1207
1208 if (pz->zspz_cpu_shares == ZS_SHARES_UNLIMITED)
1209 return (ZS_PCT_NONE);
1210
1211 if (pz->zspz_cpu_shares == 0)
1212 return (ZS_PCT_NONE);
1213
1214 sharefactor = (double)zs_pset_zone_usage_pct_pset_shares(pz);
1215
1216 /* Common scaling function won't do sharefactor. */
1217 time = pz->zspz_pset->zsp_total_time;
1218 tot = pz->zspz_cpu_usage;
1219
1220 total = (double)time.tv_sec +
1221 ((double)time.tv_nsec / (double)NANOSEC);
1222 total = total * (sharefactor / ZSD_PCT_DOUBLE);
1223 used = (double)tot.tv_sec +
1224 ((double)tot.tv_nsec / (double)NANOSEC);
1225
1226 pct = used / total * ZSD_PCT_DOUBLE;
1227 /* Allow percent of share used to exceed 100% */
1228 return ((uint_t)pct);
1229 }
1230
1231 static void
zs_cpu_total_time(zs_usage_t * usage,timestruc_t * ts)1232 zs_cpu_total_time(zs_usage_t *usage, timestruc_t *ts)
1233 {
1234 *ts = usage->zsu_system->zss_cpu_total_time;
1235 }
1236
1237 static void
zs_cpu_usage_all(zs_usage_t * usage,timestruc_t * ts)1238 zs_cpu_usage_all(zs_usage_t *usage, timestruc_t *ts)
1239 {
1240 timestruc_t tot;
1241
1242 tot.tv_sec = 0;
1243 tot.tv_nsec = 0;
1244 TIMESTRUC_ADD_TIMESTRUC(tot, usage->zsu_system->zss_cpu_usage_kern);
1245 TIMESTRUC_ADD_TIMESTRUC(tot, usage->zsu_system->zss_cpu_usage_zones);
1246 *ts = tot;
1247 }
1248
1249 static void
zs_cpu_usage_idle(zs_usage_t * usage,timestruc_t * ts)1250 zs_cpu_usage_idle(zs_usage_t *usage, timestruc_t *ts)
1251 {
1252 timestruc_t tot, time, idle;
1253
1254 tot.tv_sec = 0;
1255 tot.tv_nsec = 0;
1256 tot = usage->zsu_system->zss_cpu_usage_kern;
1257 TIMESTRUC_ADD_TIMESTRUC(tot, usage->zsu_system->zss_cpu_usage_zones);
1258 time = usage->zsu_system->zss_cpu_total_time;
1259 TIMESTRUC_DELTA(idle, time, tot);
1260 *ts = idle;
1261 }
1262
1263 static uint_t
zs_cpu_usage_all_pct(zs_usage_t * usage)1264 zs_cpu_usage_all_pct(zs_usage_t *usage)
1265 {
1266 timestruc_t tot;
1267
1268 tot = usage->zsu_system->zss_cpu_usage_kern;
1269 TIMESTRUC_ADD_TIMESTRUC(tot, usage->zsu_system->zss_cpu_usage_zones);
1270
1271 return (zs_ts_used_pct(&usage->zsu_system->zss_cpu_total_time,
1272 &tot, B_TRUE));
1273 }
1274
1275
1276 static uint_t
zs_cpu_usage_idle_pct(zs_usage_t * usage)1277 zs_cpu_usage_idle_pct(zs_usage_t *usage)
1278 {
1279 timestruc_t tot, idle;
1280
1281 tot = usage->zsu_system->zss_cpu_usage_kern;
1282 TIMESTRUC_ADD_TIMESTRUC(tot, usage->zsu_system->zss_cpu_usage_zones);
1283 TIMESTRUC_DELTA(idle, usage->zsu_system->zss_cpu_total_time, tot);
1284
1285 return (zs_ts_used_pct(&usage->zsu_system->zss_cpu_total_time,
1286 &idle, B_TRUE));
1287 }
1288
1289 static void
zs_cpu_usage_kernel(zs_usage_t * usage,timestruc_t * ts)1290 zs_cpu_usage_kernel(zs_usage_t *usage, timestruc_t *ts)
1291 {
1292 *ts = usage->zsu_system->zss_cpu_usage_kern;
1293 }
1294
1295 static uint_t
zs_cpu_usage_kernel_pct(zs_usage_t * usage)1296 zs_cpu_usage_kernel_pct(zs_usage_t *usage)
1297 {
1298 return (zs_ts_used_pct(&usage->zsu_system->zss_cpu_total_time,
1299 &usage->zsu_system->zss_cpu_usage_kern, B_TRUE));
1300 }
1301
1302 static void
zs_cpu_usage_zones(zs_usage_t * usage,timestruc_t * ts)1303 zs_cpu_usage_zones(zs_usage_t *usage, timestruc_t *ts)
1304 {
1305 *ts = usage->zsu_system->zss_cpu_usage_zones;
1306 }
1307
1308
1309 static uint_t
zs_cpu_usage_zones_pct(zs_usage_t * usage)1310 zs_cpu_usage_zones_pct(zs_usage_t *usage)
1311 {
1312 return (zs_ts_used_pct(&usage->zsu_system->zss_cpu_total_time,
1313 &usage->zsu_system->zss_cpu_usage_zones, B_TRUE));
1314 }
1315
1316
1317 static void
zs_cpu_usage_zone(zs_zone_t * zone,timestruc_t * ts)1318 zs_cpu_usage_zone(zs_zone_t *zone, timestruc_t *ts)
1319 {
1320 *ts = zone->zsz_cpu_usage;
1321 }
1322
1323 static uint64_t
zs_cpu_total_cpu(zs_usage_t * usage)1324 zs_cpu_total_cpu(zs_usage_t *usage)
1325 {
1326 return (usage->zsu_system->zss_ncpus_online * ZSD_ONE_CPU);
1327 }
1328
1329 static uint64_t
zs_cpu_usage_all_cpu(zs_usage_t * usage)1330 zs_cpu_usage_all_cpu(zs_usage_t *usage)
1331 {
1332 timestruc_t tot;
1333
1334 tot = usage->zsu_system->zss_cpu_usage_kern;
1335 TIMESTRUC_ADD_TIMESTRUC(tot, usage->zsu_system->zss_cpu_usage_zones);
1336
1337 return (zs_ts_used_cpus(&usage->zsu_system->zss_cpu_total_time,
1338 &tot, usage->zsu_system->zss_ncpus_online, B_TRUE));
1339 }
1340
1341 static uint64_t
zs_cpu_usage_idle_cpu(zs_usage_t * usage)1342 zs_cpu_usage_idle_cpu(zs_usage_t *usage)
1343 {
1344 timestruc_t tot, idle;
1345
1346 tot = usage->zsu_system->zss_cpu_usage_kern;
1347 TIMESTRUC_ADD_TIMESTRUC(tot, usage->zsu_system->zss_cpu_usage_zones);
1348 TIMESTRUC_DELTA(idle, usage->zsu_system->zss_cpu_total_time, tot);
1349
1350 return (zs_ts_used_cpus(&usage->zsu_system->zss_cpu_total_time,
1351 &idle, usage->zsu_system->zss_ncpus_online, B_TRUE));
1352 }
1353
1354 static uint64_t
zs_cpu_usage_kernel_cpu(zs_usage_t * usage)1355 zs_cpu_usage_kernel_cpu(zs_usage_t *usage)
1356 {
1357 return (zs_ts_used_cpus(&usage->zsu_system->zss_cpu_total_time,
1358 &usage->zsu_system->zss_cpu_usage_kern,
1359 usage->zsu_system->zss_ncpus_online, B_TRUE));
1360 }
1361
1362 static uint64_t
zs_cpu_usage_zones_cpu(zs_usage_t * usage)1363 zs_cpu_usage_zones_cpu(zs_usage_t *usage)
1364 {
1365 return (zs_ts_used_cpus(&usage->zsu_system->zss_cpu_total_time,
1366 &usage->zsu_system->zss_cpu_usage_kern,
1367 usage->zsu_system->zss_ncpus_online, B_TRUE));
1368 }
1369
1370 static uint64_t
zs_cpu_usage_zone_cpu(zs_zone_t * zone)1371 zs_cpu_usage_zone_cpu(zs_zone_t *zone)
1372 {
1373 return (zs_ts_used_cpus(&zone->zsz_pset_time, &zone->zsz_cpu_usage,
1374 zone->zsz_cpus_online, B_TRUE));
1375 }
1376
1377 static uint_t
zs_cpu_usage_zone_pct(zs_zone_t * zone)1378 zs_cpu_usage_zone_pct(zs_zone_t *zone)
1379 {
1380 return (zs_ts_used_pct(&zone->zsz_pset_time, &zone->zsz_cpu_usage,
1381 B_TRUE));
1382 }
1383
1384 static uint64_t
zs_physical_memory_total(zs_usage_t * usage)1385 zs_physical_memory_total(zs_usage_t *usage)
1386 {
1387 return (usage->zsu_system->zss_ram_total);
1388 }
1389
1390
1391 static uint64_t
zs_physical_memory_usage_all(zs_usage_t * usage)1392 zs_physical_memory_usage_all(zs_usage_t *usage)
1393 {
1394 return (usage->zsu_system->zss_ram_kern +
1395 usage->zsu_system->zss_ram_zones);
1396 }
1397
1398 static uint_t
zs_physical_memory_usage_all_pct(zs_usage_t * usage)1399 zs_physical_memory_usage_all_pct(zs_usage_t *usage)
1400 {
1401 zs_system_t *system = usage->zsu_system;
1402
1403 return (zs_uint64_used_pct(system->zss_ram_total,
1404 (system->zss_ram_kern + system->zss_ram_zones), B_TRUE));
1405 }
1406
1407 static uint64_t
zs_physical_memory_usage_free(zs_usage_t * usage)1408 zs_physical_memory_usage_free(zs_usage_t *usage)
1409 {
1410 return (usage->zsu_system->zss_ram_total -
1411 (usage->zsu_system->zss_ram_kern +
1412 usage->zsu_system->zss_ram_zones));
1413 }
1414
1415 static uint_t
zs_physical_memory_usage_free_pct(zs_usage_t * usage)1416 zs_physical_memory_usage_free_pct(zs_usage_t *usage)
1417 {
1418 return (ZSD_PCT_INT - zs_physical_memory_usage_all_pct(usage));
1419 }
1420
1421 static uint64_t
zs_physical_memory_usage_kernel(zs_usage_t * usage)1422 zs_physical_memory_usage_kernel(zs_usage_t *usage)
1423 {
1424 return (usage->zsu_system->zss_ram_kern);
1425 }
1426
1427 static uint_t
zs_physical_memory_usage_kernel_pct(zs_usage_t * usage)1428 zs_physical_memory_usage_kernel_pct(zs_usage_t *usage)
1429 {
1430 zs_system_t *system = usage->zsu_system;
1431
1432 return (zs_uint64_used_pct(system->zss_ram_total,
1433 system->zss_ram_kern, B_TRUE));
1434 }
1435
1436 static uint64_t
zs_physical_memory_usage_zones(zs_usage_t * usage)1437 zs_physical_memory_usage_zones(zs_usage_t *usage)
1438 {
1439 return (usage->zsu_system->zss_ram_zones);
1440 }
1441
1442 static uint_t
zs_physical_memory_usage_zones_pct(zs_usage_t * usage)1443 zs_physical_memory_usage_zones_pct(zs_usage_t *usage)
1444 {
1445 zs_system_t *system = usage->zsu_system;
1446
1447 return (zs_uint64_used_pct(system->zss_ram_total,
1448 system->zss_ram_zones, B_TRUE));
1449 }
1450
1451 static uint64_t
zs_physical_memory_usage_zone(zs_zone_t * zone)1452 zs_physical_memory_usage_zone(zs_zone_t *zone)
1453 {
1454 return (zone->zsz_usage_ram);
1455 }
1456
1457 static uint_t
zs_physical_memory_usage_zone_pct(zs_zone_t * zone)1458 zs_physical_memory_usage_zone_pct(zs_zone_t *zone)
1459 {
1460 zs_system_t *system = zone->zsz_system;
1461
1462 return (zs_uint64_used_pct(system->zss_ram_total,
1463 zone->zsz_usage_ram, B_TRUE));
1464 }
1465
1466 static uint_t
zs_zone_physical_memory_cap_pct(zs_zone_t * zone)1467 zs_zone_physical_memory_cap_pct(zs_zone_t *zone)
1468 {
1469 if (zone->zsz_ram_cap == ZS_LIMIT_NONE)
1470 return (ZS_PCT_NONE);
1471
1472 if (zone->zsz_ram_cap == 0) {
1473 return (0);
1474 }
1475
1476 /* Allow ram cap to exeed 100% */
1477 return (zs_uint64_used_pct(zone->zsz_ram_cap,
1478 zone->zsz_usage_ram, B_FALSE));
1479 }
1480 static uint64_t
zs_virtual_memory_total(zs_usage_t * usage)1481 zs_virtual_memory_total(zs_usage_t *usage)
1482 {
1483 return (usage->zsu_system->zss_vm_total);
1484 }
1485
1486 static uint64_t
zs_virtual_memory_usage_all(zs_usage_t * usage)1487 zs_virtual_memory_usage_all(zs_usage_t *usage)
1488 {
1489 return (usage->zsu_system->zss_vm_kern +
1490 usage->zsu_system->zss_vm_zones);
1491 }
1492 static uint64_t
zs_virtual_memory_usage_free(zs_usage_t * usage)1493 zs_virtual_memory_usage_free(zs_usage_t *usage)
1494 {
1495 return (usage->zsu_system->zss_vm_total -
1496 (usage->zsu_system->zss_vm_kern +
1497 usage->zsu_system->zss_vm_zones));
1498 }
1499 static uint_t
zs_virtual_memory_usage_all_pct(zs_usage_t * usage)1500 zs_virtual_memory_usage_all_pct(zs_usage_t *usage)
1501 {
1502 zs_system_t *system = usage->zsu_system;
1503
1504 return (zs_uint64_used_pct(system->zss_vm_total,
1505 (system->zss_vm_kern + system->zss_vm_zones), B_TRUE));
1506
1507 }
1508
1509 static uint_t
zs_virtual_memory_usage_free_pct(zs_usage_t * usage)1510 zs_virtual_memory_usage_free_pct(zs_usage_t *usage)
1511 {
1512 return (ZSD_PCT_INT - zs_virtual_memory_usage_all_pct(usage));
1513
1514 }
1515 static uint64_t
zs_virtual_memory_usage_kernel(zs_usage_t * usage)1516 zs_virtual_memory_usage_kernel(zs_usage_t *usage)
1517 {
1518 return (usage->zsu_system->zss_vm_kern);
1519 }
1520
1521 static uint_t
zs_virtual_memory_usage_kernel_pct(zs_usage_t * usage)1522 zs_virtual_memory_usage_kernel_pct(zs_usage_t *usage)
1523 {
1524 zs_system_t *system = usage->zsu_system;
1525
1526 return (zs_uint64_used_pct(system->zss_vm_total,
1527 system->zss_vm_kern, B_TRUE));
1528 }
1529
1530 static uint64_t
zs_virtual_memory_usage_zones(zs_usage_t * usage)1531 zs_virtual_memory_usage_zones(zs_usage_t *usage)
1532 {
1533 return (usage->zsu_system->zss_vm_zones);
1534 }
1535
1536 static uint_t
zs_virtual_memory_usage_zones_pct(zs_usage_t * usage)1537 zs_virtual_memory_usage_zones_pct(zs_usage_t *usage)
1538 {
1539 zs_system_t *system = usage->zsu_system;
1540
1541 return (zs_uint64_used_pct(system->zss_vm_total,
1542 system->zss_vm_zones, B_TRUE));
1543 }
1544
1545 static uint64_t
zs_virtual_memory_usage_zone(zs_zone_t * zone)1546 zs_virtual_memory_usage_zone(zs_zone_t *zone)
1547 {
1548 return (zone->zsz_usage_vm);
1549 }
1550
1551 static uint_t
zs_virtual_memory_usage_zone_pct(zs_zone_t * zone)1552 zs_virtual_memory_usage_zone_pct(zs_zone_t *zone)
1553 {
1554 zs_system_t *system = zone->zsz_system;
1555
1556 return (zs_uint64_used_pct(system->zss_vm_total,
1557 zone->zsz_usage_vm, B_TRUE));
1558
1559 }
1560
1561 static uint_t
zs_zone_virtual_memory_cap_pct(zs_zone_t * zone)1562 zs_zone_virtual_memory_cap_pct(zs_zone_t *zone)
1563 {
1564 if (zone->zsz_vm_cap == ZS_LIMIT_NONE)
1565 return (ZS_PCT_NONE);
1566
1567 if (zone->zsz_vm_cap == 0)
1568 return (0);
1569
1570 return (zs_uint64_used_pct(zone->zsz_vm_cap,
1571 zone->zsz_usage_vm, B_TRUE));
1572 }
1573
1574 static uint64_t
zs_locked_memory_total(zs_usage_t * usage)1575 zs_locked_memory_total(zs_usage_t *usage)
1576 {
1577 return (usage->zsu_system->zss_ram_total);
1578 }
1579
1580 static uint64_t
zs_locked_memory_usage_all(zs_usage_t * usage)1581 zs_locked_memory_usage_all(zs_usage_t *usage)
1582 {
1583 return (usage->zsu_system->zss_locked_kern +
1584 usage->zsu_system->zss_locked_zones);
1585 }
1586 static uint64_t
zs_locked_memory_usage_free(zs_usage_t * usage)1587 zs_locked_memory_usage_free(zs_usage_t *usage)
1588 {
1589 return (usage->zsu_system->zss_ram_total -
1590 (usage->zsu_system->zss_locked_kern +
1591 usage->zsu_system->zss_locked_zones));
1592 }
1593
1594 static uint_t
zs_locked_memory_usage_all_pct(zs_usage_t * usage)1595 zs_locked_memory_usage_all_pct(zs_usage_t *usage)
1596 {
1597 zs_system_t *system = usage->zsu_system;
1598
1599 return (zs_uint64_used_pct(system->zss_ram_total,
1600 (system->zss_locked_kern + system->zss_locked_zones), B_TRUE));
1601 }
1602
1603 static uint_t
zs_locked_memory_usage_free_pct(zs_usage_t * usage)1604 zs_locked_memory_usage_free_pct(zs_usage_t *usage)
1605 {
1606 return (ZSD_PCT_INT - zs_locked_memory_usage_all_pct(usage));
1607
1608 }
1609
1610 static uint64_t
zs_locked_memory_usage_kernel(zs_usage_t * usage)1611 zs_locked_memory_usage_kernel(zs_usage_t *usage)
1612 {
1613 return (usage->zsu_system->zss_locked_kern);
1614 }
1615
1616 static uint_t
zs_locked_memory_usage_kernel_pct(zs_usage_t * usage)1617 zs_locked_memory_usage_kernel_pct(zs_usage_t *usage)
1618 {
1619 zs_system_t *system = usage->zsu_system;
1620
1621 return (zs_uint64_used_pct(system->zss_ram_total,
1622 system->zss_locked_kern, B_TRUE));
1623 }
1624
1625 static uint64_t
zs_locked_memory_usage_zones(zs_usage_t * usage)1626 zs_locked_memory_usage_zones(zs_usage_t *usage)
1627 {
1628 return (usage->zsu_system->zss_locked_zones);
1629 }
1630
1631 static uint_t
zs_locked_memory_usage_zones_pct(zs_usage_t * usage)1632 zs_locked_memory_usage_zones_pct(zs_usage_t *usage)
1633 {
1634 zs_system_t *system = usage->zsu_system;
1635
1636 return (zs_uint64_used_pct(system->zss_ram_total,
1637 system->zss_locked_zones, B_TRUE));
1638 }
1639
1640 static uint64_t
zs_locked_memory_usage_zone(zs_zone_t * zone)1641 zs_locked_memory_usage_zone(zs_zone_t *zone)
1642 {
1643 return (zone->zsz_usage_locked);
1644 }
1645
1646 static uint_t
zs_locked_memory_usage_zone_pct(zs_zone_t * zone)1647 zs_locked_memory_usage_zone_pct(zs_zone_t *zone)
1648 {
1649 zs_system_t *system = zone->zsz_system;
1650
1651 return (zs_uint64_used_pct(system->zss_ram_total,
1652 zone->zsz_usage_locked, B_TRUE));
1653 }
1654
1655 static uint_t
zs_zone_locked_memory_cap_pct(zs_zone_t * zone)1656 zs_zone_locked_memory_cap_pct(zs_zone_t *zone)
1657 {
1658 if (zone->zsz_locked_cap == ZS_LIMIT_NONE)
1659 return (ZS_PCT_NONE);
1660
1661 if (zone->zsz_locked_cap == 0)
1662 return (0);
1663
1664 return (zs_uint64_used_pct(zone->zsz_locked_cap,
1665 zone->zsz_usage_locked, B_TRUE));
1666
1667 }
1668 static uint64_t
zs_disk_swap_total(zs_usage_t * usage)1669 zs_disk_swap_total(zs_usage_t *usage)
1670 {
1671 return (usage->zsu_system->zss_swap_total);
1672 }
1673
1674 static uint64_t
zs_disk_swap_usage_all(zs_usage_t * usage)1675 zs_disk_swap_usage_all(zs_usage_t *usage)
1676 {
1677 return (usage->zsu_system->zss_swap_used);
1678 }
1679
1680 static uint_t
zs_disk_swap_usage_all_pct(zs_usage_t * usage)1681 zs_disk_swap_usage_all_pct(zs_usage_t *usage)
1682 {
1683 return (zs_uint64_used_pct(usage->zsu_system->zss_swap_total,
1684 usage->zsu_system->zss_swap_used, B_TRUE));
1685 }
1686
1687 static uint64_t
zs_disk_swap_usage_free(zs_usage_t * usage)1688 zs_disk_swap_usage_free(zs_usage_t *usage)
1689 {
1690 return (usage->zsu_system->zss_swap_total -
1691 usage->zsu_system->zss_swap_used);
1692 }
1693
1694 static uint_t
zs_disk_swap_usage_free_pct(zs_usage_t * usage)1695 zs_disk_swap_usage_free_pct(zs_usage_t *usage)
1696 {
1697 return (ZSD_PCT_INT - zs_disk_swap_usage_all_pct(usage));
1698 }
1699
1700 static uint64_t
zs_processes_total(zs_usage_t * usage)1701 zs_processes_total(zs_usage_t *usage)
1702 {
1703 return (usage->zsu_system->zss_processes_max);
1704 }
1705
1706 static uint64_t
zs_lwps_total(zs_usage_t * usage)1707 zs_lwps_total(zs_usage_t *usage)
1708 {
1709 return (usage->zsu_system->zss_lwps_max);
1710 }
1711
1712 static uint64_t
zs_shm_total(zs_usage_t * usage)1713 zs_shm_total(zs_usage_t *usage)
1714 {
1715 return (usage->zsu_system->zss_shm_max);
1716 }
1717
1718 static uint64_t
zs_shmids_total(zs_usage_t * usage)1719 zs_shmids_total(zs_usage_t *usage)
1720 {
1721 return (usage->zsu_system->zss_shmids_max);
1722 }
1723
1724 static uint64_t
zs_semids_total(zs_usage_t * usage)1725 zs_semids_total(zs_usage_t *usage)
1726 {
1727 return (usage->zsu_system->zss_semids_max);
1728 }
1729
1730 static uint64_t
zs_msgids_total(zs_usage_t * usage)1731 zs_msgids_total(zs_usage_t *usage)
1732 {
1733 return (usage->zsu_system->zss_msgids_max);
1734 }
1735
1736 static uint64_t
zs_lofi_total(zs_usage_t * usage)1737 zs_lofi_total(zs_usage_t *usage)
1738 {
1739 return (usage->zsu_system->zss_lofi_max);
1740 }
1741
1742 static uint64_t
zs_processes_usage_all(zs_usage_t * usage)1743 zs_processes_usage_all(zs_usage_t *usage)
1744 {
1745 return (usage->zsu_system->zss_processes);
1746 }
1747
1748 static uint64_t
zs_lwps_usage_all(zs_usage_t * usage)1749 zs_lwps_usage_all(zs_usage_t *usage)
1750 {
1751 return (usage->zsu_system->zss_lwps);
1752 }
1753
1754 static uint64_t
zs_shm_usage_all(zs_usage_t * usage)1755 zs_shm_usage_all(zs_usage_t *usage)
1756 {
1757 return (usage->zsu_system->zss_shm);
1758 }
1759
1760 static uint64_t
zs_shmids_usage_all(zs_usage_t * usage)1761 zs_shmids_usage_all(zs_usage_t *usage)
1762 {
1763 return (usage->zsu_system->zss_shmids);
1764 }
1765
1766 static uint64_t
zs_semids_usage_all(zs_usage_t * usage)1767 zs_semids_usage_all(zs_usage_t *usage)
1768 {
1769 return (usage->zsu_system->zss_semids);
1770 }
1771
1772 static uint64_t
zs_msgids_usage_all(zs_usage_t * usage)1773 zs_msgids_usage_all(zs_usage_t *usage)
1774 {
1775 return (usage->zsu_system->zss_msgids);
1776 }
1777
1778 static uint64_t
zs_lofi_usage_all(zs_usage_t * usage)1779 zs_lofi_usage_all(zs_usage_t *usage)
1780 {
1781 return (usage->zsu_system->zss_lofi);
1782 }
1783 static uint64_t
zs_processes_usage_all_pct(zs_usage_t * usage)1784 zs_processes_usage_all_pct(zs_usage_t *usage)
1785 {
1786 zs_system_t *system = usage->zsu_system;
1787
1788 return (zs_uint64_used_pct(system->zss_processes_max,
1789 system->zss_processes, B_TRUE));
1790 }
1791
1792 static uint_t
zs_lwps_usage_all_pct(zs_usage_t * usage)1793 zs_lwps_usage_all_pct(zs_usage_t *usage)
1794 {
1795 zs_system_t *system = usage->zsu_system;
1796
1797 return (zs_uint64_used_pct(system->zss_lwps_max,
1798 system->zss_lwps, B_TRUE));
1799 }
1800
1801 static uint_t
zs_shm_usage_all_pct(zs_usage_t * usage)1802 zs_shm_usage_all_pct(zs_usage_t *usage)
1803 {
1804 zs_system_t *system = usage->zsu_system;
1805
1806 return (zs_uint64_used_pct(system->zss_shm_max,
1807 system->zss_shm, B_TRUE));
1808 }
1809
1810 static uint_t
zs_shmids_usage_all_pct(zs_usage_t * usage)1811 zs_shmids_usage_all_pct(zs_usage_t *usage)
1812 {
1813 zs_system_t *system = usage->zsu_system;
1814
1815 return (zs_uint64_used_pct(system->zss_shmids_max,
1816 system->zss_shmids, B_TRUE));
1817 }
1818
1819 static uint64_t
zs_semids_usage_all_pct(zs_usage_t * usage)1820 zs_semids_usage_all_pct(zs_usage_t *usage)
1821 {
1822 zs_system_t *system = usage->zsu_system;
1823
1824 return (zs_uint64_used_pct(system->zss_semids_max,
1825 system->zss_semids, B_TRUE));
1826 }
1827
1828 static uint64_t
zs_msgids_usage_all_pct(zs_usage_t * usage)1829 zs_msgids_usage_all_pct(zs_usage_t *usage)
1830 {
1831 zs_system_t *system = usage->zsu_system;
1832
1833 return (zs_uint64_used_pct(system->zss_msgids_max,
1834 system->zss_msgids, B_TRUE));
1835 }
1836
1837 static uint64_t
zs_lofi_usage_all_pct(zs_usage_t * usage)1838 zs_lofi_usage_all_pct(zs_usage_t *usage)
1839 {
1840 zs_system_t *system = usage->zsu_system;
1841
1842 return (zs_uint64_used_pct(system->zss_lofi_max,
1843 system->zss_lofi, B_TRUE));
1844 }
1845
1846 static uint64_t
zs_processes_usage_zone(zs_zone_t * zone)1847 zs_processes_usage_zone(zs_zone_t *zone)
1848 {
1849 return (zone->zsz_processes);
1850 }
1851
1852 static uint64_t
zs_lwps_usage_zone(zs_zone_t * zone)1853 zs_lwps_usage_zone(zs_zone_t *zone)
1854 {
1855 return (zone->zsz_lwps);
1856 }
1857
1858 static uint64_t
zs_shm_usage_zone(zs_zone_t * zone)1859 zs_shm_usage_zone(zs_zone_t *zone)
1860 {
1861 return (zone->zsz_shm);
1862 }
1863
1864 static uint64_t
zs_shmids_usage_zone(zs_zone_t * zone)1865 zs_shmids_usage_zone(zs_zone_t *zone)
1866 {
1867 return (zone->zsz_shmids);
1868 }
1869
1870 static uint64_t
zs_semids_usage_zone(zs_zone_t * zone)1871 zs_semids_usage_zone(zs_zone_t *zone)
1872 {
1873 return (zone->zsz_semids);
1874 }
1875
1876 static uint64_t
zs_msgids_usage_zone(zs_zone_t * zone)1877 zs_msgids_usage_zone(zs_zone_t *zone)
1878 {
1879 return (zone->zsz_msgids);
1880 }
1881
1882 static uint64_t
zs_lofi_usage_zone(zs_zone_t * zone)1883 zs_lofi_usage_zone(zs_zone_t *zone)
1884 {
1885 return (zone->zsz_lofi);
1886 }
1887
1888 static uint_t
zs_processes_usage_zone_pct(zs_zone_t * zone)1889 zs_processes_usage_zone_pct(zs_zone_t *zone)
1890 {
1891 zs_system_t *system = zone->zsz_system;
1892
1893 return (zs_uint64_used_pct(system->zss_processes_max,
1894 zone->zsz_processes, B_TRUE));
1895 }
1896
1897 static uint_t
zs_lwps_usage_zone_pct(zs_zone_t * zone)1898 zs_lwps_usage_zone_pct(zs_zone_t *zone)
1899 {
1900 zs_system_t *system = zone->zsz_system;
1901
1902 return (zs_uint64_used_pct(system->zss_lwps_max,
1903 zone->zsz_lwps, B_TRUE));
1904 }
1905
1906 static uint_t
zs_shm_usage_zone_pct(zs_zone_t * zone)1907 zs_shm_usage_zone_pct(zs_zone_t *zone)
1908 {
1909 zs_system_t *system = zone->zsz_system;
1910
1911 return (zs_uint64_used_pct(system->zss_shm_max,
1912 zone->zsz_shm, B_TRUE));
1913 }
1914
1915 static uint_t
zs_shmids_usage_zone_pct(zs_zone_t * zone)1916 zs_shmids_usage_zone_pct(zs_zone_t *zone)
1917 {
1918 zs_system_t *system = zone->zsz_system;
1919
1920 return (zs_uint64_used_pct(system->zss_shmids_max,
1921 zone->zsz_shmids, B_TRUE));
1922 }
1923
1924 static uint_t
zs_semids_usage_zone_pct(zs_zone_t * zone)1925 zs_semids_usage_zone_pct(zs_zone_t *zone)
1926 {
1927 zs_system_t *system = zone->zsz_system;
1928
1929 return (zs_uint64_used_pct(system->zss_semids_max,
1930 zone->zsz_semids, B_TRUE));
1931 }
1932
1933 static uint_t
zs_msgids_usage_zone_pct(zs_zone_t * zone)1934 zs_msgids_usage_zone_pct(zs_zone_t *zone)
1935 {
1936 zs_system_t *system = zone->zsz_system;
1937
1938 return (zs_uint64_used_pct(system->zss_msgids_max,
1939 zone->zsz_msgids, B_TRUE));
1940 }
1941
1942 static uint_t
zs_lofi_usage_zone_pct(zs_zone_t * zone)1943 zs_lofi_usage_zone_pct(zs_zone_t *zone)
1944 {
1945 zs_system_t *system = zone->zsz_system;
1946
1947 return (zs_uint64_used_pct(system->zss_lofi_max,
1948 zone->zsz_lofi, B_TRUE));
1949 }
1950
1951 static uint_t
zs_processes_zone_cap_pct(zs_zone_t * zone)1952 zs_processes_zone_cap_pct(zs_zone_t *zone)
1953 {
1954 if (zone->zsz_processes_cap == ZS_LIMIT_NONE)
1955 return (ZS_PCT_NONE);
1956
1957 if (zone->zsz_processes_cap == 0)
1958 return (0);
1959
1960 return (zs_uint64_used_pct(zone->zsz_processes_cap,
1961 zone->zsz_processes, B_TRUE));
1962 }
1963
1964 static uint_t
zs_lwps_zone_cap_pct(zs_zone_t * zone)1965 zs_lwps_zone_cap_pct(zs_zone_t *zone)
1966 {
1967 if (zone->zsz_lwps_cap == ZS_LIMIT_NONE)
1968 return (ZS_PCT_NONE);
1969
1970 if (zone->zsz_lwps_cap == 0)
1971 return (0);
1972
1973 return (zs_uint64_used_pct(zone->zsz_lwps_cap, zone->zsz_lwps, B_TRUE));
1974 }
1975
1976 static uint_t
zs_shm_zone_cap_pct(zs_zone_t * zone)1977 zs_shm_zone_cap_pct(zs_zone_t *zone)
1978 {
1979 if (zone->zsz_shm_cap == ZS_LIMIT_NONE)
1980 return (ZS_PCT_NONE);
1981
1982 if (zone->zsz_shm_cap == 0)
1983 return (0);
1984
1985 return (zs_uint64_used_pct(zone->zsz_shm_cap, zone->zsz_shm, B_TRUE));
1986 }
1987
1988 static uint_t
zs_shmids_zone_cap_pct(zs_zone_t * zone)1989 zs_shmids_zone_cap_pct(zs_zone_t *zone)
1990 {
1991 if (zone->zsz_shmids_cap == ZS_LIMIT_NONE)
1992 return (ZS_PCT_NONE);
1993
1994 if (zone->zsz_shmids_cap == 0)
1995 return (0);
1996
1997 return (zs_uint64_used_pct(zone->zsz_shmids_cap, zone->zsz_shmids,
1998 B_TRUE));
1999 }
2000
2001 static uint_t
zs_semids_zone_cap_pct(zs_zone_t * zone)2002 zs_semids_zone_cap_pct(zs_zone_t *zone)
2003 {
2004 if (zone->zsz_semids_cap == ZS_LIMIT_NONE)
2005 return (ZS_PCT_NONE);
2006
2007 if (zone->zsz_semids_cap == 0)
2008 return (0);
2009
2010 return (zs_uint64_used_pct(zone->zsz_semids_cap, zone->zsz_semids,
2011 B_TRUE));
2012 }
2013
2014 static uint_t
zs_msgids_zone_cap_pct(zs_zone_t * zone)2015 zs_msgids_zone_cap_pct(zs_zone_t *zone)
2016 {
2017 if (zone->zsz_msgids_cap == ZS_LIMIT_NONE)
2018 return (ZS_PCT_NONE);
2019
2020 if (zone->zsz_msgids_cap == 0)
2021 return (0);
2022
2023 return (zs_uint64_used_pct(zone->zsz_msgids_cap, zone->zsz_msgids,
2024 B_TRUE));
2025 }
2026
2027 static uint_t
zs_lofi_zone_cap_pct(zs_zone_t * zone)2028 zs_lofi_zone_cap_pct(zs_zone_t *zone)
2029 {
2030 if (zone->zsz_lofi_cap == ZS_LIMIT_NONE)
2031 return (ZS_PCT_NONE);
2032
2033 if (zone->zsz_lofi_cap == 0)
2034 return (0);
2035
2036 return (zs_uint64_used_pct(zone->zsz_lofi_cap, zone->zsz_lofi,
2037 B_TRUE));
2038 }
2039
2040 /* All funcs this line should be static */
2041
2042 void
zs_close(zs_ctl_t * ctl)2043 zs_close(zs_ctl_t *ctl)
2044 {
2045 (void) close(ctl->zsctl_door);
2046 zs_usage_free(ctl->zsctl_start);
2047 free(ctl);
2048 }
2049
2050 /*
2051 * ERRORS
2052 *
2053 * EINTR signal received, process forked, or zonestatd exited
2054 * ESRCH zonestatd not responding
2055 */
2056 static zs_usage_t *
zs_usage_read_internal(zs_ctl_t * ctl,int init)2057 zs_usage_read_internal(zs_ctl_t *ctl, int init)
2058 {
2059 int fd = -1;
2060 uint_t i, j;
2061 zs_usage_t *usage;
2062 zs_zone_t *zone = NULL;
2063 zs_pset_t *pset = NULL;
2064 zs_pset_zone_t *pz;
2065 char *next;
2066 uint64_t cmd[2];
2067 door_arg_t params;
2068
2069 fd = ctl->zsctl_door;
2070 cmd[0] = ZSD_CMD_READ;
2071 cmd[1] = ctl->zsctl_gen;
2072 params.data_ptr = (char *)cmd;
2073 params.data_size = sizeof (cmd);
2074 params.desc_ptr = NULL;
2075 params.desc_num = 0;
2076 params.rbuf = NULL;
2077 params.rsize = 0;
2078
2079 if (door_call(fd, ¶ms) != 0) {
2080 if (errno != EINTR)
2081 errno = ESRCH;
2082 return (NULL);
2083 }
2084
2085 if (params.rbuf == NULL) {
2086 errno = ESRCH;
2087 return (NULL);
2088 }
2089 /* LINTED */
2090 usage = (zs_usage_t *)params.data_ptr;
2091 ctl->zsctl_gen = usage->zsu_gen;
2092 usage->zsu_mmap = B_TRUE;
2093 usage->zsu_intervals = 0;
2094
2095 list_create(&usage->zsu_zone_list, sizeof (zs_zone_t),
2096 offsetof(zs_zone_t, zsz_next));
2097 list_create(&usage->zsu_pset_list, sizeof (zs_pset_t),
2098 offsetof(zs_pset_t, zsp_next));
2099
2100 /* Fix up next pointers inside usage_t */
2101 next = (char *)usage;
2102 next += sizeof (zs_usage_t);
2103
2104 /* LINTED */
2105 usage->zsu_system = (zs_system_t *)next;
2106 next += sizeof (zs_system_t);
2107
2108 for (i = 0; i < usage->zsu_nzones; i++) {
2109 /* LINTED */
2110 zone = (zs_zone_t *)next;
2111 list_insert_tail(&usage->zsu_zone_list, zone);
2112 next += sizeof (zs_zone_t);
2113 zone->zsz_system = usage->zsu_system;
2114 zone->zsz_intervals = 0;
2115 }
2116
2117 for (i = 0; i < usage->zsu_npsets; i++) {
2118 /* LINTED */
2119 pset = (zs_pset_t *)next;
2120 list_insert_tail(&usage->zsu_pset_list, pset);
2121 next += sizeof (zs_pset_t);
2122 list_create(&pset->zsp_usage_list, sizeof (zs_pset_zone_t),
2123 offsetof(zs_pset_zone_t, zspz_next));
2124 for (j = 0; j < pset->zsp_nusage; j++) {
2125 /* LINTED */
2126 pz = (zs_pset_zone_t *)next;
2127 list_insert_tail(&pset->zsp_usage_list, pz);
2128 next += sizeof (zs_pset_zone_t);
2129 pz->zspz_pset = pset;
2130 pz->zspz_zone =
2131 zs_lookup_zone_byid(usage, pz->zspz_zoneid);
2132 assert(pz->zspz_zone != NULL);
2133 pz->zspz_intervals = 0;
2134 }
2135 pset->zsp_intervals = 0;
2136 }
2137 if (init)
2138 return (usage);
2139
2140 /*
2141 * If current usage tracking started after start usage, then
2142 * no need to subtract start usage. This really can't happen,
2143 * as zonestatd should never start over while this client is
2144 * connected.
2145 */
2146 if (usage->zsu_hrstart > ctl->zsctl_start->zsu_hrtime) {
2147 return (usage);
2148 }
2149
2150 /*
2151 * Compute usage relative to first open. Usage returned by
2152 * zonestatd starts at an arbitrary point in the past.
2153 *
2154 */
2155
2156 (void) zs_usage_compute(usage, ctl->zsctl_start, usage,
2157 ZS_COMPUTE_USAGE_INTERVAL);
2158
2159 return (usage);
2160 }
2161
2162 zs_usage_t *
zs_usage_read(zs_ctl_t * ctl)2163 zs_usage_read(zs_ctl_t *ctl)
2164 {
2165 return (zs_usage_read_internal(ctl, B_FALSE));
2166 }
2167
2168 /*
2169 * Open connection to zonestatd. NULL of failure, with errno set:
2170 *
2171 * EPERM: Insufficent privilege (no PRIV_PROC_INFO)
2172 * ESRCH: Zones monitoring service not available or responding
2173 * ENOTSUP: Incompatiable zones monitoring service version.
2174 * EINTR: Server exited or client forked.
2175 * ENOMEM: as malloc(3c)
2176 * EAGAIN: asl malloc(3c)
2177 *
2178 */
2179 zs_ctl_t *
zs_open()2180 zs_open()
2181 {
2182 zs_ctl_t *ctl;
2183 int cmd[2];
2184 int *res;
2185 int fd;
2186 door_arg_t params;
2187 door_desc_t *door;
2188 int errno_save;
2189
2190 ctl = calloc(sizeof (zs_ctl_t), 1);
2191 if (ctl == NULL)
2192 return (NULL);
2193
2194 fd = zs_connect_zonestatd();
2195 if (fd < 0) {
2196 free(ctl);
2197 errno = ESRCH;
2198 return (NULL);
2199 }
2200
2201 cmd[0] = ZSD_CMD_CONNECT;
2202 cmd[1] = ZS_VERSION;
2203 params.data_ptr = (char *)cmd;
2204 params.data_size = sizeof (cmd);
2205 params.desc_ptr = NULL;
2206 params.desc_num = 0;
2207 params.rbuf = NULL;
2208 params.rsize = 0;
2209 if (door_call(fd, ¶ms) != 0) {
2210 errno_save = errno;
2211 free(ctl);
2212 (void) close(fd);
2213 if (errno_save == EINTR)
2214 errno = EINTR;
2215 else
2216 errno = ESRCH;
2217 return (NULL);
2218 }
2219 (void) close(fd);
2220 /* LINTED */
2221 res = (int *)params.data_ptr;
2222 if (res[1] == ZSD_STATUS_VERSION_MISMATCH) {
2223 free(ctl);
2224 errno = ENOTSUP;
2225 return (NULL);
2226 }
2227 if (res[1] == ZSD_STATUS_PERMISSION) {
2228 free(ctl);
2229 errno = EPERM;
2230 return (NULL);
2231 }
2232 if (res[1] != ZSD_STATUS_OK) {
2233 free(ctl);
2234 errno = ESRCH;
2235 return (NULL);
2236 }
2237
2238 door = params.desc_ptr;
2239 if (door == NULL) {
2240 free(ctl);
2241 return (NULL);
2242 }
2243 ctl->zsctl_door = door->d_data.d_desc.d_descriptor;
2244
2245 if (params.data_ptr != (char *)cmd)
2246 (void) munmap(params.data_ptr, params.data_size);
2247
2248
2249 /*
2250 * Get the initial usage from zonestatd. This creates a
2251 * zero-point on which to base future usages returned by
2252 * zs_read().
2253 */
2254 ctl->zsctl_start = zs_usage_read_internal(ctl, B_TRUE);
2255 if (ctl->zsctl_start == NULL) {
2256 errno_save = errno;
2257 (void) close(ctl->zsctl_door);
2258 free(ctl);
2259 if (errno_save == EINTR)
2260 errno = EINTR;
2261 else
2262 errno = ESRCH;
2263 return (NULL);
2264 }
2265 return (ctl);
2266 }
2267
2268 /*
2269 * Return NULL on error.
2270 *
2271 * ERRORS:
2272 * EINVAL: Invalid function.
2273 */
2274 zs_usage_t *
zs_usage_compute(zs_usage_t * ures,zs_usage_t * uold,zs_usage_t * unew,int func)2275 zs_usage_compute(zs_usage_t *ures, zs_usage_t *uold, zs_usage_t *unew,
2276 int func)
2277 {
2278 zs_system_t *sold, *snew, *sres;
2279 boolean_t alloced = B_FALSE;
2280
2281 if (func != ZS_COMPUTE_USAGE_INTERVAL &&
2282 func != ZS_COMPUTE_USAGE_TOTAL &&
2283 func != ZS_COMPUTE_USAGE_AVERAGE &&
2284 func != ZS_COMPUTE_USAGE_HIGH)
2285 assert(0);
2286
2287 if (ures == NULL) {
2288 alloced = B_TRUE;
2289 ures = zs_usage_alloc();
2290 if (ures == NULL)
2291 return (NULL);
2292 }
2293
2294 sres = ures->zsu_system;
2295 sold = uold->zsu_system;
2296 snew = unew->zsu_system;
2297
2298 switch (func) {
2299 case ZS_COMPUTE_USAGE_INTERVAL:
2300 /* Use system totals from newer interval */
2301 if (sres != snew)
2302 *sres = *snew;
2303
2304 TIMESTRUC_DELTA(sres->zss_cpu_total_time,
2305 snew->zss_cpu_total_time, sold->zss_cpu_total_time);
2306 TIMESTRUC_DELTA(sres->zss_cpu_usage_kern,
2307 snew->zss_cpu_usage_kern, sold->zss_cpu_usage_kern);
2308 TIMESTRUC_DELTA(sres->zss_cpu_usage_zones,
2309 snew->zss_cpu_usage_zones, sold->zss_cpu_usage_zones);
2310 break;
2311 case ZS_COMPUTE_USAGE_HIGH:
2312
2313 /* Find max cpus */
2314 sres->zss_ncpus = MAX(sold->zss_ncpus, snew->zss_ncpus);
2315 sres->zss_ncpus_online = MAX(sold->zss_ncpus_online,
2316 snew->zss_ncpus_online);
2317
2318 /* Find max cpu times */
2319 sres->zss_cpu_total_time = ZS_MAXTS(sold->zss_cpu_total_time,
2320 snew->zss_cpu_total_time);
2321 sres->zss_cpu_usage_kern = ZS_MAXTS(sold->zss_cpu_usage_kern,
2322 snew->zss_cpu_usage_kern);
2323 sres->zss_cpu_usage_zones = ZS_MAXTS(sold->zss_cpu_usage_zones,
2324 snew->zss_cpu_usage_zones);
2325
2326 /* These don't change */
2327 sres->zss_processes_max = snew->zss_processes_max;
2328 sres->zss_lwps_max = snew->zss_lwps_max;
2329 sres->zss_shm_max = snew->zss_shm_max;
2330 sres->zss_shmids_max = snew->zss_shmids_max;
2331 sres->zss_semids_max = snew->zss_semids_max;
2332 sres->zss_msgids_max = snew->zss_msgids_max;
2333 sres->zss_lofi_max = snew->zss_lofi_max;
2334 /*
2335 * Add in memory values and limits. Scale memory to
2336 * avoid overflow.
2337 */
2338 sres->zss_ram_total = MAX(sold->zss_ram_total,
2339 snew->zss_ram_total);
2340 sres->zss_ram_kern = MAX(sold->zss_ram_kern,
2341 snew->zss_ram_kern);
2342 sres->zss_ram_zones = MAX(sold->zss_ram_zones,
2343 snew->zss_ram_zones);
2344 sres->zss_locked_kern = MAX(sold->zss_locked_kern,
2345 snew->zss_locked_kern);
2346 sres->zss_locked_zones = MAX(sold->zss_locked_zones,
2347 snew->zss_locked_zones);
2348 sres->zss_vm_total = MAX(sold->zss_vm_total,
2349 snew->zss_vm_total);
2350 sres->zss_vm_kern = MAX(sold->zss_vm_kern,
2351 snew->zss_vm_kern);
2352 sres->zss_vm_zones = MAX(sold->zss_vm_zones,
2353 snew->zss_vm_zones);
2354 sres->zss_swap_total = MAX(sold->zss_swap_total,
2355 snew->zss_swap_total);
2356 sres->zss_swap_used = MAX(sold->zss_swap_used,
2357 snew->zss_swap_used);
2358
2359 sres->zss_processes = MAX(sold->zss_processes,
2360 snew->zss_processes);
2361 sres->zss_lwps = MAX(sold->zss_lwps, snew->zss_lwps);
2362 sres->zss_shm = MAX(sold->zss_shm, snew->zss_shm);
2363 sres->zss_shmids = MAX(sold->zss_shmids, snew->zss_shmids);
2364 sres->zss_semids = MAX(sold->zss_semids, snew->zss_semids);
2365 sres->zss_msgids = MAX(sold->zss_msgids, snew->zss_msgids);
2366 sres->zss_lofi = MAX(sold->zss_msgids, snew->zss_lofi);
2367 break;
2368 case ZS_COMPUTE_USAGE_TOTAL:
2369 /* FALLTHROUGH */
2370 case ZS_COMPUTE_USAGE_AVERAGE:
2371 ures->zsu_intervals++;
2372
2373 /*
2374 * Add cpus. The total report will divide this by the
2375 * number of intervals to give the average number of cpus
2376 * over all intervals.
2377 */
2378 sres->zss_ncpus = sold->zss_ncpus + snew->zss_ncpus;
2379 sres->zss_ncpus_online = sold->zss_ncpus_online +
2380 snew->zss_ncpus_online;
2381
2382 /* Add in cpu times */
2383 sres->zss_cpu_total_time = sold->zss_cpu_total_time;
2384 TIMESTRUC_ADD_TIMESTRUC(sres->zss_cpu_total_time,
2385 snew->zss_cpu_total_time);
2386 sres->zss_cpu_usage_kern = sold->zss_cpu_usage_kern;
2387 TIMESTRUC_ADD_TIMESTRUC(sres->zss_cpu_usage_kern,
2388 snew->zss_cpu_usage_kern);
2389 sres->zss_cpu_usage_zones = sold->zss_cpu_usage_zones;
2390 TIMESTRUC_ADD_TIMESTRUC(sres->zss_cpu_usage_zones,
2391 snew->zss_cpu_usage_zones);
2392
2393 /* These don't change */
2394 sres->zss_processes_max = snew->zss_processes_max;
2395 sres->zss_lwps_max = snew->zss_lwps_max;
2396 sres->zss_shm_max = snew->zss_shm_max;
2397 sres->zss_shmids_max = snew->zss_shmids_max;
2398 sres->zss_semids_max = snew->zss_semids_max;
2399 sres->zss_msgids_max = snew->zss_msgids_max;
2400 sres->zss_lofi_max = snew->zss_lofi_max;
2401 /*
2402 * Add in memory values and limits. Scale memory to
2403 * avoid overflow.
2404 */
2405 if (sres != sold) {
2406 sres->zss_ram_total = sold->zss_ram_total / 1024;
2407 sres->zss_ram_kern = sold->zss_ram_kern / 1024;
2408 sres->zss_ram_zones = sold->zss_ram_zones / 1024;
2409 sres->zss_locked_kern = sold->zss_locked_kern / 1024;
2410 sres->zss_locked_zones = sold->zss_locked_zones / 1024;
2411 sres->zss_vm_total = sold->zss_vm_total / 1024;
2412 sres->zss_vm_kern = sold->zss_vm_kern / 1024;
2413 sres->zss_vm_zones = sold->zss_vm_zones / 1024;
2414 sres->zss_swap_total = sold->zss_swap_total / 1024;
2415 sres->zss_swap_used = sold->zss_swap_used / 1024;
2416
2417 sres->zss_processes = sold->zss_processes;
2418 sres->zss_lwps = sold->zss_lwps;
2419 sres->zss_shm = sold->zss_shm / 1024;
2420 sres->zss_shmids = sold->zss_shmids;
2421 sres->zss_semids = sold->zss_semids;
2422 sres->zss_msgids = sold->zss_msgids;
2423 sres->zss_lofi = sold->zss_lofi;
2424 }
2425 /* Add in new values. */
2426 sres->zss_ram_total += (snew->zss_ram_total / 1024);
2427 sres->zss_ram_kern += (snew->zss_ram_kern / 1024);
2428 sres->zss_ram_zones += (snew->zss_ram_zones / 1024);
2429 sres->zss_locked_kern += (snew->zss_locked_kern / 1024);
2430 sres->zss_locked_zones += (snew->zss_locked_zones / 1024);
2431 sres->zss_vm_total += (snew->zss_vm_total / 1024);
2432 sres->zss_vm_kern += (snew->zss_vm_kern / 1024);
2433 sres->zss_vm_zones += (snew->zss_vm_zones / 1024);
2434 sres->zss_swap_total += (snew->zss_swap_total / 1024);
2435 sres->zss_swap_used += (snew->zss_swap_used / 1024);
2436 sres->zss_processes += snew->zss_processes;
2437 sres->zss_lwps += snew->zss_lwps;
2438 sres->zss_shm += (snew->zss_shm / 1024);
2439 sres->zss_shmids += snew->zss_shmids;
2440 sres->zss_semids += snew->zss_semids;
2441 sres->zss_msgids += snew->zss_msgids;
2442 sres->zss_lofi += snew->zss_lofi;
2443 break;
2444 default:
2445 if (alloced)
2446 zs_usage_free(ures);
2447 assert(0);
2448 }
2449 if (zs_usage_compute_zones(ures, uold, unew, func) != 0)
2450 goto err;
2451
2452 if (zs_usage_compute_psets(ures, uold, unew, func) != 0)
2453 goto err;
2454
2455 return (ures);
2456 err:
2457 if (alloced)
2458 zs_usage_free(ures);
2459 return (NULL);
2460 }
2461
2462 void
zs_usage_free(zs_usage_t * usage)2463 zs_usage_free(zs_usage_t *usage)
2464 {
2465 zs_zone_t *zone, *ztmp;
2466 zs_pset_t *pset, *ptmp;
2467 zs_pset_zone_t *pz, *pztmp;
2468
2469 if (usage->zsu_mmap) {
2470 (void) munmap((void *)usage, usage->zsu_size);
2471 return;
2472 }
2473 free(usage->zsu_system);
2474 zone = list_head(&usage->zsu_zone_list);
2475 while (zone != NULL) {
2476 ztmp = zone;
2477 zone = list_next(&usage->zsu_zone_list, zone);
2478 free(ztmp);
2479 }
2480 pset = list_head(&usage->zsu_pset_list);
2481 while (pset != NULL) {
2482 pz = list_head(&pset->zsp_usage_list);
2483 while (pz != NULL) {
2484 pztmp = pz;
2485 pz = list_next(&pset->zsp_usage_list, pz);
2486 free(pztmp);
2487 }
2488 ptmp = pset;
2489 pset = list_next(&usage->zsu_pset_list, pset);
2490 free(ptmp);
2491 }
2492 free(usage);
2493 }
2494
2495 zs_usage_set_t *
zs_usage_set_alloc()2496 zs_usage_set_alloc()
2497 {
2498 zs_usage_set_t *set;
2499
2500 set = calloc(sizeof (zs_usage_set_t), 1);
2501 if (set == NULL)
2502 return (NULL);
2503
2504 if ((set->zsus_total = zs_usage_alloc()) == NULL)
2505 goto err;
2506 if ((set->zsus_avg = zs_usage_alloc()) == NULL)
2507 goto err;
2508 if ((set->zsus_high = zs_usage_alloc()) == NULL)
2509 goto err;
2510
2511 return (set);
2512
2513 err:
2514 if (set->zsus_total != NULL)
2515 free(set->zsus_total);
2516 if (set->zsus_avg != NULL)
2517 free(set->zsus_avg);
2518 if (set->zsus_high != NULL)
2519 free(set->zsus_high);
2520
2521 return (NULL);
2522 }
2523
2524 void
zs_usage_set_free(zs_usage_set_t * set)2525 zs_usage_set_free(zs_usage_set_t *set)
2526 {
2527 zs_usage_free(set->zsus_total);
2528 zs_usage_free(set->zsus_avg);
2529 zs_usage_free(set->zsus_high);
2530 free(set);
2531 }
2532
2533 int
zs_usage_set_add(zs_usage_set_t * set,zs_usage_t * usage)2534 zs_usage_set_add(zs_usage_set_t *set, zs_usage_t *usage)
2535 {
2536
2537 /* Compute ongoing functions for usage set */
2538 (void) zs_usage_compute(set->zsus_high, set->zsus_high, usage,
2539 ZS_COMPUTE_USAGE_HIGH);
2540
2541 (void) zs_usage_compute(set->zsus_total, set->zsus_total, usage,
2542 ZS_COMPUTE_USAGE_TOTAL);
2543
2544 (void) zs_usage_compute(set->zsus_avg, set->zsus_avg, usage,
2545 ZS_COMPUTE_USAGE_AVERAGE);
2546
2547 set->zsus_count++;
2548 zs_usage_free(usage);
2549 return (0);
2550 }
2551
2552 int
zs_usage_set_count(zs_usage_set_t * set)2553 zs_usage_set_count(zs_usage_set_t *set)
2554 {
2555 return (set->zsus_count);
2556 }
2557
2558 zs_usage_t *
zs_usage_set_compute(zs_usage_set_t * set,int func)2559 zs_usage_set_compute(zs_usage_set_t *set, int func)
2560 {
2561 zs_usage_t *u;
2562 zs_system_t *s;
2563 zs_zone_t *z;
2564 zs_pset_t *p;
2565 zs_pset_zone_t *pz;
2566 uint_t intervals;
2567 boolean_t average;
2568
2569 switch (func) {
2570 case ZS_COMPUTE_SET_HIGH:
2571 return (set->zsus_high);
2572 case ZS_COMPUTE_SET_TOTAL:
2573 u = set->zsus_total;
2574 average = B_FALSE;
2575 break;
2576 case ZS_COMPUTE_SET_AVERAGE:
2577 u = set->zsus_avg;
2578 average = B_TRUE;
2579 break;
2580 default:
2581 assert(0);
2582 }
2583
2584 s = u->zsu_system;
2585
2586 s->zss_ram_total /= u->zsu_intervals;
2587 s->zss_ram_total *= 1024;
2588 s->zss_ram_kern /= u->zsu_intervals;
2589 s->zss_ram_kern *= 1024;
2590 s->zss_ram_zones /= u->zsu_intervals;
2591 s->zss_ram_zones *= 1024;
2592 s->zss_locked_kern /= u->zsu_intervals;
2593 s->zss_locked_kern *= 1024;
2594 s->zss_locked_zones /= u->zsu_intervals;
2595 s->zss_locked_zones *= 1024;
2596 s->zss_vm_total /= u->zsu_intervals;
2597 s->zss_vm_total *= 1024;
2598 s->zss_vm_kern /= u->zsu_intervals;
2599 s->zss_vm_kern *= 1024;
2600 s->zss_vm_zones /= u->zsu_intervals;
2601 s->zss_vm_zones *= 1024;
2602 s->zss_swap_total /= u->zsu_intervals;
2603 s->zss_swap_total *= 1024;
2604 s->zss_swap_used /= u->zsu_intervals;
2605 s->zss_swap_used *= 1024;
2606 s->zss_processes /= u->zsu_intervals;
2607 s->zss_lwps /= u->zsu_intervals;
2608 s->zss_shm /= u->zsu_intervals;
2609 s->zss_shm *= 1024;
2610 s->zss_shmids /= u->zsu_intervals;
2611 s->zss_semids /= u->zsu_intervals;
2612 s->zss_msgids /= u->zsu_intervals;
2613 s->zss_lofi /= u->zsu_intervals;
2614
2615 s->zss_ncpus /= u->zsu_intervals;
2616 s->zss_ncpus_online /= u->zsu_intervals;
2617
2618 for (z = list_head(&u->zsu_zone_list); z != NULL;
2619 z = list_next(&u->zsu_zone_list, z)) {
2620
2621 if (average) {
2622 intervals = z->zsz_intervals;
2623 } else {
2624 assert(z->zsz_intervals == 0);
2625 intervals = u->zsu_intervals;
2626 }
2627
2628 if (z->zsz_cpu_cap != ZS_LIMIT_NONE)
2629 z->zsz_cpu_cap /= z->zsz_intervals;
2630 if (z->zsz_ram_cap != ZS_LIMIT_NONE)
2631 z->zsz_ram_cap /= z->zsz_intervals;
2632 if (z->zsz_vm_cap != ZS_LIMIT_NONE)
2633 z->zsz_vm_cap /= z->zsz_intervals;
2634 if (z->zsz_locked_cap != ZS_LIMIT_NONE)
2635 z->zsz_locked_cap /= z->zsz_intervals;
2636 if (z->zsz_processes_cap != ZS_LIMIT_NONE)
2637 z->zsz_processes_cap /= z->zsz_intervals;
2638 if (z->zsz_lwps_cap != ZS_LIMIT_NONE)
2639 z->zsz_lwps_cap /= z->zsz_intervals;
2640 if (z->zsz_shm_cap != ZS_LIMIT_NONE)
2641 z->zsz_shm_cap /= z->zsz_intervals;
2642 if (z->zsz_shmids_cap != ZS_LIMIT_NONE)
2643 z->zsz_shmids_cap /= z->zsz_intervals;
2644 if (z->zsz_semids_cap != ZS_LIMIT_NONE)
2645 z->zsz_semids_cap /= z->zsz_intervals;
2646 if (z->zsz_msgids_cap != ZS_LIMIT_NONE)
2647 z->zsz_msgids_cap /= z->zsz_intervals;
2648 if (z->zsz_lofi_cap != ZS_LIMIT_NONE)
2649 z->zsz_lofi_cap /= z->zsz_intervals;
2650
2651 z->zsz_usage_ram /= intervals;
2652 z->zsz_usage_locked /= intervals;
2653 z->zsz_usage_vm /= intervals;
2654 z->zsz_processes /= intervals;
2655 z->zsz_lwps /= intervals;
2656 z->zsz_shm /= intervals;
2657 z->zsz_shmids /= intervals;
2658 z->zsz_semids /= intervals;
2659 z->zsz_msgids /= intervals;
2660 z->zsz_lofi /= intervals;
2661 z->zsz_cpus_online /= intervals;
2662 z->zsz_cpu_shares /= intervals;
2663 }
2664 for (p = list_head(&u->zsu_pset_list); p != NULL;
2665 p = list_next(&u->zsu_pset_list, p)) {
2666
2667 intervals = p->zsp_intervals;
2668
2669 p->zsp_online /= intervals;
2670 p->zsp_size /= intervals;
2671 p->zsp_min /= intervals;
2672 p->zsp_max /= intervals;
2673 p->zsp_importance /= intervals;
2674 p->zsp_cpu_shares /= intervals;
2675
2676 for (pz = list_head(&p->zsp_usage_list); pz != NULL;
2677 pz = list_next(&p->zsp_usage_list, pz)) {
2678
2679 if (average) {
2680 intervals = pz->zspz_intervals;
2681 } else {
2682 assert(pz->zspz_intervals == 0);
2683 intervals = p->zsp_intervals;
2684 }
2685 pz->zspz_cpu_shares /= intervals;
2686 }
2687 }
2688 return (u);
2689 }
2690
2691 /*
2692 * Returns 0 on success. Trips assert on invalid property.
2693 */
2694 void
zs_resource_property(zs_usage_t * u,int res,int prop,zs_property_t * p)2695 zs_resource_property(zs_usage_t *u, int res, int prop, zs_property_t *p)
2696 {
2697 switch (res) {
2698 case ZS_RESOURCE_CPU:
2699 switch (prop) {
2700 case ZS_RESOURCE_PROP_CPU_TOTAL:
2701 p->zsp_id = prop;
2702 p->zsp_type = ZS_PROP_TYPE_UINT64;
2703 p->zsp_v.zsv_uint64 = u->zsu_system->zss_ncpus;
2704 break;
2705 case ZS_RESOURCE_PROP_CPU_ONLINE:
2706 p->zsp_id = prop;
2707 p->zsp_type = ZS_PROP_TYPE_UINT64;
2708 p->zsp_v.zsv_uint64 = u->zsu_system->zss_ncpus_online;
2709 break;
2710 default:
2711 assert(0);
2712 }
2713 break;
2714 case ZS_RESOURCE_RAM_RSS:
2715 case ZS_RESOURCE_RAM_LOCKED:
2716 case ZS_RESOURCE_VM:
2717 case ZS_RESOURCE_DISK_SWAP:
2718 case ZS_RESOURCE_LWPS:
2719 case ZS_RESOURCE_PROCESSES:
2720 case ZS_RESOURCE_SHM_MEMORY:
2721 case ZS_RESOURCE_SHM_IDS:
2722 case ZS_RESOURCE_SEM_IDS:
2723 case ZS_RESOURCE_MSG_IDS:
2724 /* FALLTHROUGH */
2725 default:
2726 assert(0);
2727 }
2728 }
2729
2730 /*
2731 * Returns one of ZS_RESOURCE_TYPE_* on success. Asserts on invalid
2732 * resource.
2733 */
2734 int
zs_resource_type(int res)2735 zs_resource_type(int res)
2736 {
2737 switch (res) {
2738 case ZS_RESOURCE_CPU:
2739 return (ZS_RESOURCE_TYPE_TIME);
2740 break;
2741 case ZS_RESOURCE_RAM_RSS:
2742 case ZS_RESOURCE_RAM_LOCKED:
2743 case ZS_RESOURCE_VM:
2744 case ZS_RESOURCE_DISK_SWAP:
2745 case ZS_RESOURCE_SHM_MEMORY:
2746 return (ZS_RESOURCE_TYPE_BYTES);
2747 break;
2748 case ZS_RESOURCE_LWPS:
2749 case ZS_RESOURCE_PROCESSES:
2750 case ZS_RESOURCE_SHM_IDS:
2751 case ZS_RESOURCE_SEM_IDS:
2752 case ZS_RESOURCE_MSG_IDS:
2753 return (ZS_RESOURCE_TYPE_COUNT);
2754 break;
2755 default:
2756 assert(0);
2757 return (0);
2758 }
2759 }
2760
2761 /*
2762 * Get total available resource on system
2763 */
2764 uint64_t
zs_resource_total_uint64(zs_usage_t * u,int res)2765 zs_resource_total_uint64(zs_usage_t *u, int res)
2766 {
2767 uint64_t v;
2768
2769 switch (res) {
2770 case ZS_RESOURCE_CPU:
2771 v = zs_cpu_total_cpu(u);
2772 break;
2773 case ZS_RESOURCE_RAM_RSS:
2774 v = zs_physical_memory_total(u);
2775 break;
2776 case ZS_RESOURCE_RAM_LOCKED:
2777 v = zs_locked_memory_total(u);
2778 break;
2779 case ZS_RESOURCE_VM:
2780 v = zs_virtual_memory_total(u);
2781 break;
2782 case ZS_RESOURCE_DISK_SWAP:
2783 v = zs_disk_swap_total(u);
2784 break;
2785 case ZS_RESOURCE_LWPS:
2786 v = zs_lwps_total(u);
2787 break;
2788 case ZS_RESOURCE_PROCESSES:
2789 v = zs_processes_total(u);
2790 break;
2791 case ZS_RESOURCE_SHM_MEMORY:
2792 v = zs_shm_total(u);
2793 break;
2794 case ZS_RESOURCE_SHM_IDS:
2795 v = zs_shmids_total(u);
2796 break;
2797 case ZS_RESOURCE_SEM_IDS:
2798 v = zs_semids_total(u);
2799 break;
2800 case ZS_RESOURCE_MSG_IDS:
2801 v = zs_msgids_total(u);
2802 break;
2803 case ZS_RESOURCE_LOFI:
2804 v = zs_lofi_total(u);
2805 break;
2806 default:
2807 assert(0);
2808 }
2809 return (v);
2810 }
2811
2812 /*
2813 * Get amount of used resource.
2814 */
2815 uint64_t
zs_resource_used_uint64(zs_usage_t * u,int res,int user)2816 zs_resource_used_uint64(zs_usage_t *u, int res, int user)
2817 {
2818 uint64_t v;
2819
2820 switch (res) {
2821 case ZS_RESOURCE_CPU:
2822 switch (user) {
2823 case ZS_USER_ALL:
2824 v = zs_cpu_usage_all_cpu(u);
2825 break;
2826 case ZS_USER_KERNEL:
2827 v = zs_cpu_usage_kernel_cpu(u);
2828 break;
2829 case ZS_USER_ZONES:
2830 v = zs_cpu_usage_zones_cpu(u);
2831 break;
2832 case ZS_USER_FREE:
2833 v = zs_cpu_usage_idle_cpu(u);
2834 break;
2835 default:
2836 assert(0);
2837 }
2838 break;
2839 case ZS_RESOURCE_RAM_RSS:
2840 switch (user) {
2841 case ZS_USER_ALL:
2842 v = zs_physical_memory_usage_all(u);
2843 break;
2844 case ZS_USER_KERNEL:
2845 v = zs_physical_memory_usage_kernel(u);
2846 break;
2847 case ZS_USER_ZONES:
2848 v = zs_physical_memory_usage_zones(u);
2849 break;
2850 case ZS_USER_FREE:
2851 v = zs_physical_memory_usage_free(u);
2852 break;
2853 default:
2854 assert(0);
2855 }
2856 break;
2857 case ZS_RESOURCE_RAM_LOCKED:
2858 switch (user) {
2859 case ZS_USER_ALL:
2860 v = zs_locked_memory_usage_all(u);
2861 break;
2862 case ZS_USER_KERNEL:
2863 v = zs_locked_memory_usage_kernel(u);
2864 break;
2865 case ZS_USER_ZONES:
2866 v = zs_locked_memory_usage_zones(u);
2867 break;
2868 case ZS_USER_FREE:
2869 v = zs_locked_memory_usage_free(u);
2870 break;
2871 default:
2872 assert(0);
2873 }
2874 break;
2875 case ZS_RESOURCE_VM:
2876 switch (user) {
2877 case ZS_USER_ALL:
2878 v = zs_virtual_memory_usage_all(u);
2879 break;
2880 case ZS_USER_KERNEL:
2881 v = zs_virtual_memory_usage_kernel(u);
2882 break;
2883 case ZS_USER_ZONES:
2884 v = zs_virtual_memory_usage_zones(u);
2885 break;
2886 case ZS_USER_FREE:
2887 v = zs_virtual_memory_usage_free(u);
2888 break;
2889 default:
2890 assert(0);
2891 }
2892 break;
2893 case ZS_RESOURCE_DISK_SWAP:
2894 switch (user) {
2895 case ZS_USER_ALL:
2896 v = zs_disk_swap_usage_all(u);
2897 break;
2898 case ZS_USER_FREE:
2899 v = zs_disk_swap_usage_free(u);
2900 break;
2901 case ZS_USER_KERNEL:
2902 case ZS_USER_ZONES:
2903 /* FALLTHROUGH */
2904 default:
2905 assert(0);
2906 }
2907 break;
2908 case ZS_RESOURCE_LWPS:
2909 switch (user) {
2910 case ZS_USER_ALL:
2911 case ZS_USER_ZONES:
2912 v = zs_lwps_usage_all(u);
2913 break;
2914 case ZS_USER_FREE:
2915 v = zs_lwps_total(u) - zs_lwps_usage_all(u);
2916 break;
2917 case ZS_USER_KERNEL:
2918 v = 0;
2919 break;
2920 default:
2921 assert(0);
2922 }
2923 break;
2924 case ZS_RESOURCE_PROCESSES:
2925 switch (user) {
2926 case ZS_USER_ALL:
2927 case ZS_USER_ZONES:
2928 v = zs_processes_usage_all(u);
2929 break;
2930 case ZS_USER_FREE:
2931 v = zs_processes_total(u) - zs_processes_usage_all(u);
2932 break;
2933 case ZS_USER_KERNEL:
2934 v = 0;
2935 break;
2936 default:
2937 assert(0);
2938 }
2939 break;
2940 case ZS_RESOURCE_SHM_MEMORY:
2941 switch (user) {
2942 case ZS_USER_ALL:
2943 case ZS_USER_ZONES:
2944 v = zs_shm_usage_all(u);
2945 break;
2946 case ZS_USER_FREE:
2947 v = zs_shm_total(u) -
2948 zs_shm_usage_all(u);
2949 break;
2950 case ZS_USER_KERNEL:
2951 v = 0;
2952 break;
2953 default:
2954 assert(0);
2955 }
2956 break;
2957 case ZS_RESOURCE_SHM_IDS:
2958 switch (user) {
2959 case ZS_USER_ALL:
2960 case ZS_USER_ZONES:
2961 v = zs_shmids_usage_all(u);
2962 break;
2963 case ZS_USER_FREE:
2964 v = zs_shmids_total(u) - zs_shmids_usage_all(u);
2965 break;
2966 case ZS_USER_KERNEL:
2967 v = 0;
2968 break;
2969 default:
2970 assert(0);
2971 }
2972 break;
2973 case ZS_RESOURCE_SEM_IDS:
2974 switch (user) {
2975 case ZS_USER_ALL:
2976 case ZS_USER_ZONES:
2977 v = zs_semids_usage_all(u);
2978 break;
2979 case ZS_USER_FREE:
2980 v = zs_semids_total(u) - zs_semids_usage_all(u);
2981 break;
2982 case ZS_USER_KERNEL:
2983 v = 0;
2984 break;
2985 default:
2986 assert(0);
2987 }
2988 break;
2989 case ZS_RESOURCE_MSG_IDS:
2990 switch (user) {
2991 case ZS_USER_ALL:
2992 case ZS_USER_ZONES:
2993 v = zs_msgids_usage_all(u);
2994 break;
2995 case ZS_USER_FREE:
2996 v = zs_msgids_total(u) - zs_msgids_usage_all(u);
2997 break;
2998 case ZS_USER_KERNEL:
2999 v = 0;
3000 break;
3001 default:
3002 assert(0);
3003 }
3004 break;
3005 case ZS_RESOURCE_LOFI:
3006 switch (user) {
3007 case ZS_USER_ALL:
3008 case ZS_USER_ZONES:
3009 v = zs_lofi_usage_all(u);
3010 break;
3011 case ZS_USER_FREE:
3012 v = zs_lofi_total(u) - zs_lofi_usage_all(u);
3013 break;
3014 case ZS_USER_KERNEL:
3015 v = 0;
3016 break;
3017 default:
3018 assert(0);
3019 }
3020 break;
3021
3022 default:
3023 assert(0);
3024 }
3025 return (v);
3026 }
3027
3028 /*
3029 * Get used resource as a percent of total resource.
3030 */
3031 uint_t
zs_resource_used_pct(zs_usage_t * u,int res,int user)3032 zs_resource_used_pct(zs_usage_t *u, int res, int user)
3033 {
3034 uint64_t v;
3035
3036 switch (res) {
3037 case ZS_RESOURCE_CPU:
3038 switch (user) {
3039 case ZS_USER_ALL:
3040 v = zs_cpu_usage_all_pct(u);
3041 break;
3042 case ZS_USER_KERNEL:
3043 v = zs_cpu_usage_kernel_pct(u);
3044 break;
3045 case ZS_USER_ZONES:
3046 v = zs_cpu_usage_zones_pct(u);
3047 break;
3048 case ZS_USER_FREE:
3049 v = zs_cpu_usage_idle_pct(u);
3050 break;
3051 default:
3052 assert(0);
3053 }
3054 break;
3055 case ZS_RESOURCE_RAM_RSS:
3056 switch (user) {
3057 case ZS_USER_ALL:
3058 v = zs_physical_memory_usage_all_pct(u);
3059 break;
3060 case ZS_USER_KERNEL:
3061 v = zs_physical_memory_usage_kernel_pct(u);
3062 break;
3063 case ZS_USER_ZONES:
3064 v = zs_physical_memory_usage_zones_pct(u);
3065 break;
3066 case ZS_USER_FREE:
3067 v = zs_physical_memory_usage_free_pct(u);
3068 break;
3069 default:
3070 assert(0);
3071 }
3072 break;
3073 case ZS_RESOURCE_RAM_LOCKED:
3074 switch (user) {
3075 case ZS_USER_ALL:
3076 v = zs_locked_memory_usage_all_pct(u);
3077 break;
3078 case ZS_USER_KERNEL:
3079 v = zs_locked_memory_usage_kernel_pct(u);
3080 break;
3081 case ZS_USER_ZONES:
3082 v = zs_locked_memory_usage_zones_pct(u);
3083 break;
3084 case ZS_USER_FREE:
3085 v = zs_locked_memory_usage_free_pct(u);
3086 break;
3087 default:
3088 assert(0);
3089 }
3090 break;
3091 case ZS_RESOURCE_VM:
3092 switch (user) {
3093 case ZS_USER_ALL:
3094 v = zs_virtual_memory_usage_all_pct(u);
3095 break;
3096 case ZS_USER_KERNEL:
3097 v = zs_virtual_memory_usage_kernel_pct(u);
3098 break;
3099 case ZS_USER_ZONES:
3100 v = zs_virtual_memory_usage_zones_pct(u);
3101 break;
3102 case ZS_USER_FREE:
3103 v = zs_virtual_memory_usage_free_pct(u);
3104 break;
3105 default:
3106 assert(0);
3107 }
3108 break;
3109 case ZS_RESOURCE_DISK_SWAP:
3110 switch (user) {
3111 case ZS_USER_ALL:
3112 v = zs_disk_swap_usage_all_pct(u);
3113 break;
3114 case ZS_USER_FREE:
3115 v = zs_disk_swap_usage_free_pct(u);
3116 break;
3117 case ZS_USER_KERNEL:
3118 case ZS_USER_ZONES:
3119 /* FALLTHROUGH */
3120 default:
3121 assert(0);
3122 }
3123 break;
3124 case ZS_RESOURCE_LWPS:
3125 switch (user) {
3126 case ZS_USER_ALL:
3127 case ZS_USER_ZONES:
3128 v = zs_lwps_usage_all_pct(u);
3129 break;
3130 case ZS_USER_FREE:
3131 v = ZSD_PCT_INT - zs_lwps_usage_all_pct(u);
3132 break;
3133 case ZS_USER_KERNEL:
3134 v = 0;
3135 break;
3136 default:
3137 assert(0);
3138 }
3139 break;
3140 case ZS_RESOURCE_PROCESSES:
3141 switch (user) {
3142 case ZS_USER_ALL:
3143 case ZS_USER_ZONES:
3144 v = zs_processes_usage_all_pct(u);
3145 break;
3146 case ZS_USER_FREE:
3147 v = ZSD_PCT_INT - zs_processes_usage_all_pct(u);
3148 break;
3149 case ZS_USER_KERNEL:
3150 v = 0;
3151 break;
3152 default:
3153 assert(0);
3154 }
3155 break;
3156 case ZS_RESOURCE_SHM_MEMORY:
3157 switch (user) {
3158 case ZS_USER_ALL:
3159 case ZS_USER_ZONES:
3160 v = zs_shm_usage_all_pct(u);
3161 break;
3162 case ZS_USER_FREE:
3163 v = ZSD_PCT_INT - zs_shm_usage_all_pct(u);
3164 break;
3165 case ZS_USER_KERNEL:
3166 v = 0;
3167 break;
3168 default:
3169 assert(0);
3170 }
3171 break;
3172 case ZS_RESOURCE_SHM_IDS:
3173 switch (user) {
3174 case ZS_USER_ALL:
3175 case ZS_USER_ZONES:
3176 v = zs_shmids_usage_all_pct(u);
3177 break;
3178 case ZS_USER_FREE:
3179 v = ZSD_PCT_INT - zs_shmids_usage_all_pct(u);
3180 break;
3181 case ZS_USER_KERNEL:
3182 v = 0;
3183 break;
3184 default:
3185 assert(0);
3186 }
3187 break;
3188 case ZS_RESOURCE_SEM_IDS:
3189 switch (user) {
3190 case ZS_USER_ALL:
3191 case ZS_USER_ZONES:
3192 v = zs_semids_usage_all_pct(u);
3193 break;
3194 case ZS_USER_FREE:
3195 v = ZSD_PCT_INT - zs_semids_usage_all_pct(u);
3196 break;
3197 case ZS_USER_KERNEL:
3198 v = 0;
3199 break;
3200 default:
3201 assert(0);
3202 }
3203 break;
3204 case ZS_RESOURCE_MSG_IDS:
3205 switch (user) {
3206 case ZS_USER_ALL:
3207 case ZS_USER_ZONES:
3208 v = zs_msgids_usage_all_pct(u);
3209 break;
3210 case ZS_USER_FREE:
3211 v = ZSD_PCT_INT - zs_msgids_usage_all_pct(u);
3212 break;
3213 case ZS_USER_KERNEL:
3214 v = 0;
3215 break;
3216 default:
3217 assert(0);
3218 }
3219 break;
3220 case ZS_RESOURCE_LOFI:
3221 switch (user) {
3222 case ZS_USER_ALL:
3223 case ZS_USER_ZONES:
3224 v = zs_lofi_usage_all_pct(u);
3225 break;
3226 case ZS_USER_FREE:
3227 v = ZSD_PCT_INT - zs_lofi_usage_all_pct(u);
3228 break;
3229 case ZS_USER_KERNEL:
3230 v = 0;
3231 break;
3232 default:
3233 assert(0);
3234 }
3235 break;
3236 default:
3237 assert(0);
3238 }
3239
3240 return (v);
3241 }
3242
3243 /*
3244 * Get resource used by individual zone.
3245 */
3246 uint64_t
zs_resource_used_zone_uint64(zs_zone_t * z,int res)3247 zs_resource_used_zone_uint64(zs_zone_t *z, int res)
3248 {
3249 uint64_t v;
3250
3251 switch (res) {
3252 case ZS_RESOURCE_CPU:
3253 v = zs_cpu_usage_zone_cpu(z);
3254 break;
3255 case ZS_RESOURCE_RAM_RSS:
3256 v = zs_physical_memory_usage_zone(z);
3257 break;
3258 case ZS_RESOURCE_RAM_LOCKED:
3259 v = zs_locked_memory_usage_zone(z);
3260 break;
3261 case ZS_RESOURCE_VM:
3262 v = zs_virtual_memory_usage_zone(z);
3263 break;
3264 case ZS_RESOURCE_DISK_SWAP:
3265 assert(0);
3266 break;
3267 case ZS_RESOURCE_LWPS:
3268 v = zs_lwps_usage_zone(z);
3269 break;
3270 case ZS_RESOURCE_PROCESSES:
3271 v = zs_processes_usage_zone(z);
3272 break;
3273 case ZS_RESOURCE_SHM_MEMORY:
3274 v = zs_shm_usage_zone(z);
3275 break;
3276 case ZS_RESOURCE_SHM_IDS:
3277 v = zs_shmids_usage_zone(z);
3278 break;
3279 case ZS_RESOURCE_SEM_IDS:
3280 v = zs_semids_usage_zone(z);
3281 break;
3282 case ZS_RESOURCE_MSG_IDS:
3283 v = zs_msgids_usage_zone(z);
3284 break;
3285 case ZS_RESOURCE_LOFI:
3286 v = zs_lofi_usage_zone(z);
3287 break;
3288 default:
3289 assert(0);
3290 }
3291 return (v);
3292 }
3293
3294 /*
3295 * Get resource used by individual zone as percent
3296 */
3297 uint_t
zs_resource_used_zone_pct(zs_zone_t * z,int res)3298 zs_resource_used_zone_pct(zs_zone_t *z, int res)
3299 {
3300 uint_t v;
3301
3302 switch (res) {
3303 case ZS_RESOURCE_CPU:
3304 v = zs_cpu_usage_zone_pct(z);
3305 break;
3306 case ZS_RESOURCE_RAM_RSS:
3307 v = zs_physical_memory_usage_zone_pct(z);
3308 break;
3309 case ZS_RESOURCE_RAM_LOCKED:
3310 v = zs_locked_memory_usage_zone_pct(z);
3311 break;
3312 case ZS_RESOURCE_VM:
3313 v = zs_virtual_memory_usage_zone_pct(z);
3314 break;
3315 case ZS_RESOURCE_DISK_SWAP:
3316 assert(0);
3317 break;
3318 case ZS_RESOURCE_LWPS:
3319 v = zs_lwps_usage_zone_pct(z);
3320 break;
3321 case ZS_RESOURCE_PROCESSES:
3322 v = zs_processes_usage_zone_pct(z);
3323 break;
3324 case ZS_RESOURCE_SHM_MEMORY:
3325 v = zs_shm_usage_zone_pct(z);
3326 break;
3327 case ZS_RESOURCE_SHM_IDS:
3328 v = zs_shmids_usage_zone_pct(z);
3329 break;
3330 case ZS_RESOURCE_SEM_IDS:
3331 v = zs_semids_usage_zone_pct(z);
3332 break;
3333 case ZS_RESOURCE_MSG_IDS:
3334 v = zs_msgids_usage_zone_pct(z);
3335 break;
3336 case ZS_RESOURCE_LOFI:
3337 v = zs_lofi_usage_zone_pct(z);
3338 break;
3339 default:
3340 assert(0);
3341 }
3342 return (v);
3343 }
3344
3345 /*
3346 * Get total time available for a resource
3347 */
3348 void
zs_resource_total_time(zs_usage_t * u,int res,timestruc_t * t)3349 zs_resource_total_time(zs_usage_t *u, int res, timestruc_t *t)
3350 {
3351 switch (res) {
3352 case ZS_RESOURCE_CPU:
3353 zs_cpu_total_time(u, t);
3354 break;
3355 case ZS_RESOURCE_RAM_RSS:
3356 case ZS_RESOURCE_RAM_LOCKED:
3357 case ZS_RESOURCE_VM:
3358 case ZS_RESOURCE_DISK_SWAP:
3359 case ZS_RESOURCE_LWPS:
3360 case ZS_RESOURCE_PROCESSES:
3361 case ZS_RESOURCE_SHM_MEMORY:
3362 case ZS_RESOURCE_SHM_IDS:
3363 case ZS_RESOURCE_SEM_IDS:
3364 case ZS_RESOURCE_MSG_IDS:
3365 /* FALLTHROUGH */
3366 default:
3367 assert(0);
3368 }
3369 }
3370
3371 /*
3372 * Get total time used for a resource
3373 */
3374 void
zs_resource_used_time(zs_usage_t * u,int res,int user,timestruc_t * t)3375 zs_resource_used_time(zs_usage_t *u, int res, int user, timestruc_t *t)
3376 {
3377 switch (res) {
3378 case ZS_RESOURCE_CPU:
3379 switch (user) {
3380 case ZS_USER_ALL:
3381 zs_cpu_usage_all(u, t);
3382 break;
3383 case ZS_USER_KERNEL:
3384 zs_cpu_usage_kernel(u, t);
3385 break;
3386 case ZS_USER_ZONES:
3387 zs_cpu_usage_zones(u, t);
3388 break;
3389 case ZS_USER_FREE:
3390 zs_cpu_usage_idle(u, t);
3391 break;
3392 default:
3393 assert(0);
3394 }
3395 break;
3396 case ZS_RESOURCE_RAM_RSS:
3397 case ZS_RESOURCE_RAM_LOCKED:
3398 case ZS_RESOURCE_VM:
3399 case ZS_RESOURCE_DISK_SWAP:
3400 case ZS_RESOURCE_LWPS:
3401 case ZS_RESOURCE_PROCESSES:
3402 case ZS_RESOURCE_SHM_MEMORY:
3403 case ZS_RESOURCE_SHM_IDS:
3404 case ZS_RESOURCE_SEM_IDS:
3405 case ZS_RESOURCE_MSG_IDS:
3406 /* FALLTHROUGH */
3407 default:
3408 assert(0);
3409 }
3410 }
3411
3412 /*
3413 * Get total resource time used for a particular zone
3414 */
3415 void
zs_resource_used_zone_time(zs_zone_t * z,int res,timestruc_t * t)3416 zs_resource_used_zone_time(zs_zone_t *z, int res, timestruc_t *t)
3417 {
3418 switch (res) {
3419 case ZS_RESOURCE_CPU:
3420 zs_cpu_usage_zone(z, t);
3421 break;
3422 case ZS_RESOURCE_RAM_RSS:
3423 case ZS_RESOURCE_RAM_LOCKED:
3424 case ZS_RESOURCE_VM:
3425 case ZS_RESOURCE_DISK_SWAP:
3426 case ZS_RESOURCE_SHM_MEMORY:
3427 case ZS_RESOURCE_LWPS:
3428 case ZS_RESOURCE_PROCESSES:
3429 case ZS_RESOURCE_SHM_IDS:
3430 case ZS_RESOURCE_SEM_IDS:
3431 case ZS_RESOURCE_MSG_IDS:
3432 /* FALLTHROUGH */
3433 default:
3434 assert(0);
3435 }
3436 }
3437
3438
3439 int
zs_zone_list(zs_usage_t * usage,zs_zone_t ** zonelist,int num)3440 zs_zone_list(zs_usage_t *usage, zs_zone_t **zonelist, int num)
3441 {
3442 int i = 0;
3443 zs_zone_t *zone, *tmp;
3444
3445 /* copy what fits of the zone list into the buffer */
3446 for (zone = list_head(&usage->zsu_zone_list); zone != NULL;
3447 zone = list_next(&usage->zsu_zone_list, zone)) {
3448
3449 /* put the global zone at the first position */
3450 if (i < num) {
3451 if (zone->zsz_id == GLOBAL_ZONEID) {
3452 tmp = zonelist[0];
3453 zonelist[i] = tmp;
3454 zonelist[0] = zone;
3455 } else {
3456 zonelist[i] = zone;
3457 }
3458 }
3459 i++;
3460 }
3461 return (i);
3462 }
3463
3464 zs_zone_t *
zs_zone_first(zs_usage_t * usage)3465 zs_zone_first(zs_usage_t *usage)
3466 {
3467 return (list_head(&usage->zsu_zone_list));
3468 }
3469
3470 zs_zone_t *
zs_zone_next(zs_usage_t * usage,zs_zone_t * zone)3471 zs_zone_next(zs_usage_t *usage, zs_zone_t *zone)
3472 {
3473 return (list_next(&usage->zsu_zone_list, zone));
3474 }
3475
3476
3477 /*
3478 * Gets a zone property
3479 */
3480 void
zs_zone_property(zs_zone_t * zone,int prop,zs_property_t * p)3481 zs_zone_property(zs_zone_t *zone, int prop, zs_property_t *p)
3482 {
3483 switch (prop) {
3484 case ZS_ZONE_PROP_NAME:
3485 p->zsp_type = ZS_PROP_TYPE_STRING;
3486 p->zsp_id = prop;
3487 (void) zs_zone_name(zone, p->zsp_v.zsv_string,
3488 sizeof (p->zsp_v.zsv_string));
3489 break;
3490 case ZS_ZONE_PROP_ID:
3491 p->zsp_type = ZS_PROP_TYPE_INT;
3492 p->zsp_id = prop;
3493 p->zsp_v.zsv_int = zs_zone_id(zone);
3494 break;
3495 case ZS_ZONE_PROP_IPTYPE:
3496 p->zsp_type = ZS_PROP_TYPE_UINT;
3497 p->zsp_id = prop;
3498 p->zsp_v.zsv_uint = zs_zone_iptype(zone);
3499 break;
3500 case ZS_ZONE_PROP_CPUTYPE:
3501 p->zsp_type = ZS_PROP_TYPE_UINT;
3502 p->zsp_id = prop;
3503 p->zsp_v.zsv_uint = zs_zone_cputype(zone);
3504 break;
3505 case ZS_ZONE_PROP_SCHEDULERS:
3506 p->zsp_type = ZS_PROP_TYPE_UINT;
3507 p->zsp_id = prop;
3508 p->zsp_v.zsv_uint = zs_zone_schedulers(zone);
3509 break;
3510 case ZS_ZONE_PROP_CPU_SHARES:
3511 p->zsp_type = ZS_PROP_TYPE_UINT64;
3512 p->zsp_id = prop;
3513 p->zsp_v.zsv_uint64 = zs_zone_cpu_shares(zone);
3514 break;
3515 case ZS_ZONE_PROP_POOLNAME:
3516 p->zsp_type = ZS_PROP_TYPE_STRING;
3517 p->zsp_id = prop;
3518 (void) zs_zone_poolname(zone, p->zsp_v.zsv_string,
3519 sizeof (p->zsp_v.zsv_string));
3520 break;
3521 case ZS_ZONE_PROP_PSETNAME:
3522 p->zsp_type = ZS_PROP_TYPE_STRING;
3523 p->zsp_id = prop;
3524 (void) zs_zone_psetname(zone, p->zsp_v.zsv_string,
3525 sizeof (p->zsp_v.zsv_string));
3526 break;
3527 /* Not implemented */
3528 case ZS_ZONE_PROP_DEFAULT_SCHED:
3529 case ZS_ZONE_PROP_UPTIME:
3530 case ZS_ZONE_PROP_BOOTTIME:
3531 /* FALLTHROUGH */
3532 default:
3533 assert(0);
3534 }
3535 }
3536
3537 int
zs_zone_limit_type(int limit)3538 zs_zone_limit_type(int limit)
3539 {
3540 switch (limit) {
3541 case ZS_LIMIT_CPU:
3542 case ZS_LIMIT_CPU_SHARES:
3543 return (ZS_LIMIT_TYPE_TIME);
3544 case ZS_LIMIT_RAM_RSS:
3545 case ZS_LIMIT_RAM_LOCKED:
3546 case ZS_LIMIT_VM:
3547 case ZS_LIMIT_SHM_MEMORY:
3548 return (ZS_LIMIT_TYPE_BYTES);
3549 case ZS_LIMIT_LWPS:
3550 case ZS_LIMIT_PROCESSES:
3551 case ZS_LIMIT_SHM_IDS:
3552 case ZS_LIMIT_MSG_IDS:
3553 case ZS_LIMIT_SEM_IDS:
3554 return (ZS_LIMIT_TYPE_COUNT);
3555 default:
3556 assert(0);
3557 return (0);
3558 }
3559 }
3560 /*
3561 * Gets the zones limit. Returns ZS_LIMIT_NONE if no limit set.
3562 */
3563 uint64_t
zs_zone_limit_uint64(zs_zone_t * z,int limit)3564 zs_zone_limit_uint64(zs_zone_t *z, int limit)
3565 {
3566 uint64_t v;
3567
3568 switch (limit) {
3569 case ZS_LIMIT_CPU:
3570 v = zs_zone_cpu_cap(z);
3571 break;
3572 case ZS_LIMIT_CPU_SHARES:
3573 v = zs_zone_cpu_shares(z);
3574 break;
3575 case ZS_LIMIT_RAM_RSS:
3576 v = zs_zone_physical_memory_cap(z);
3577 break;
3578 case ZS_LIMIT_RAM_LOCKED:
3579 v = zs_zone_locked_memory_cap(z);
3580 break;
3581 case ZS_LIMIT_VM:
3582 v = zs_zone_virtual_memory_cap(z);
3583 break;
3584 case ZS_LIMIT_LWPS:
3585 v = z->zsz_lwps_cap;
3586 break;
3587 case ZS_LIMIT_PROCESSES:
3588 v = z->zsz_processes_cap;
3589 break;
3590 case ZS_LIMIT_SHM_MEMORY:
3591 v = z->zsz_shm_cap;
3592 break;
3593 case ZS_LIMIT_SHM_IDS:
3594 v = z->zsz_shmids_cap;
3595 break;
3596 case ZS_LIMIT_SEM_IDS:
3597 v = z->zsz_semids_cap;
3598 break;
3599 case ZS_LIMIT_MSG_IDS:
3600 v = z->zsz_msgids_cap;
3601 break;
3602 case ZS_LIMIT_LOFI:
3603 v = z->zsz_lofi_cap;
3604 break;
3605 default:
3606 assert(0);
3607 }
3608 return (v);
3609 }
3610
3611 /*
3612 * Gets the amount of resource used for a limit. Returns ZS_LIMIT_NONE if
3613 * no limit configured.
3614 */
3615 uint64_t
zs_zone_limit_used_uint64(zs_zone_t * z,int limit)3616 zs_zone_limit_used_uint64(zs_zone_t *z, int limit)
3617 {
3618 uint64_t v;
3619
3620 switch (limit) {
3621 case ZS_LIMIT_CPU:
3622 v = zs_zone_cpu_cap_used(z);
3623 break;
3624 case ZS_LIMIT_CPU_SHARES:
3625 v = zs_zone_cpu_shares_used(z);
3626 break;
3627 case ZS_LIMIT_RAM_RSS:
3628 v = zs_zone_physical_memory_cap_used(z);
3629 break;
3630 case ZS_LIMIT_RAM_LOCKED:
3631 v = zs_zone_locked_memory_cap_used(z);
3632 break;
3633 case ZS_LIMIT_VM:
3634 v = zs_zone_virtual_memory_cap_used(z);
3635 break;
3636 case ZS_LIMIT_LWPS:
3637 v = z->zsz_lwps;
3638 break;
3639 case ZS_LIMIT_PROCESSES:
3640 v = z->zsz_processes;
3641 break;
3642 case ZS_LIMIT_SHM_MEMORY:
3643 v = z->zsz_shm;
3644 break;
3645 case ZS_LIMIT_SHM_IDS:
3646 v = z->zsz_shmids;
3647 break;
3648 case ZS_LIMIT_SEM_IDS:
3649 v = z->zsz_semids;
3650 break;
3651 case ZS_LIMIT_MSG_IDS:
3652 v = z->zsz_msgids;
3653 break;
3654 case ZS_LIMIT_LOFI:
3655 v = z->zsz_lofi;
3656 break;
3657 default:
3658 assert(0);
3659 }
3660 return (v);
3661 }
3662
3663 /*
3664 * Gets time used under limit. Time is zero if no limit is configured
3665 */
3666 void
zs_zone_limit_time(zs_zone_t * z,int limit,timestruc_t * v)3667 zs_zone_limit_time(zs_zone_t *z, int limit, timestruc_t *v)
3668 {
3669 switch (limit) {
3670 case ZS_LIMIT_CPU:
3671 if (z->zsz_cpu_cap == ZS_LIMIT_NONE) {
3672 v->tv_sec = 0;
3673 v->tv_nsec = 0;
3674 break;
3675 }
3676 zs_zone_cpu_cap_time(z, v);
3677 break;
3678 case ZS_LIMIT_CPU_SHARES:
3679 if (z->zsz_cpu_shares == ZS_LIMIT_NONE ||
3680 z->zsz_cpu_shares == ZS_SHARES_UNLIMITED ||
3681 z->zsz_cpu_shares == 0 ||
3682 (z->zsz_scheds & ZS_SCHED_FSS) == 0) {
3683 v->tv_sec = 0;
3684 v->tv_nsec = 0;
3685 break;
3686 }
3687 zs_zone_cpu_share_time(z, v);
3688 break;
3689 case ZS_LIMIT_RAM_RSS:
3690 case ZS_LIMIT_RAM_LOCKED:
3691 case ZS_LIMIT_VM:
3692 case ZS_LIMIT_SHM_MEMORY:
3693 case ZS_LIMIT_LWPS:
3694 case ZS_LIMIT_PROCESSES:
3695 case ZS_LIMIT_SHM_IDS:
3696 case ZS_LIMIT_MSG_IDS:
3697 case ZS_LIMIT_SEM_IDS:
3698 /* FALLTHROUGH */
3699 default:
3700 assert(0);
3701 }
3702 }
3703
3704 /*
3705 * Errno is set on error:
3706 *
3707 * EINVAL: No such property
3708 * ENOENT: No time value for the specified limit.
3709 * ESRCH: No limit is configured.
3710 *
3711 * If no limit is configured, the value will be ZS_PCT_NONE
3712 */
3713 void
zs_zone_limit_used_time(zs_zone_t * z,int limit,timestruc_t * t)3714 zs_zone_limit_used_time(zs_zone_t *z, int limit, timestruc_t *t)
3715 {
3716 switch (limit) {
3717 case ZS_LIMIT_CPU:
3718 if (z->zsz_cpu_cap == ZS_LIMIT_NONE) {
3719 t->tv_sec = 0;
3720 t->tv_nsec = 0;
3721 break;
3722 }
3723 zs_zone_cpu_cap_time_used(z, t);
3724 break;
3725 case ZS_LIMIT_CPU_SHARES:
3726 if (z->zsz_cpu_shares == ZS_LIMIT_NONE ||
3727 z->zsz_cpu_shares == ZS_SHARES_UNLIMITED ||
3728 z->zsz_cpu_shares == 0 ||
3729 (z->zsz_scheds & ZS_SCHED_FSS) == 0) {
3730 t->tv_sec = 0;
3731 t->tv_nsec = 0;
3732 break;
3733 }
3734 zs_zone_cpu_share_time_used(z, t);
3735 break;
3736 case ZS_LIMIT_RAM_RSS:
3737 case ZS_LIMIT_RAM_LOCKED:
3738 case ZS_LIMIT_VM:
3739 case ZS_LIMIT_SHM_MEMORY:
3740 case ZS_LIMIT_LWPS:
3741 case ZS_LIMIT_PROCESSES:
3742 case ZS_LIMIT_SHM_IDS:
3743 case ZS_LIMIT_MSG_IDS:
3744 case ZS_LIMIT_SEM_IDS:
3745 /* FALLTHROUGH */
3746 default:
3747 assert(0);
3748 }
3749 }
3750
3751 /*
3752 * Get a zones usage as a percent of the limit. Return ZS_PCT_NONE if
3753 * no limit is configured.
3754 */
3755 uint_t
zs_zone_limit_used_pct(zs_zone_t * z,int limit)3756 zs_zone_limit_used_pct(zs_zone_t *z, int limit)
3757 {
3758 uint_t v;
3759
3760 switch (limit) {
3761 case ZS_LIMIT_CPU:
3762 v = zs_zone_cpu_cap_pct(z);
3763 break;
3764 case ZS_LIMIT_CPU_SHARES:
3765 v = zs_zone_cpu_shares_pct(z);
3766 break;
3767 case ZS_LIMIT_RAM_RSS:
3768 v = zs_zone_physical_memory_cap_pct(z);
3769 break;
3770 case ZS_LIMIT_RAM_LOCKED:
3771 v = zs_zone_locked_memory_cap_pct(z);
3772 break;
3773 case ZS_LIMIT_VM:
3774 v = zs_zone_virtual_memory_cap_pct(z);
3775 break;
3776 case ZS_LIMIT_LWPS:
3777 v = zs_lwps_zone_cap_pct(z);
3778 break;
3779 case ZS_LIMIT_PROCESSES:
3780 v = zs_processes_zone_cap_pct(z);
3781 break;
3782 case ZS_LIMIT_SHM_MEMORY:
3783 v = zs_shm_zone_cap_pct(z);
3784 break;
3785 case ZS_LIMIT_SHM_IDS:
3786 v = zs_shmids_zone_cap_pct(z);
3787 break;
3788 case ZS_LIMIT_SEM_IDS:
3789 v = zs_semids_zone_cap_pct(z);
3790 break;
3791 case ZS_LIMIT_MSG_IDS:
3792 v = zs_msgids_zone_cap_pct(z);
3793 break;
3794 case ZS_LIMIT_LOFI:
3795 v = zs_lofi_zone_cap_pct(z);
3796 break;
3797 default:
3798 assert(0);
3799 }
3800 return (v);
3801 }
3802
3803 int
zs_pset_list(zs_usage_t * usage,zs_pset_t ** psetlist,int num)3804 zs_pset_list(zs_usage_t *usage, zs_pset_t **psetlist, int num)
3805 {
3806 int i = 0;
3807 zs_pset_t *pset, *tmp;
3808
3809 /* copy what fits of the pset list into the buffer */
3810 for (pset = list_head(&usage->zsu_pset_list); pset != NULL;
3811 pset = list_next(&usage->zsu_pset_list, pset)) {
3812
3813 /* put the default pset at the first position */
3814 if (i < num) {
3815 if (pset->zsp_id == ZS_PSET_DEFAULT) {
3816 tmp = psetlist[0];
3817 psetlist[i] = tmp;
3818 psetlist[0] = pset;
3819 } else {
3820 psetlist[i] = pset;
3821 }
3822 }
3823 i++;
3824 }
3825 return (i);
3826 }
3827
3828 zs_pset_t *
zs_pset_first(zs_usage_t * usage)3829 zs_pset_first(zs_usage_t *usage)
3830 {
3831 return (list_head(&usage->zsu_pset_list));
3832 }
3833
3834 zs_pset_t *
zs_pset_next(zs_usage_t * usage,zs_pset_t * pset)3835 zs_pset_next(zs_usage_t *usage, zs_pset_t *pset)
3836 {
3837 return (list_next(&usage->zsu_pset_list, pset));
3838 }
3839
3840 /*
3841 * Get various properties on a pset.
3842 */
3843 void
zs_pset_property(zs_pset_t * pset,int prop,zs_property_t * p)3844 zs_pset_property(zs_pset_t *pset, int prop, zs_property_t *p)
3845 {
3846 switch (prop) {
3847
3848 case ZS_PSET_PROP_NAME:
3849 p->zsp_type = ZS_PROP_TYPE_STRING;
3850 p->zsp_id = prop;
3851 (void) zs_pset_name(pset, p->zsp_v.zsv_string,
3852 sizeof (p->zsp_v.zsv_string));
3853 break;
3854 case ZS_PSET_PROP_ID:
3855 p->zsp_type = ZS_PROP_TYPE_INT;
3856 p->zsp_id = prop;
3857 p->zsp_v.zsv_int = zs_pset_id(pset);
3858 break;
3859 case ZS_PSET_PROP_CPUTYPE:
3860 p->zsp_type = ZS_PROP_TYPE_UINT;
3861 p->zsp_id = prop;
3862 p->zsp_v.zsv_uint = zs_pset_cputype(pset);
3863 break;
3864 case ZS_PSET_PROP_SIZE:
3865 p->zsp_type = ZS_PROP_TYPE_UINT64;
3866 p->zsp_id = prop;
3867 p->zsp_v.zsv_uint64 = zs_pset_size(pset);
3868 break;
3869 case ZS_PSET_PROP_ONLINE:
3870 p->zsp_type = ZS_PROP_TYPE_UINT64;
3871 p->zsp_id = prop;
3872 p->zsp_v.zsv_uint64 = zs_pset_online(pset);
3873 break;
3874 case ZS_PSET_PROP_MIN:
3875 p->zsp_type = ZS_PROP_TYPE_UINT64;
3876 p->zsp_id = prop;
3877 p->zsp_v.zsv_uint64 = zs_pset_min(pset);
3878 break;
3879 case ZS_PSET_PROP_MAX:
3880 p->zsp_type = ZS_PROP_TYPE_UINT64;
3881 p->zsp_id = prop;
3882 p->zsp_v.zsv_uint64 = zs_pset_max(pset);
3883 break;
3884 case ZS_PSET_PROP_CPU_SHARES:
3885 p->zsp_type = ZS_PROP_TYPE_UINT64;
3886 p->zsp_id = prop;
3887 p->zsp_v.zsv_uint64 = zs_pset_cpu_shares(pset);
3888 break;
3889 case ZS_PSET_PROP_SCHEDULERS:
3890 p->zsp_type = ZS_PROP_TYPE_UINT;
3891 p->zsp_id = prop;
3892 p->zsp_v.zsv_uint = zs_pset_schedulers(pset);
3893 break;
3894 /* Not implemented */
3895 case ZS_PSET_PROP_CREATETIME:
3896 case ZS_PSET_PROP_LOAD_1MIN:
3897 case ZS_PSET_PROP_LOAD_5MIN:
3898 case ZS_PSET_PROP_LOAD_15MIN:
3899 /* FALLTHROUGH */
3900 default:
3901 assert(0);
3902 }
3903 }
3904
3905 void
zs_pset_total_time(zs_pset_t * pset,timestruc_t * t)3906 zs_pset_total_time(zs_pset_t *pset, timestruc_t *t)
3907 {
3908 *t = pset->zsp_total_time;
3909 }
3910
3911 uint64_t
zs_pset_total_cpus(zs_pset_t * pset)3912 zs_pset_total_cpus(zs_pset_t *pset)
3913 {
3914 return (pset->zsp_online * ZSD_ONE_CPU);
3915 }
3916
3917 /*
3918 * Get total time used for pset
3919 */
3920 void
zs_pset_used_time(zs_pset_t * pset,int user,timestruc_t * t)3921 zs_pset_used_time(zs_pset_t *pset, int user, timestruc_t *t)
3922 {
3923 switch (user) {
3924 case ZS_USER_ALL:
3925 zs_pset_usage_all(pset, t);
3926 break;
3927 case ZS_USER_KERNEL:
3928 zs_pset_usage_kernel(pset, t);
3929 break;
3930 case ZS_USER_ZONES:
3931 zs_pset_usage_zones(pset, t);
3932 break;
3933 case ZS_USER_FREE:
3934 zs_pset_usage_idle(pset, t);
3935 break;
3936 default:
3937 assert(0);
3938 }
3939 }
3940
3941 /*
3942 * Returns 0 on success. -1 on failure.
3943 *
3944 * ERRORS
3945 * EINVAL: Invalid user.
3946 *
3947 */
3948 uint64_t
zs_pset_used_cpus(zs_pset_t * pset,int user)3949 zs_pset_used_cpus(zs_pset_t *pset, int user)
3950 {
3951 uint_t v;
3952
3953 switch (user) {
3954 case ZS_USER_ALL:
3955 v = zs_pset_usage_all_cpus(pset);
3956 break;
3957 case ZS_USER_KERNEL:
3958 v = zs_pset_usage_kernel_cpus(pset);
3959 break;
3960 case ZS_USER_ZONES:
3961 v = zs_pset_usage_zones_cpus(pset);
3962 break;
3963 case ZS_USER_FREE:
3964 v = zs_pset_usage_idle_cpus(pset);
3965 break;
3966 default:
3967 assert(0);
3968 }
3969 return (v);
3970 }
3971 /*
3972 * Get percent of pset cpu time used
3973 */
3974 uint_t
zs_pset_used_pct(zs_pset_t * pset,int user)3975 zs_pset_used_pct(zs_pset_t *pset, int user)
3976 {
3977 uint_t v;
3978
3979 switch (user) {
3980 case ZS_USER_ALL:
3981 v = zs_pset_usage_all_pct(pset);
3982 break;
3983 case ZS_USER_KERNEL:
3984 v = zs_pset_usage_kernel_pct(pset);
3985 break;
3986 case ZS_USER_ZONES:
3987 v = zs_pset_usage_zones_pct(pset);
3988 break;
3989 case ZS_USER_FREE:
3990 v = zs_pset_usage_idle_pct(pset);
3991 break;
3992 default:
3993 assert(0);
3994 }
3995 return (v);
3996 }
3997
3998 int
zs_pset_zone_list(zs_pset_t * pset,zs_pset_zone_t ** zonelist,int num)3999 zs_pset_zone_list(zs_pset_t *pset, zs_pset_zone_t **zonelist, int num)
4000 {
4001 int i = 0;
4002 zs_pset_zone_t *zone, *tmp;
4003
4004 /* copy what fits of the pset's zone list into the buffer */
4005 for (zone = list_head(&pset->zsp_usage_list); zone != NULL;
4006 zone = list_next(&pset->zsp_usage_list, zone)) {
4007
4008 /* put the global zone at the first position */
4009 if (i < num) {
4010 if (zone->zspz_zone->zsz_id == GLOBAL_ZONEID) {
4011 tmp = zonelist[0];
4012 zonelist[i] = tmp;
4013 zonelist[0] = zone;
4014 } else {
4015 zonelist[i] = zone;
4016 }
4017 }
4018 i++;
4019 }
4020 return (i);
4021 }
4022
4023 zs_pset_zone_t *
zs_pset_zone_first(zs_pset_t * pset)4024 zs_pset_zone_first(zs_pset_t *pset)
4025 {
4026 return (list_head(&pset->zsp_usage_list));
4027 }
4028
4029 zs_pset_zone_t *
zs_pset_zone_next(zs_pset_t * pset,zs_pset_zone_t * pz)4030 zs_pset_zone_next(zs_pset_t *pset, zs_pset_zone_t *pz)
4031 {
4032 return (list_next(&pset->zsp_usage_list, pz));
4033 }
4034
4035 zs_pset_t *
zs_pset_zone_get_pset(zs_pset_zone_t * pz)4036 zs_pset_zone_get_pset(zs_pset_zone_t *pz)
4037 {
4038 return (pz->zspz_pset);
4039 }
4040
4041 zs_zone_t *
zs_pset_zone_get_zone(zs_pset_zone_t * pz)4042 zs_pset_zone_get_zone(zs_pset_zone_t *pz)
4043 {
4044 return (pz->zspz_zone);
4045 }
4046
4047 /*
4048 * Get a property describing a zone's usage of a pset
4049 */
4050 void
zs_pset_zone_property(zs_pset_zone_t * pz,int prop,zs_property_t * p)4051 zs_pset_zone_property(zs_pset_zone_t *pz, int prop, zs_property_t *p)
4052 {
4053 switch (prop) {
4054
4055 case ZS_PZ_PROP_CPU_CAP:
4056 p->zsp_type = ZS_PROP_TYPE_UINT64;
4057 p->zsp_id = prop;
4058 p->zsp_v.zsv_uint64 = (int)zs_pset_zone_cpu_cap(pz);
4059 break;
4060 case ZS_PZ_PROP_CPU_SHARES:
4061 p->zsp_type = ZS_PROP_TYPE_UINT64;
4062 p->zsp_id = prop;
4063 p->zsp_v.zsv_uint64 = (int)zs_pset_zone_cpu_shares(pz);
4064 break;
4065 case ZS_PZ_PROP_SCHEDULERS:
4066 p->zsp_type = ZS_PROP_TYPE_UINT;
4067 p->zsp_id = prop;
4068 p->zsp_v.zsv_uint = (int)zs_pset_zone_schedulers(pz);
4069 break;
4070 default:
4071 assert(0);
4072 }
4073 }
4074
4075 void
zs_pset_zone_used_time(zs_pset_zone_t * pz,timestruc_t * t)4076 zs_pset_zone_used_time(zs_pset_zone_t *pz, timestruc_t *t)
4077 {
4078 zs_pset_zone_usage_time(pz, t);
4079 }
4080
4081 uint64_t
zs_pset_zone_used_cpus(zs_pset_zone_t * pz)4082 zs_pset_zone_used_cpus(zs_pset_zone_t *pz)
4083 {
4084 return (zs_pset_zone_usage_cpus(pz));
4085 }
4086
4087 /*
4088 * Get percent of a psets cpus used by a zone
4089 */
4090 uint_t
zs_pset_zone_used_pct(zs_pset_zone_t * pz,int type)4091 zs_pset_zone_used_pct(zs_pset_zone_t *pz, int type)
4092 {
4093 uint_t v;
4094
4095 switch (type) {
4096 case ZS_PZ_PCT_PSET:
4097 v = zs_pset_zone_usage_pct_pset(pz);
4098 break;
4099 case ZS_PZ_PCT_CPU_CAP:
4100 v = zs_pset_zone_usage_pct_cpu_cap(pz);
4101 break;
4102 case ZS_PZ_PCT_PSET_SHARES:
4103 v = zs_pset_zone_usage_pct_pset_shares(pz);
4104 break;
4105 case ZS_PZ_PCT_CPU_SHARES:
4106 v = zs_pset_zone_usage_pct_cpu_shares(pz);
4107 break;
4108 default:
4109 assert(0);
4110 }
4111 return (v);
4112 }
4113
4114 /*
4115 * returns similar to malloc
4116 */
4117 zs_property_t *
zs_property_alloc()4118 zs_property_alloc()
4119 {
4120 return ((zs_property_t *)malloc(sizeof (zs_property_t)));
4121 }
4122
4123 size_t
zs_property_size()4124 zs_property_size()
4125 {
4126 return (sizeof (zs_property_t));
4127 }
4128
4129 void
zs_property_free(zs_property_t * p)4130 zs_property_free(zs_property_t *p)
4131 {
4132 free(p);
4133 }
4134
4135 int
zs_property_type(zs_property_t * p)4136 zs_property_type(zs_property_t *p)
4137 {
4138 return (p->zsp_type);
4139 }
4140
4141 int
zs_property_id(zs_property_t * p)4142 zs_property_id(zs_property_t *p)
4143 {
4144 return (p->zsp_id);
4145 }
4146
4147 char *
zs_property_string(zs_property_t * p)4148 zs_property_string(zs_property_t *p)
4149 {
4150 assert(p->zsp_type == ZS_PROP_TYPE_STRING);
4151 return (p->zsp_v.zsv_string);
4152 }
4153
4154 double
zs_property_double(zs_property_t * p)4155 zs_property_double(zs_property_t *p)
4156 {
4157 assert(p->zsp_type == ZS_PROP_TYPE_DOUBLE);
4158 return (p->zsp_v.zsv_double);
4159 }
4160
4161 void
zs_property_time(zs_property_t * p,timestruc_t * t)4162 zs_property_time(zs_property_t *p, timestruc_t *t)
4163 {
4164 assert(p->zsp_type == ZS_PROP_TYPE_TIME);
4165 *t = p->zsp_v.zsv_ts;
4166 }
4167
4168 uint64_t
zs_property_uint64(zs_property_t * p)4169 zs_property_uint64(zs_property_t *p)
4170 {
4171 assert(p->zsp_type == ZS_PROP_TYPE_UINT64);
4172 return (p->zsp_v.zsv_uint64);
4173 }
4174
4175 int64_t
zs_property_int64(zs_property_t * p)4176 zs_property_int64(zs_property_t *p)
4177 {
4178 assert(p->zsp_type == ZS_PROP_TYPE_INT64);
4179 return (p->zsp_v.zsv_int64);
4180 }
4181
4182 uint_t
zs_property_uint(zs_property_t * p)4183 zs_property_uint(zs_property_t *p)
4184 {
4185 assert(p->zsp_type == ZS_PROP_TYPE_UINT);
4186 return (p->zsp_v.zsv_uint);
4187 }
4188
4189 int
zs_property_int(zs_property_t * p)4190 zs_property_int(zs_property_t *p)
4191 {
4192 assert(p->zsp_type == ZS_PROP_TYPE_INT);
4193 return (p->zsp_v.zsv_uint);
4194 }
4195