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 */
86static int
87zs_connect_zonestatd()
88{
89	int fd;
90
91	fd = open(ZS_DOOR_PATH, O_RDONLY);
92	return (fd);
93}
94
95static zs_zone_t *
96zs_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
108static zs_zone_t *
109zs_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
121static zs_usage_t *
122zs_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
147static void
148zs_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
223static int
224zs_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
348static void
349zs_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
360static int
361zs_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
523static void
524zs_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
550static int
551zs_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		}
650usages:
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
688static int
689zs_zone_name(zs_zone_t *zone, char *name, size_t len)
690{
691	return (strlcpy(name, zone->zsz_name, len));
692}
693
694static zoneid_t
695zs_zone_id(zs_zone_t *zone)
696{
697	return (zone->zsz_id);
698}
699
700static uint_t
701zs_zone_iptype(zs_zone_t *zone)
702{
703	return (zone->zsz_iptype);
704}
705
706static uint_t
707zs_zone_cputype(zs_zone_t *zone)
708{
709	return (zone->zsz_cputype);
710}
711
712static int
713zs_zone_poolname(zs_zone_t *zone, char *name, size_t len)
714{
715	return (strlcpy(name, zone->zsz_pool, len));
716}
717
718static int
719zs_zone_psetname(zs_zone_t *zone, char *name, size_t len)
720{
721	return (strlcpy(name, zone->zsz_pset, len));
722}
723
724static uint_t
725zs_zone_schedulers(zs_zone_t *zone)
726{
727	return (zone->zsz_scheds);
728}
729
730static uint64_t
731zs_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 */
756static uint_t
757zs_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 */
766static uint64_t
767zs_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
773static uint64_t
774zs_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
783static uint64_t
784zs_zone_cpu_cap(zs_zone_t *zone)
785{
786	return (zone->zsz_cpu_cap);
787}
788
789static uint64_t
790zs_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
799static uint64_t
800zs_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
815static void
816zs_zone_cpu_cap_time(zs_zone_t *zone, timestruc_t *ts)
817{
818	*ts = zone->zsz_cap_time;
819}
820
821static void
822zs_zone_cpu_share_time(zs_zone_t *zone, timestruc_t *ts)
823{
824	*ts = zone->zsz_share_time;
825}
826
827static void
828zs_zone_cpu_cap_time_used(zs_zone_t *zone, timestruc_t *ts)
829{
830	*ts = zone->zsz_cpu_usage;
831}
832
833static void
834zs_zone_cpu_share_time_used(zs_zone_t *zone, timestruc_t *ts)
835{
836	*ts = zone->zsz_cpu_usage;
837}
838
839
840static uint64_t
841zs_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 */
864static uint_t
865zs_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
871static uint_t
872zs_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
881static uint_t
882zs_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
897static uint64_t
898zs_zone_physical_memory_cap(zs_zone_t *zone)
899{
900	return (zone->zsz_ram_cap);
901}
902
903static uint64_t
904zs_zone_virtual_memory_cap(zs_zone_t *zone)
905{
906	return (zone->zsz_vm_cap);
907}
908
909static uint64_t
910zs_zone_locked_memory_cap(zs_zone_t *zone)
911{
912	return (zone->zsz_locked_cap);
913}
914
915static uint64_t
916zs_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
924static uint64_t
925zs_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
933static uint64_t
934zs_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
942static int
943zs_pset_name(zs_pset_t *pset, char *name, size_t len)
944{
945	return (strlcpy(name, pset->zsp_name, len));
946}
947
948static psetid_t
949zs_pset_id(zs_pset_t *pset)
950{
951	return (pset->zsp_id);
952}
953
954static uint64_t
955zs_pset_size(zs_pset_t *pset)
956{
957	return (pset->zsp_size);
958}
959
960static uint64_t
961zs_pset_online(zs_pset_t *pset)
962{
963	return (pset->zsp_online);
964}
965
966uint64_t
967zs_pset_min(zs_pset_t *pset)
968{
969	return (pset->zsp_min);
970}
971
972uint64_t
973zs_pset_max(zs_pset_t *pset)
974{
975	return (pset->zsp_max);
976}
977
978static uint_t
979zs_pset_schedulers(zs_pset_t *pset)
980{
981	return (pset->zsp_scheds);
982}
983
984static uint_t
985zs_pset_zone_schedulers(zs_pset_zone_t *pz)
986{
987	return (pz->zspz_scheds);
988}
989
990static uint64_t
991zs_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
999static uint64_t
1000zs_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
1008static uint_t
1009zs_pset_cputype(zs_pset_t *pset)
1010{
1011	return (pset->zsp_cputype);
1012}
1013
1014static void
1015zs_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
1024static void
1025zs_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
1036static void
1037zs_pset_usage_kernel(zs_pset_t *pset, timestruc_t *ts)
1038{
1039	*ts = pset->zsp_usage_kern;
1040}
1041
1042static void
1043zs_pset_usage_zones(zs_pset_t *pset, timestruc_t *ts)
1044{
1045	*ts = pset->zsp_usage_zones;
1046}
1047
1048static uint_t
1049zs_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
1059static uint_t
1060zs_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
1071static uint_t
1072zs_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
1078static uint_t
1079zs_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
1085static uint_t
1086zs_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
1096static uint_t
1097zs_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
1109static uint_t
1110zs_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
1116static uint64_t
1117zs_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
1123static void
1124zs_pset_zone_usage_time(zs_pset_zone_t *pz, timestruc_t *t)
1125{
1126	*t = pz->zspz_cpu_usage;
1127}
1128
1129static uint_t
1130zs_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
1136static uint_t
1137zs_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
1143static uint64_t
1144zs_pset_zone_cpu_cap(zs_pset_zone_t *pz)
1145{
1146	return (pz->zspz_zone->zsz_cpu_cap);
1147}
1148
1149static uint_t
1150zs_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 */
1164static uint_t
1165zs_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 */
1193static uint_t
1194zs_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
1231static void
1232zs_cpu_total_time(zs_usage_t *usage, timestruc_t *ts)
1233{
1234	*ts = usage->zsu_system->zss_cpu_total_time;
1235}
1236
1237static void
1238zs_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
1249static void
1250zs_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
1263static uint_t
1264zs_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
1276static uint_t
1277zs_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
1289static void
1290zs_cpu_usage_kernel(zs_usage_t *usage, timestruc_t *ts)
1291{
1292	*ts = usage->zsu_system->zss_cpu_usage_kern;
1293}
1294
1295static uint_t
1296zs_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
1302static void
1303zs_cpu_usage_zones(zs_usage_t *usage, timestruc_t *ts)
1304{
1305	*ts = usage->zsu_system->zss_cpu_usage_zones;
1306}
1307
1308
1309static uint_t
1310zs_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
1317static void
1318zs_cpu_usage_zone(zs_zone_t *zone, timestruc_t *ts)
1319{
1320	*ts = zone->zsz_cpu_usage;
1321}
1322
1323static uint64_t
1324zs_cpu_total_cpu(zs_usage_t *usage)
1325{
1326	return (usage->zsu_system->zss_ncpus_online * ZSD_ONE_CPU);
1327}
1328
1329static uint64_t
1330zs_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
1341static uint64_t
1342zs_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
1354static uint64_t
1355zs_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
1362static uint64_t
1363zs_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
1370static uint64_t
1371zs_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
1377static uint_t
1378zs_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
1384static uint64_t
1385zs_physical_memory_total(zs_usage_t *usage)
1386{
1387	return (usage->zsu_system->zss_ram_total);
1388}
1389
1390
1391static uint64_t
1392zs_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
1398static uint_t
1399zs_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
1407static uint64_t
1408zs_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
1415static uint_t
1416zs_physical_memory_usage_free_pct(zs_usage_t *usage)
1417{
1418	return (ZSD_PCT_INT - zs_physical_memory_usage_all_pct(usage));
1419}
1420
1421static uint64_t
1422zs_physical_memory_usage_kernel(zs_usage_t *usage)
1423{
1424	return (usage->zsu_system->zss_ram_kern);
1425}
1426
1427static uint_t
1428zs_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
1436static uint64_t
1437zs_physical_memory_usage_zones(zs_usage_t *usage)
1438{
1439	return (usage->zsu_system->zss_ram_zones);
1440}
1441
1442static uint_t
1443zs_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
1451static uint64_t
1452zs_physical_memory_usage_zone(zs_zone_t *zone)
1453{
1454	return (zone->zsz_usage_ram);
1455}
1456
1457static uint_t
1458zs_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
1466static uint_t
1467zs_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}
1480static uint64_t
1481zs_virtual_memory_total(zs_usage_t *usage)
1482{
1483	return (usage->zsu_system->zss_vm_total);
1484}
1485
1486static uint64_t
1487zs_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}
1492static uint64_t
1493zs_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}
1499static uint_t
1500zs_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
1509static uint_t
1510zs_virtual_memory_usage_free_pct(zs_usage_t *usage)
1511{
1512	return (ZSD_PCT_INT - zs_virtual_memory_usage_all_pct(usage));
1513
1514}
1515static uint64_t
1516zs_virtual_memory_usage_kernel(zs_usage_t *usage)
1517{
1518	return (usage->zsu_system->zss_vm_kern);
1519}
1520
1521static uint_t
1522zs_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
1530static uint64_t
1531zs_virtual_memory_usage_zones(zs_usage_t *usage)
1532{
1533	return (usage->zsu_system->zss_vm_zones);
1534}
1535
1536static uint_t
1537zs_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
1545static uint64_t
1546zs_virtual_memory_usage_zone(zs_zone_t *zone)
1547{
1548	return (zone->zsz_usage_vm);
1549}
1550
1551static uint_t
1552zs_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
1561static uint_t
1562zs_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
1574static uint64_t
1575zs_locked_memory_total(zs_usage_t *usage)
1576{
1577	return (usage->zsu_system->zss_ram_total);
1578}
1579
1580static uint64_t
1581zs_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}
1586static uint64_t
1587zs_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
1594static uint_t
1595zs_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
1603static uint_t
1604zs_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
1610static uint64_t
1611zs_locked_memory_usage_kernel(zs_usage_t *usage)
1612{
1613	return (usage->zsu_system->zss_locked_kern);
1614}
1615
1616static uint_t
1617zs_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
1625static uint64_t
1626zs_locked_memory_usage_zones(zs_usage_t *usage)
1627{
1628	return (usage->zsu_system->zss_locked_zones);
1629}
1630
1631static uint_t
1632zs_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
1640static uint64_t
1641zs_locked_memory_usage_zone(zs_zone_t *zone)
1642{
1643	return (zone->zsz_usage_locked);
1644}
1645
1646static uint_t
1647zs_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
1655static uint_t
1656zs_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}
1668static uint64_t
1669zs_disk_swap_total(zs_usage_t *usage)
1670{
1671	return (usage->zsu_system->zss_swap_total);
1672}
1673
1674static uint64_t
1675zs_disk_swap_usage_all(zs_usage_t *usage)
1676{
1677	return (usage->zsu_system->zss_swap_used);
1678}
1679
1680static uint_t
1681zs_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
1687static uint64_t
1688zs_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
1694static uint_t
1695zs_disk_swap_usage_free_pct(zs_usage_t *usage)
1696{
1697	return (ZSD_PCT_INT - zs_disk_swap_usage_all_pct(usage));
1698}
1699
1700static uint64_t
1701zs_processes_total(zs_usage_t *usage)
1702{
1703	return (usage->zsu_system->zss_processes_max);
1704}
1705
1706static uint64_t
1707zs_lwps_total(zs_usage_t *usage)
1708{
1709	return (usage->zsu_system->zss_lwps_max);
1710}
1711
1712static uint64_t
1713zs_shm_total(zs_usage_t *usage)
1714{
1715	return (usage->zsu_system->zss_shm_max);
1716}
1717
1718static uint64_t
1719zs_shmids_total(zs_usage_t *usage)
1720{
1721	return (usage->zsu_system->zss_shmids_max);
1722}
1723
1724static uint64_t
1725zs_semids_total(zs_usage_t *usage)
1726{
1727	return (usage->zsu_system->zss_semids_max);
1728}
1729
1730static uint64_t
1731zs_msgids_total(zs_usage_t *usage)
1732{
1733	return (usage->zsu_system->zss_msgids_max);
1734}
1735
1736static uint64_t
1737zs_lofi_total(zs_usage_t *usage)
1738{
1739	return (usage->zsu_system->zss_lofi_max);
1740}
1741
1742static uint64_t
1743zs_processes_usage_all(zs_usage_t *usage)
1744{
1745	return (usage->zsu_system->zss_processes);
1746}
1747
1748static uint64_t
1749zs_lwps_usage_all(zs_usage_t *usage)
1750{
1751	return (usage->zsu_system->zss_lwps);
1752}
1753
1754static uint64_t
1755zs_shm_usage_all(zs_usage_t *usage)
1756{
1757	return (usage->zsu_system->zss_shm);
1758}
1759
1760static uint64_t
1761zs_shmids_usage_all(zs_usage_t *usage)
1762{
1763	return (usage->zsu_system->zss_shmids);
1764}
1765
1766static uint64_t
1767zs_semids_usage_all(zs_usage_t *usage)
1768{
1769	return (usage->zsu_system->zss_semids);
1770}
1771
1772static uint64_t
1773zs_msgids_usage_all(zs_usage_t *usage)
1774{
1775	return (usage->zsu_system->zss_msgids);
1776}
1777
1778static uint64_t
1779zs_lofi_usage_all(zs_usage_t *usage)
1780{
1781	return (usage->zsu_system->zss_lofi);
1782}
1783static uint64_t
1784zs_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
1792static uint_t
1793zs_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
1801static uint_t
1802zs_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
1810static uint_t
1811zs_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
1819static uint64_t
1820zs_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
1828static uint64_t
1829zs_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
1837static uint64_t
1838zs_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
1846static uint64_t
1847zs_processes_usage_zone(zs_zone_t *zone)
1848{
1849	return (zone->zsz_processes);
1850}
1851
1852static uint64_t
1853zs_lwps_usage_zone(zs_zone_t *zone)
1854{
1855	return (zone->zsz_lwps);
1856}
1857
1858static uint64_t
1859zs_shm_usage_zone(zs_zone_t *zone)
1860{
1861	return (zone->zsz_shm);
1862}
1863
1864static uint64_t
1865zs_shmids_usage_zone(zs_zone_t *zone)
1866{
1867	return (zone->zsz_shmids);
1868}
1869
1870static uint64_t
1871zs_semids_usage_zone(zs_zone_t *zone)
1872{
1873	return (zone->zsz_semids);
1874}
1875
1876static uint64_t
1877zs_msgids_usage_zone(zs_zone_t *zone)
1878{
1879	return (zone->zsz_msgids);
1880}
1881
1882static uint64_t
1883zs_lofi_usage_zone(zs_zone_t *zone)
1884{
1885	return (zone->zsz_lofi);
1886}
1887
1888static uint_t
1889zs_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
1897static uint_t
1898zs_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
1906static uint_t
1907zs_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
1915static uint_t
1916zs_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
1924static uint_t
1925zs_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
1933static uint_t
1934zs_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
1942static uint_t
1943zs_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
1951static uint_t
1952zs_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
1964static uint_t
1965zs_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
1976static uint_t
1977zs_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
1988static uint_t
1989zs_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
2001static uint_t
2002zs_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
2014static uint_t
2015zs_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
2027static uint_t
2028zs_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
2042void
2043zs_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 */
2056static zs_usage_t *
2057zs_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
2162zs_usage_t *
2163zs_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 */
2179zs_ctl_t *
2180zs_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 */
2274zs_usage_t *
2275zs_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);
2456err:
2457	if (alloced)
2458		zs_usage_free(ures);
2459	return (NULL);
2460}
2461
2462void
2463zs_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
2495zs_usage_set_t *
2496zs_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
2513err:
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
2524void
2525zs_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
2533int
2534zs_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
2552int
2553zs_usage_set_count(zs_usage_set_t *set)
2554{
2555	return (set->zsus_count);
2556}
2557
2558zs_usage_t *
2559zs_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 */
2694void
2695zs_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 */
2734int
2735zs_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 */
2764uint64_t
2765zs_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 */
2815uint64_t
2816zs_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 */
3031uint_t
3032zs_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 */
3246uint64_t
3247zs_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 */
3297uint_t
3298zs_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 */
3348void
3349zs_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 */
3374void
3375zs_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 */
3415void
3416zs_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
3439int
3440zs_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
3464zs_zone_t *
3465zs_zone_first(zs_usage_t *usage)
3466{
3467	return (list_head(&usage->zsu_zone_list));
3468}
3469
3470zs_zone_t *
3471zs_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 */
3480void
3481zs_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
3537int
3538zs_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 */
3563uint64_t
3564zs_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 */
3615uint64_t
3616zs_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 */
3666void
3667zs_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 */
3713void
3714zs_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 */
3755uint_t
3756zs_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
3803int
3804zs_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
3828zs_pset_t *
3829zs_pset_first(zs_usage_t *usage)
3830{
3831	return (list_head(&usage->zsu_pset_list));
3832}
3833
3834zs_pset_t *
3835zs_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 */
3843void
3844zs_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
3905void
3906zs_pset_total_time(zs_pset_t *pset, timestruc_t *t)
3907{
3908	*t = pset->zsp_total_time;
3909}
3910
3911uint64_t
3912zs_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 */
3920void
3921zs_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 */
3948uint64_t
3949zs_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 */
3974uint_t
3975zs_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
3998int
3999zs_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
4023zs_pset_zone_t *
4024zs_pset_zone_first(zs_pset_t *pset)
4025{
4026	return (list_head(&pset->zsp_usage_list));
4027}
4028
4029zs_pset_zone_t *
4030zs_pset_zone_next(zs_pset_t *pset, zs_pset_zone_t *pz)
4031{
4032	return (list_next(&pset->zsp_usage_list, pz));
4033}
4034
4035zs_pset_t *
4036zs_pset_zone_get_pset(zs_pset_zone_t *pz)
4037{
4038	return (pz->zspz_pset);
4039}
4040
4041zs_zone_t *
4042zs_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 */
4050void
4051zs_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
4075void
4076zs_pset_zone_used_time(zs_pset_zone_t *pz, timestruc_t *t)
4077{
4078	zs_pset_zone_usage_time(pz, t);
4079}
4080
4081uint64_t
4082zs_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 */
4090uint_t
4091zs_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 */
4117zs_property_t *
4118zs_property_alloc()
4119{
4120	return ((zs_property_t *)malloc(sizeof (zs_property_t)));
4121}
4122
4123size_t
4124zs_property_size()
4125{
4126	return (sizeof (zs_property_t));
4127}
4128
4129void
4130zs_property_free(zs_property_t *p)
4131{
4132	free(p);
4133}
4134
4135int
4136zs_property_type(zs_property_t *p)
4137{
4138	return (p->zsp_type);
4139}
4140
4141int
4142zs_property_id(zs_property_t *p)
4143{
4144	return (p->zsp_id);
4145}
4146
4147char *
4148zs_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
4154double
4155zs_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
4161void
4162zs_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
4168uint64_t
4169zs_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
4175int64_t
4176zs_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
4182uint_t
4183zs_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
4189int
4190zs_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