xref: /illumos-gate/usr/src/lib/libzonestat/common/libzonestat.c (revision 09a48d4ca0ddda4ad26cc885769745870d989baf)
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
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 *
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 *
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 *
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
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
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
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
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
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
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
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
695 zs_zone_id(zs_zone_t *zone)
696 {
697 	return (zone->zsz_id);
698 }
699 
700 static uint_t
701 zs_zone_iptype(zs_zone_t *zone)
702 {
703 	return (zone->zsz_iptype);
704 }
705 
706 static uint_t
707 zs_zone_cputype(zs_zone_t *zone)
708 {
709 	return (zone->zsz_cputype);
710 }
711 
712 static int
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
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
725 zs_zone_schedulers(zs_zone_t *zone)
726 {
727 	return (zone->zsz_scheds);
728 }
729 
730 static uint64_t
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
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
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
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
784 zs_zone_cpu_cap(zs_zone_t *zone)
785 {
786 	return (zone->zsz_cpu_cap);
787 }
788 
789 static uint64_t
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
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
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
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
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
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
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
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
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
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
898 zs_zone_physical_memory_cap(zs_zone_t *zone)
899 {
900 	return (zone->zsz_ram_cap);
901 }
902 
903 static uint64_t
904 zs_zone_virtual_memory_cap(zs_zone_t *zone)
905 {
906 	return (zone->zsz_vm_cap);
907 }
908 
909 static uint64_t
910 zs_zone_locked_memory_cap(zs_zone_t *zone)
911 {
912 	return (zone->zsz_locked_cap);
913 }
914 
915 static uint64_t
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
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
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
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
949 zs_pset_id(zs_pset_t *pset)
950 {
951 	return (pset->zsp_id);
952 }
953 
954 static uint64_t
955 zs_pset_size(zs_pset_t *pset)
956 {
957 	return (pset->zsp_size);
958 }
959 
960 static uint64_t
961 zs_pset_online(zs_pset_t *pset)
962 {
963 	return (pset->zsp_online);
964 }
965 
966 uint64_t
967 zs_pset_min(zs_pset_t *pset)
968 {
969 	return (pset->zsp_min);
970 }
971 
972 uint64_t
973 zs_pset_max(zs_pset_t *pset)
974 {
975 	return (pset->zsp_max);
976 }
977 
978 static uint_t
979 zs_pset_schedulers(zs_pset_t *pset)
980 {
981 	return (pset->zsp_scheds);
982 }
983 
984 static uint_t
985 zs_pset_zone_schedulers(zs_pset_zone_t *pz)
986 {
987 	return (pz->zspz_scheds);
988 }
989 
990 static uint64_t
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
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
1009 zs_pset_cputype(zs_pset_t *pset)
1010 {
1011 	return (pset->zsp_cputype);
1012 }
1013 
1014 static void
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
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
1037 zs_pset_usage_kernel(zs_pset_t *pset, timestruc_t *ts)
1038 {
1039 	*ts = pset->zsp_usage_kern;
1040 }
1041 
1042 static void
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1452 zs_physical_memory_usage_zone(zs_zone_t *zone)
1453 {
1454 	return (zone->zsz_usage_ram);
1455 }
1456 
1457 static uint_t
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
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
1481 zs_virtual_memory_total(zs_usage_t *usage)
1482 {
1483 	return (usage->zsu_system->zss_vm_total);
1484 }
1485 
1486 static uint64_t
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
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
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
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
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
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
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
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
1546 zs_virtual_memory_usage_zone(zs_zone_t *zone)
1547 {
1548 	return (zone->zsz_usage_vm);
1549 }
1550 
1551 static uint_t
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
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
1575 zs_locked_memory_total(zs_usage_t *usage)
1576 {
1577 	return (usage->zsu_system->zss_ram_total);
1578 }
1579 
1580 static uint64_t
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
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
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
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
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
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
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
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
1641 zs_locked_memory_usage_zone(zs_zone_t *zone)
1642 {
1643 	return (zone->zsz_usage_locked);
1644 }
1645 
1646 static uint_t
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
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
1669 zs_disk_swap_total(zs_usage_t *usage)
1670 {
1671 	return (usage->zsu_system->zss_swap_total);
1672 }
1673 
1674 static uint64_t
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
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
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
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
1701 zs_processes_total(zs_usage_t *usage)
1702 {
1703 	return (usage->zsu_system->zss_processes_max);
1704 }
1705 
1706 static uint64_t
1707 zs_lwps_total(zs_usage_t *usage)
1708 {
1709 	return (usage->zsu_system->zss_lwps_max);
1710 }
1711 
1712 static uint64_t
1713 zs_shm_total(zs_usage_t *usage)
1714 {
1715 	return (usage->zsu_system->zss_shm_max);
1716 }
1717 
1718 static uint64_t
1719 zs_shmids_total(zs_usage_t *usage)
1720 {
1721 	return (usage->zsu_system->zss_shmids_max);
1722 }
1723 
1724 static uint64_t
1725 zs_semids_total(zs_usage_t *usage)
1726 {
1727 	return (usage->zsu_system->zss_semids_max);
1728 }
1729 
1730 static uint64_t
1731 zs_msgids_total(zs_usage_t *usage)
1732 {
1733 	return (usage->zsu_system->zss_msgids_max);
1734 }
1735 
1736 static uint64_t
1737 zs_lofi_total(zs_usage_t *usage)
1738 {
1739 	return (usage->zsu_system->zss_lofi_max);
1740 }
1741 
1742 static uint64_t
1743 zs_processes_usage_all(zs_usage_t *usage)
1744 {
1745 	return (usage->zsu_system->zss_processes);
1746 }
1747 
1748 static uint64_t
1749 zs_lwps_usage_all(zs_usage_t *usage)
1750 {
1751 	return (usage->zsu_system->zss_lwps);
1752 }
1753 
1754 static uint64_t
1755 zs_shm_usage_all(zs_usage_t *usage)
1756 {
1757 	return (usage->zsu_system->zss_shm);
1758 }
1759 
1760 static uint64_t
1761 zs_shmids_usage_all(zs_usage_t *usage)
1762 {
1763 	return (usage->zsu_system->zss_shmids);
1764 }
1765 
1766 static uint64_t
1767 zs_semids_usage_all(zs_usage_t *usage)
1768 {
1769 	return (usage->zsu_system->zss_semids);
1770 }
1771 
1772 static uint64_t
1773 zs_msgids_usage_all(zs_usage_t *usage)
1774 {
1775 	return (usage->zsu_system->zss_msgids);
1776 }
1777 
1778 static uint64_t
1779 zs_lofi_usage_all(zs_usage_t *usage)
1780 {
1781 	return (usage->zsu_system->zss_lofi);
1782 }
1783 static uint64_t
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
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
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
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
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
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
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
1847 zs_processes_usage_zone(zs_zone_t *zone)
1848 {
1849 	return (zone->zsz_processes);
1850 }
1851 
1852 static uint64_t
1853 zs_lwps_usage_zone(zs_zone_t *zone)
1854 {
1855 	return (zone->zsz_lwps);
1856 }
1857 
1858 static uint64_t
1859 zs_shm_usage_zone(zs_zone_t *zone)
1860 {
1861 	return (zone->zsz_shm);
1862 }
1863 
1864 static uint64_t
1865 zs_shmids_usage_zone(zs_zone_t *zone)
1866 {
1867 	return (zone->zsz_shmids);
1868 }
1869 
1870 static uint64_t
1871 zs_semids_usage_zone(zs_zone_t *zone)
1872 {
1873 	return (zone->zsz_semids);
1874 }
1875 
1876 static uint64_t
1877 zs_msgids_usage_zone(zs_zone_t *zone)
1878 {
1879 	return (zone->zsz_msgids);
1880 }
1881 
1882 static uint64_t
1883 zs_lofi_usage_zone(zs_zone_t *zone)
1884 {
1885 	return (zone->zsz_lofi);
1886 }
1887 
1888 static uint_t
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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, &params) != 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 *
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 *
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, &params) != 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 *
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
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 *
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
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
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
2553 zs_usage_set_count(zs_usage_set_t *set)
2554 {
2555 	return (set->zsus_count);
2556 }
2557 
2558 zs_usage_t *
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
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
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
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
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
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
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
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
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
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
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
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 *
3465 zs_zone_first(zs_usage_t *usage)
3466 {
3467 	return (list_head(&usage->zsu_zone_list));
3468 }
3469 
3470 zs_zone_t *
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
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
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
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
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
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
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
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
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 *
3829 zs_pset_first(zs_usage_t *usage)
3830 {
3831 	return (list_head(&usage->zsu_pset_list));
3832 }
3833 
3834 zs_pset_t *
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
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
3906 zs_pset_total_time(zs_pset_t *pset, timestruc_t *t)
3907 {
3908 	*t = pset->zsp_total_time;
3909 }
3910 
3911 uint64_t
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
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
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
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
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 *
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 *
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 *
4036 zs_pset_zone_get_pset(zs_pset_zone_t *pz)
4037 {
4038 	return (pz->zspz_pset);
4039 }
4040 
4041 zs_zone_t *
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
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
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
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
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 *
4118 zs_property_alloc()
4119 {
4120 	return ((zs_property_t *)malloc(sizeof (zs_property_t)));
4121 }
4122 
4123 size_t
4124 zs_property_size()
4125 {
4126 	return (sizeof (zs_property_t));
4127 }
4128 
4129 void
4130 zs_property_free(zs_property_t *p)
4131 {
4132 	free(p);
4133 }
4134 
4135 int
4136 zs_property_type(zs_property_t *p)
4137 {
4138 	return (p->zsp_type);
4139 }
4140 
4141 int
4142 zs_property_id(zs_property_t *p)
4143 {
4144 	return (p->zsp_id);
4145 }
4146 
4147 char *
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
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
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
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
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
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
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