/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ZSD_PCT_INT 10000 #define ZSD_PCT_DOUBLE 10000.0 #define ZSD_ONE_CPU 100 #ifndef MIN #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif #ifndef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif #define ZS_MAXTS(a, b) ((b).tv_sec > (a).tv_sec || \ ((b).tv_sec == (a).tv_sec && (b).tv_nsec > (a).tv_nsec) ? (b) : (a)) /* Compute max, treating ZS_LIMIT_NONE as zero */ #define ZS_MAXOF(a, b) { \ if ((b) != ZS_LIMIT_NONE) { \ if ((a) == ZS_LIMIT_NONE) \ (a) = (b); \ else if ((b) > (a)) \ (b) = (a); \ } \ } /* Add two caps together, treating ZS_LIMIT_NONE as zero */ #define ZS_ADD_CAP(a, b) { \ if ((b) != ZS_LIMIT_NONE) { \ if ((a) == ZS_LIMIT_NONE) \ (a) = (b); \ else \ (a) += (b); \ } \ } #define ZS_MAXOFTS(a, b) { \ if ((b).tv_sec > (a).tv_sec) (a) = (b); \ else if ((b).tv_nsec > (a).tv_nsec) (a) = (b); } /* * Functions for reading and manipulating resource usage. */ static int zs_connect_zonestatd() { int fd; fd = open(ZS_DOOR_PATH, O_RDONLY); return (fd); } static zs_zone_t * zs_lookup_zone_byid(zs_usage_t *u, zoneid_t zid) { zs_zone_t *zone; for (zone = list_head(&u->zsu_zone_list); zone != NULL; zone = list_next(&u->zsu_zone_list, zone)) { if (zone->zsz_id == zid) return (zone); } return (NULL); } static zs_zone_t * zs_lookup_zone_byname(zs_usage_t *u, char *name) { zs_zone_t *zone; for (zone = list_head(&u->zsu_zone_list); zone != NULL; zone = list_next(&u->zsu_zone_list, zone)) { if (strcmp(zone->zsz_name, name) == 0) return (zone); } return (NULL); } static zs_usage_t * zs_usage_alloc() { zs_usage_t *u; zs_system_t *s; u = (zs_usage_t *)calloc(sizeof (zs_usage_t), 1); if (u == NULL) return (NULL); s = (zs_system_t *)calloc(sizeof (zs_system_t), 1); if (s == NULL) { free(u); return (NULL); } u->zsu_mmap = B_FALSE; u->zsu_system = s; list_create(&u->zsu_zone_list, sizeof (zs_zone_t), offsetof(zs_zone_t, zsz_next)); list_create(&u->zsu_pset_list, sizeof (zs_pset_t), offsetof(zs_pset_t, zsp_next)); return (u); } static void zs_zone_add_usage(zs_zone_t *old, zs_zone_t *new, int func) { if (func == ZS_COMPUTE_USAGE_HIGH) { /* Compute max of caps */ ZS_MAXOF(old->zsz_cpu_cap, new->zsz_cpu_cap); ZS_MAXOF(old->zsz_cpu_shares, new->zsz_cpu_shares); ZS_MAXOF(old->zsz_ram_cap, new->zsz_ram_cap); ZS_MAXOF(old->zsz_locked_cap, new->zsz_locked_cap); ZS_MAXOF(old->zsz_vm_cap, new->zsz_vm_cap); ZS_MAXOF(old->zsz_processes_cap, new->zsz_processes_cap); ZS_MAXOF(old->zsz_lwps_cap, new->zsz_lwps_cap); ZS_MAXOF(old->zsz_shm_cap, new->zsz_shm_cap); ZS_MAXOF(old->zsz_shmids_cap, new->zsz_shmids_cap); ZS_MAXOF(old->zsz_semids_cap, new->zsz_semids_cap); ZS_MAXOF(old->zsz_msgids_cap, new->zsz_msgids_cap); ZS_MAXOF(old->zsz_lofi_cap, new->zsz_lofi_cap); /* Compute max memory and limit usages */ ZS_MAXOF(old->zsz_usage_ram, new->zsz_usage_ram); ZS_MAXOF(old->zsz_usage_locked, new->zsz_usage_locked); ZS_MAXOF(old->zsz_usage_ram, new->zsz_usage_ram); ZS_MAXOF(old->zsz_processes, new->zsz_processes); ZS_MAXOF(old->zsz_lwps, new->zsz_lwps); ZS_MAXOF(old->zsz_shm, new->zsz_shm); ZS_MAXOF(old->zsz_shmids, new->zsz_shmids); ZS_MAXOF(old->zsz_semids, new->zsz_semids); ZS_MAXOF(old->zsz_msgids, new->zsz_msgids); ZS_MAXOF(old->zsz_lofi, new->zsz_lofi); ZS_MAXOF(old->zsz_cpus_online, new->zsz_cpus_online); ZS_MAXOFTS(old->zsz_cpu_usage, new->zsz_cpu_usage); ZS_MAXOFTS(old->zsz_pset_time, new->zsz_pset_time); ZS_MAXOFTS(old->zsz_cap_time, new->zsz_cap_time); ZS_MAXOFTS(old->zsz_share_time, new->zsz_share_time); return; } ZS_ADD_CAP(old->zsz_cpu_cap, new->zsz_cpu_cap); ZS_ADD_CAP(old->zsz_ram_cap, new->zsz_ram_cap); ZS_ADD_CAP(old->zsz_locked_cap, new->zsz_locked_cap); ZS_ADD_CAP(old->zsz_vm_cap, new->zsz_vm_cap); ZS_ADD_CAP(old->zsz_processes_cap, new->zsz_processes_cap); ZS_ADD_CAP(old->zsz_lwps_cap, new->zsz_lwps_cap); ZS_ADD_CAP(old->zsz_shm_cap, new->zsz_shm_cap); ZS_ADD_CAP(old->zsz_shmids_cap, new->zsz_shmids_cap); ZS_ADD_CAP(old->zsz_semids_cap, new->zsz_semids_cap); ZS_ADD_CAP(old->zsz_msgids_cap, new->zsz_msgids_cap); ZS_ADD_CAP(old->zsz_lofi_cap, new->zsz_lofi_cap); /* Add in memory and limit usages */ old->zsz_usage_ram += new->zsz_usage_ram; old->zsz_usage_locked += new->zsz_usage_locked; old->zsz_usage_vm += new->zsz_usage_vm; old->zsz_processes += new->zsz_processes; old->zsz_lwps += new->zsz_lwps; old->zsz_shm += new->zsz_shm; old->zsz_shmids += new->zsz_shmids; old->zsz_semids += new->zsz_semids; old->zsz_msgids += new->zsz_msgids; old->zsz_lofi += new->zsz_lofi; old->zsz_cpus_online += new->zsz_cpus_online; old->zsz_cpu_shares += new->zsz_cpu_shares; TIMESTRUC_ADD_TIMESTRUC(old->zsz_cpu_usage, new->zsz_cpu_usage); TIMESTRUC_ADD_TIMESTRUC(old->zsz_pset_time, new->zsz_pset_time); TIMESTRUC_ADD_TIMESTRUC(old->zsz_cap_time, new->zsz_cap_time); TIMESTRUC_ADD_TIMESTRUC(old->zsz_share_time, new->zsz_share_time); } static int zs_usage_compute_zones(zs_usage_t *ures, zs_usage_t *uold, zs_usage_t *unew, int func) { zs_system_t *sres; zs_zone_t *zold, *znew, *zres; sres = ures->zsu_system; /* * Walk zones, assume lists are always sorted the same. Include * all zones that exist in the new usage. */ zold = list_head(&uold->zsu_zone_list); znew = list_head(&unew->zsu_zone_list); while (zold != NULL && znew != NULL) { int cmp; cmp = strcmp(zold->zsz_name, znew->zsz_name); if (cmp > 0) { /* * Old interval does not contain zone in new * interval. Zone is new. Add zone to result. */ if (ures != unew) { zres = (zs_zone_t *)calloc(sizeof (zs_zone_t), 1); if (zres == NULL) return (-1); *zres = *znew; zres->zsz_system = sres; list_link_init(&zres->zsz_next); zres->zsz_intervals = 0; if (ures == uold) list_insert_before(&uold->zsu_zone_list, zold, zres); else list_insert_tail(&ures->zsu_zone_list, zres); } else { zres = znew; } if (func == ZS_COMPUTE_USAGE_AVERAGE) zres->zsz_intervals++; znew = list_next(&unew->zsu_zone_list, znew); continue; } else if (cmp < 0) { /* * Start interval contains zones that is not in the * end interval. This zone is gone. Leave zone in * old usage, but do not add it to result usage */ zold = list_next(&uold->zsu_zone_list, zold); continue; } /* Zone is in both start and end interval. Compute interval */ if (ures == uold) { zres = zold; } else if (ures == unew) { zres = znew; } else { /* add zone to new usage */ zres = (zs_zone_t *)calloc(sizeof (zs_zone_t), 1); if (zres == NULL) return (-1); *zres = *znew; zres->zsz_system = sres; list_insert_tail(&ures->zsu_zone_list, zres); } if (func == ZS_COMPUTE_USAGE_AVERAGE) zres->zsz_intervals++; if (func == ZS_COMPUTE_USAGE_INTERVAL) { /* * If zone is in the old interval, but has been * rebooted, don't subtract its old interval usage */ if (zres->zsz_hrstart > uold->zsu_hrtime) { znew = list_next(&unew->zsu_zone_list, znew); zold = list_next(&uold->zsu_zone_list, zold); continue; } TIMESTRUC_DELTA(zres->zsz_cpu_usage, znew->zsz_cpu_usage, zold->zsz_cpu_usage); TIMESTRUC_DELTA(zres->zsz_cap_time, znew->zsz_cap_time, zold->zsz_cap_time); TIMESTRUC_DELTA(zres->zsz_share_time, znew->zsz_share_time, zold->zsz_share_time); TIMESTRUC_DELTA(zres->zsz_pset_time, znew->zsz_pset_time, zold->zsz_pset_time); } else { zs_zone_add_usage(zres, znew, func); } znew = list_next(&unew->zsu_zone_list, znew); zold = list_next(&uold->zsu_zone_list, zold); } if (ures == unew) return (0); /* Add in any remaining zones in the new interval */ while (znew != NULL) { zres = (zs_zone_t *)calloc(sizeof (zs_zone_t), 1); if (zres == NULL) return (-1); *zres = *znew; zres->zsz_system = sres; if (func == ZS_COMPUTE_USAGE_AVERAGE) zres->zsz_intervals++; if (ures == uold) list_insert_tail(&uold->zsu_zone_list, zres); else list_insert_tail(&ures->zsu_zone_list, zres); znew = list_next(&unew->zsu_zone_list, znew); } return (0); } static void zs_pset_zone_add_usage(zs_pset_zone_t *old, zs_pset_zone_t *new, int func) { if (func == ZS_COMPUTE_USAGE_HIGH) { ZS_MAXOF(old->zspz_cpu_shares, new->zspz_cpu_shares); ZS_MAXOFTS(old->zspz_cpu_usage, new->zspz_cpu_usage); return; } old->zspz_cpu_shares += new->zspz_cpu_shares; TIMESTRUC_ADD_TIMESTRUC(old->zspz_cpu_usage, new->zspz_cpu_usage); } static int zs_usage_compute_pset_usage(zs_usage_t *uold, zs_usage_t *ures, zs_pset_t *pres, zs_pset_t *pold, zs_pset_t *pnew, int func) { zs_pset_zone_t *puold, *punew, *pures; /* * Walk psets usages, assume lists are always sorted the same. Include * all pset usages that exist in the new pset. */ if (pold == NULL) puold = NULL; else puold = list_head(&pold->zsp_usage_list); punew = list_head(&pnew->zsp_usage_list); while (puold != NULL && punew != NULL) { int cmp; cmp = strcmp(puold->zspz_zone->zsz_name, punew->zspz_zone->zsz_name); if (cmp > 0) { /* * Old interval does not contain usage new * interval. Usage is new. */ if (pres != pnew) { pures = (zs_pset_zone_t *)malloc( sizeof (zs_pset_zone_t)); if (pures == NULL) return (-1); *pures = *punew; pures->zspz_pset = pres; pures->zspz_zone = zs_lookup_zone_byname(ures, punew->zspz_zone->zsz_name); assert(pures->zspz_zone != NULL); pures->zspz_intervals = 0; if (pres == pold) list_insert_before( &pold->zsp_usage_list, puold, pures); else list_insert_tail(&pres->zsp_usage_list, pures); } else { pures = punew; } if (func == ZS_COMPUTE_USAGE_AVERAGE) pures->zspz_intervals++; else if (func == ZS_COMPUTE_USAGE_TOTAL) { /* Add pset's time so far to the zone usage */ TIMESTRUC_ADD_TIMESTRUC( pures->zspz_zone->zsz_pset_time, pres->zsp_total_time); pures->zspz_zone->zsz_cpus_online += pres->zsp_online; } punew = list_next(&pnew->zsp_usage_list, punew); continue; } else if (cmp < 0) { /* * Old interval contains pset_zone that is not in the * new interval. This zone is no longer using the * pset. Leave pset_zone in old interval, but do not * add it to result usage. * * For total utilization, add pset time to zone that * has run in this pset before. */ if (func == ZS_COMPUTE_USAGE_TOTAL) { /* Add new pset time to the zone usage */ TIMESTRUC_ADD_TIMESTRUC( puold->zspz_zone->zsz_pset_time, pnew->zsp_total_time); puold->zspz_zone->zsz_cpus_online += pnew->zsp_online; } puold = list_next(&pold->zsp_usage_list, puold); continue; } /* * Zone is using pset in both start and end interval. Compute * interval */ if (pres == pold) { pures = puold; } else if (pres == pnew) { pures = punew; } else { pures = (zs_pset_zone_t *)malloc( sizeof (zs_pset_zone_t)); if (pures == NULL) return (-1); *pures = *punew; pures->zspz_pset = pres; pures->zspz_zone = zs_lookup_zone_byname(ures, punew->zspz_zone->zsz_name); assert(pures->zspz_zone != NULL); list_insert_tail(&pres->zsp_usage_list, pures); } if (func == ZS_COMPUTE_USAGE_AVERAGE) pures->zspz_intervals++; if (func == ZS_COMPUTE_USAGE_INTERVAL) { /* * If pset usage has been destroyed and re-created * since start interval, don't subtract the start * interval. */ if (punew->zspz_hrstart > uold->zsu_hrtime) { punew = list_next(&pnew->zsp_usage_list, punew); puold = list_next(&pold->zsp_usage_list, puold); continue; } TIMESTRUC_DELTA(pures->zspz_cpu_usage, punew->zspz_cpu_usage, puold->zspz_cpu_usage); } else { zs_pset_zone_add_usage(pures, punew, func); } punew = list_next(&pnew->zsp_usage_list, punew); puold = list_next(&pold->zsp_usage_list, puold); } if (func == ZS_COMPUTE_USAGE_TOTAL) { while (puold != NULL) { TIMESTRUC_ADD_TIMESTRUC( puold->zspz_zone->zsz_pset_time, pnew->zsp_total_time); puold->zspz_zone->zsz_cpus_online += pnew->zsp_online; puold = list_next(&pold->zsp_usage_list, puold); } } /* No need to add new pset zone usages if result pset is new pset */ if (pres == pnew) return (0); /* Add in any remaining new psets in the new interval */ while (punew != NULL) { pures = (zs_pset_zone_t *)calloc(sizeof (zs_pset_zone_t), 1); if (pures == NULL) return (-1); *pures = *punew; pures->zspz_pset = pres; pures->zspz_zone = zs_lookup_zone_byname(ures, punew->zspz_zone->zsz_name); assert(pures->zspz_zone != NULL); if (func == ZS_COMPUTE_USAGE_AVERAGE) pures->zspz_intervals++; if (pres == pold) list_insert_tail(&pold->zsp_usage_list, pures); else list_insert_tail(&pres->zsp_usage_list, pures); punew = list_next(&pnew->zsp_usage_list, punew); } return (0); } static void zs_pset_add_usage(zs_pset_t *old, zs_pset_t *new, int func) { if (func == ZS_COMPUTE_USAGE_HIGH) { ZS_MAXOF(old->zsp_online, new->zsp_online); ZS_MAXOF(old->zsp_size, new->zsp_size); ZS_MAXOF(old->zsp_min, new->zsp_min); ZS_MAXOF(old->zsp_max, new->zsp_max); ZS_MAXOF(old->zsp_importance, new->zsp_importance); ZS_MAXOF(old->zsp_cpu_shares, new->zsp_cpu_shares); ZS_MAXOFTS(old->zsp_total_time, new->zsp_total_time); ZS_MAXOFTS(old->zsp_usage_kern, new->zsp_usage_kern); ZS_MAXOFTS(old->zsp_usage_zones, new->zsp_usage_zones); return; } old->zsp_online += new->zsp_online; old->zsp_size += new->zsp_size; old->zsp_min += new->zsp_min; old->zsp_max += new->zsp_max; old->zsp_importance += new->zsp_importance; old->zsp_cpu_shares += new->zsp_cpu_shares; TIMESTRUC_ADD_TIMESTRUC(old->zsp_total_time, new->zsp_total_time); TIMESTRUC_ADD_TIMESTRUC(old->zsp_usage_kern, new->zsp_usage_kern); TIMESTRUC_ADD_TIMESTRUC(old->zsp_usage_zones, new->zsp_usage_zones); } static int zs_usage_compute_psets(zs_usage_t *ures, zs_usage_t *uold, zs_usage_t *unew, int func) { zs_pset_t *pold, *pnew, *pres; /* * Walk psets, assume lists are always sorted the same. Include * all psets that exist at the end of the interval. */ pold = list_head(&uold->zsu_pset_list); pnew = list_head(&unew->zsu_pset_list); while (pold != NULL && pnew != NULL) { int cmp; cmp = strcmp(pold->zsp_name, pnew->zsp_name); if (cmp > 0) { /* * Old interval does not contain pset in new * interval. Pset is new. */ if (ures != unew) { pres = (zs_pset_t *)malloc(sizeof (zs_pset_t)); if (pres == NULL) return (-1); *pres = *pnew; pres->zsp_intervals = 0; list_create(&pres->zsp_usage_list, sizeof (zs_pset_zone_t), offsetof(zs_pset_zone_t, zspz_next)); if (ures == uold) list_insert_before(&uold->zsu_pset_list, pold, pres); else list_insert_tail(&ures->zsu_pset_list, pres); } else { pres = pnew; } if (zs_usage_compute_pset_usage(uold, ures, pres, NULL, pnew, func) != 0) return (-1); if (func == ZS_COMPUTE_USAGE_AVERAGE || func == ZS_COMPUTE_USAGE_TOTAL) pres->zsp_intervals++; pnew = list_next(&unew->zsu_pset_list, pnew); continue; } else if (cmp < 0) { /* * Start interval contains psets that is not in the * end interval. This pset is gone. Leave pset in * old usage, but do not add it to result usage. */ pold = list_next(&uold->zsu_pset_list, pold); continue; } /* Pset is in both start and end interval. Compute interval */ if (ures == uold) { pres = pold; } else if (ures == unew) { pres = pnew; } else { pres = (zs_pset_t *)calloc(sizeof (zs_pset_t), 1); if (pres == NULL) return (-1); *pres = *pnew; list_create(&pres->zsp_usage_list, sizeof (zs_pset_zone_t), offsetof(zs_pset_zone_t, zspz_next)); list_insert_tail(&ures->zsu_pset_list, pres); } if (func == ZS_COMPUTE_USAGE_AVERAGE || func == ZS_COMPUTE_USAGE_TOTAL) pres->zsp_intervals++; if (func == ZS_COMPUTE_USAGE_INTERVAL) { /* * If pset as been destroyed and re-created since start * interval, don't subtract the start interval. */ if (pnew->zsp_hrstart > uold->zsu_hrtime) { goto usages; } TIMESTRUC_DELTA(pres->zsp_total_time, pnew->zsp_total_time, pold->zsp_total_time); TIMESTRUC_DELTA(pres->zsp_usage_kern, pnew->zsp_usage_kern, pold->zsp_usage_kern); TIMESTRUC_DELTA(pres->zsp_usage_zones, pnew->zsp_usage_zones, pold->zsp_usage_zones); } else { zs_pset_add_usage(pres, pnew, func); } usages: if (zs_usage_compute_pset_usage(uold, ures, pres, pold, pnew, func) != 0) return (-1); pnew = list_next(&unew->zsu_pset_list, pnew); pold = list_next(&uold->zsu_pset_list, pold); } if (ures == unew) return (0); /* Add in any remaining psets in the new interval */ while (pnew != NULL) { pres = (zs_pset_t *)calloc(sizeof (zs_pset_t), 1); if (pres == NULL) return (-1); *pres = *pnew; list_create(&pres->zsp_usage_list, sizeof (zs_pset_zone_t), offsetof(zs_pset_zone_t, zspz_next)); if (func == ZS_COMPUTE_USAGE_AVERAGE || func == ZS_COMPUTE_USAGE_TOTAL) pres->zsp_intervals++; if (ures == uold) list_insert_tail(&uold->zsu_pset_list, pres); else list_insert_tail(&ures->zsu_pset_list, pres); if (zs_usage_compute_pset_usage(uold, ures, pres, NULL, pnew, func) != 0) return (-1); pnew = list_next(&unew->zsu_pset_list, pnew); } return (0); } static int zs_zone_name(zs_zone_t *zone, char *name, size_t len) { return (strlcpy(name, zone->zsz_name, len)); } static zoneid_t zs_zone_id(zs_zone_t *zone) { return (zone->zsz_id); } static uint_t zs_zone_iptype(zs_zone_t *zone) { return (zone->zsz_iptype); } static uint_t zs_zone_cputype(zs_zone_t *zone) { return (zone->zsz_cputype); } static int zs_zone_poolname(zs_zone_t *zone, char *name, size_t len) { return (strlcpy(name, zone->zsz_pool, len)); } static int zs_zone_psetname(zs_zone_t *zone, char *name, size_t len) { return (strlcpy(name, zone->zsz_pset, len)); } static uint_t zs_zone_schedulers(zs_zone_t *zone) { return (zone->zsz_scheds); } static uint64_t zs_ts_used_scale(timestruc_t *total, timestruc_t *used, uint64_t scale, boolean_t cap_at_100) { double dtotal, dused, pct, dscale; /* If no time yet, treat as zero */ if (total->tv_sec == 0 && total->tv_nsec == 0) return (0); dtotal = (double)total->tv_sec + ((double)total->tv_nsec / (double)NANOSEC); dused = (double)used->tv_sec + ((double)used->tv_nsec / (double)NANOSEC); dscale = (double)scale; pct = dused / dtotal * dscale; if (cap_at_100 && pct > dscale) pct = dscale; return ((uint_t)pct); } /* * Convert total and used time into percent used. */ static uint_t zs_ts_used_pct(timestruc_t *total, timestruc_t *used, boolean_t cap_at_100) { return ((uint_t)zs_ts_used_scale(total, used, ZSD_PCT_INT, cap_at_100)); } /* * Convert total and used time, plus number of cpus, into number of cpus * used, where 100 equals 1 cpu used. */ static uint64_t zs_ts_used_cpus(timestruc_t *total, timestruc_t *used, uint_t ncpus, boolean_t cap_at_100) { return (zs_ts_used_scale(total, used, ncpus * ZSD_ONE_CPU, cap_at_100)); } static uint64_t zs_zone_cpu_shares(zs_zone_t *zone) { /* No processes found in FSS */ if ((zone->zsz_scheds & ZS_SCHED_FSS) == 0) return (ZS_LIMIT_NONE); return (zone->zsz_cpu_shares); } static uint64_t zs_zone_cpu_cap(zs_zone_t *zone) { return (zone->zsz_cpu_cap); } static uint64_t zs_zone_cpu_cap_used(zs_zone_t *zone) { if (zone->zsz_cpu_cap == ZS_LIMIT_NONE) return (ZS_LIMIT_NONE); return (zs_ts_used_cpus(&zone->zsz_cap_time, &zone->zsz_cpu_usage, zone->zsz_cpus_online, B_TRUE)); } static uint64_t zs_zone_cpu_shares_used(zs_zone_t *zone) { if (zone->zsz_cpu_shares == ZS_LIMIT_NONE) return (ZS_LIMIT_NONE); if (zone->zsz_cpu_shares == ZS_SHARES_UNLIMITED) return (ZS_LIMIT_NONE); if ((zone->zsz_scheds & ZS_SCHED_FSS) == 0) return (ZS_LIMIT_NONE); return (zs_ts_used_scale(&zone->zsz_share_time, &zone->zsz_cpu_usage, zone->zsz_cpu_shares, B_FALSE)); } static void zs_zone_cpu_cap_time(zs_zone_t *zone, timestruc_t *ts) { *ts = zone->zsz_cap_time; } static void zs_zone_cpu_share_time(zs_zone_t *zone, timestruc_t *ts) { *ts = zone->zsz_share_time; } static void zs_zone_cpu_cap_time_used(zs_zone_t *zone, timestruc_t *ts) { *ts = zone->zsz_cpu_usage; } static void zs_zone_cpu_share_time_used(zs_zone_t *zone, timestruc_t *ts) { *ts = zone->zsz_cpu_usage; } static uint64_t zs_uint64_used_scale(uint64_t total, uint64_t used, uint64_t scale, boolean_t cap_at_100) { double dtotal, dused, pct, dscale; /* If no time yet, treat as zero */ if (total == 0) return (0); dtotal = (double)total; dused = (double)used; dscale = (double)scale; pct = dused / dtotal * dscale; if (cap_at_100 && pct > dscale) pct = dscale; return ((uint64_t)pct); } /* * Convert a total and used value into a percent used. */ static uint_t zs_uint64_used_pct(uint64_t total, uint64_t used, boolean_t cap_at_100) { return ((uint_t)zs_uint64_used_scale(total, used, ZSD_PCT_INT, cap_at_100)); } static uint_t zs_zone_cpu_cap_pct(zs_zone_t *zone) { if (zone->zsz_cpu_cap == ZS_LIMIT_NONE) return (ZS_PCT_NONE); return (zs_ts_used_pct(&zone->zsz_cap_time, &zone->zsz_cpu_usage, B_TRUE)); } static uint_t zs_zone_cpu_shares_pct(zs_zone_t *zone) { if (zone->zsz_cpu_shares == ZS_LIMIT_NONE) return (ZS_PCT_NONE); if (zone->zsz_cpu_shares == ZS_SHARES_UNLIMITED) return (ZS_PCT_NONE); if ((zone->zsz_scheds & ZS_SCHED_FSS) == 0) return (ZS_PCT_NONE); return (zs_ts_used_pct(&zone->zsz_share_time, &zone->zsz_cpu_usage, B_FALSE)); } static uint64_t zs_zone_physical_memory_cap(zs_zone_t *zone) { return (zone->zsz_ram_cap); } static uint64_t zs_zone_virtual_memory_cap(zs_zone_t *zone) { return (zone->zsz_vm_cap); } static uint64_t zs_zone_locked_memory_cap(zs_zone_t *zone) { return (zone->zsz_locked_cap); } static uint64_t zs_zone_physical_memory_cap_used(zs_zone_t *zone) { if (zone->zsz_ram_cap == ZS_LIMIT_NONE) return (ZS_LIMIT_NONE); return (zone->zsz_usage_ram); } static uint64_t zs_zone_virtual_memory_cap_used(zs_zone_t *zone) { if (zone->zsz_vm_cap == ZS_LIMIT_NONE) return (ZS_LIMIT_NONE); return (zone->zsz_usage_vm); } static uint64_t zs_zone_locked_memory_cap_used(zs_zone_t *zone) { if (zone->zsz_locked_cap == ZS_LIMIT_NONE) return (ZS_LIMIT_NONE); return (zone->zsz_usage_locked); } static int zs_pset_name(zs_pset_t *pset, char *name, size_t len) { return (strlcpy(name, pset->zsp_name, len)); } static psetid_t zs_pset_id(zs_pset_t *pset) { return (pset->zsp_id); } static uint64_t zs_pset_size(zs_pset_t *pset) { return (pset->zsp_size); } static uint64_t zs_pset_online(zs_pset_t *pset) { return (pset->zsp_online); } uint64_t zs_pset_min(zs_pset_t *pset) { return (pset->zsp_min); } uint64_t zs_pset_max(zs_pset_t *pset) { return (pset->zsp_max); } static uint_t zs_pset_schedulers(zs_pset_t *pset) { return (pset->zsp_scheds); } static uint_t zs_pset_zone_schedulers(zs_pset_zone_t *pz) { return (pz->zspz_scheds); } static uint64_t zs_pset_cpu_shares(zs_pset_t *pset) { if (!(pset->zsp_scheds & ZS_SCHED_FSS)) return (ZS_LIMIT_NONE); return (pset->zsp_cpu_shares); } static uint64_t zs_pset_zone_cpu_shares(zs_pset_zone_t *pz) { if (!(pz->zspz_scheds & ZS_SCHED_FSS)) return (ZS_LIMIT_NONE); return (pz->zspz_cpu_shares); } static uint_t zs_pset_cputype(zs_pset_t *pset) { return (pset->zsp_cputype); } static void zs_pset_usage_all(zs_pset_t *pset, timestruc_t *ts) { timestruc_t tot; tot = pset->zsp_usage_kern; TIMESTRUC_ADD_TIMESTRUC(tot, pset->zsp_usage_zones); *ts = tot; } static void zs_pset_usage_idle(zs_pset_t *pset, timestruc_t *ts) { timestruc_t tot, time, idle; tot = pset->zsp_usage_kern; TIMESTRUC_ADD_TIMESTRUC(tot, pset->zsp_usage_zones); time = pset->zsp_total_time; TIMESTRUC_DELTA(idle, time, tot); *ts = idle; } static void zs_pset_usage_kernel(zs_pset_t *pset, timestruc_t *ts) { *ts = pset->zsp_usage_kern; } static void zs_pset_usage_zones(zs_pset_t *pset, timestruc_t *ts) { *ts = pset->zsp_usage_zones; } static uint_t zs_pset_usage_all_pct(zs_pset_t *pset) { timestruc_t tot; tot = pset->zsp_usage_kern; TIMESTRUC_ADD_TIMESTRUC(tot, pset->zsp_usage_zones); return (zs_ts_used_pct(&pset->zsp_total_time, &tot, B_TRUE)); } static uint_t zs_pset_usage_idle_pct(zs_pset_t *pset) { timestruc_t tot, idle; tot = pset->zsp_usage_kern; TIMESTRUC_ADD_TIMESTRUC(tot, pset->zsp_usage_zones); TIMESTRUC_DELTA(idle, pset->zsp_total_time, tot); return (zs_ts_used_pct(&pset->zsp_total_time, &idle, B_TRUE)); } static uint_t zs_pset_usage_kernel_pct(zs_pset_t *pset) { return (zs_ts_used_pct(&pset->zsp_total_time, &pset->zsp_usage_kern, B_TRUE)); } static uint_t zs_pset_usage_zones_pct(zs_pset_t *pset) { return (zs_ts_used_pct(&pset->zsp_total_time, &pset->zsp_usage_zones, B_TRUE)); } static uint_t zs_pset_usage_all_cpus(zs_pset_t *pset) { timestruc_t tot; tot = pset->zsp_usage_kern; TIMESTRUC_ADD_TIMESTRUC(tot, pset->zsp_usage_zones); return (zs_ts_used_cpus(&pset->zsp_total_time, &tot, pset->zsp_online, B_TRUE)); } static uint_t zs_pset_usage_idle_cpus(zs_pset_t *pset) { timestruc_t tot, idle; tot = pset->zsp_usage_kern; TIMESTRUC_ADD_TIMESTRUC(tot, pset->zsp_usage_zones); TIMESTRUC_DELTA(idle, pset->zsp_total_time, tot); return (zs_ts_used_cpus(&pset->zsp_total_time, &tot, pset->zsp_online, B_TRUE)); } static uint_t zs_pset_usage_kernel_cpus(zs_pset_t *pset) { return (zs_ts_used_cpus(&pset->zsp_total_time, &pset->zsp_usage_kern, pset->zsp_online, B_TRUE)); } static uint64_t zs_pset_usage_zones_cpus(zs_pset_t *pset) { return (zs_ts_used_cpus(&pset->zsp_total_time, &pset->zsp_usage_zones, pset->zsp_online, B_TRUE)); } static void zs_pset_zone_usage_time(zs_pset_zone_t *pz, timestruc_t *t) { *t = pz->zspz_cpu_usage; } static uint_t zs_pset_zone_usage_cpus(zs_pset_zone_t *pz) { return (zs_ts_used_cpus(&pz->zspz_pset->zsp_total_time, &pz->zspz_cpu_usage, pz->zspz_pset->zsp_online, B_TRUE)); } static uint_t zs_pset_zone_usage_pct_pset(zs_pset_zone_t *pz) { return (zs_ts_used_pct(&pz->zspz_pset->zsp_total_time, &pz->zspz_cpu_usage, B_TRUE)); } static uint64_t zs_pset_zone_cpu_cap(zs_pset_zone_t *pz) { return (pz->zspz_zone->zsz_cpu_cap); } static uint_t zs_pset_zone_usage_pct_cpu_cap(zs_pset_zone_t *pz) { zs_zone_t *zone = pz->zspz_zone; if (zone->zsz_cpu_cap == ZS_LIMIT_NONE) { return (ZS_PCT_NONE); } return (zs_ts_used_pct(&zone->zsz_cap_time, &pz->zspz_cpu_usage, B_TRUE)); } /* * Return the fraction of total shares for a pset allocated to the zone. */ static uint_t zs_pset_zone_usage_pct_pset_shares(zs_pset_zone_t *pz) { zs_pset_t *pset = pz->zspz_pset; if (!(pz->zspz_scheds & ZS_SCHED_FSS)) return (ZS_PCT_NONE); if (pz->zspz_cpu_shares == ZS_LIMIT_NONE) return (ZS_PCT_NONE); if (pz->zspz_cpu_shares == ZS_SHARES_UNLIMITED) return (ZS_PCT_NONE); if (pz->zspz_pset->zsp_cpu_shares == 0) return (0); if (pz->zspz_cpu_shares == 0) return (0); return (zs_uint64_used_pct(pset->zsp_cpu_shares, pz->zspz_cpu_shares, B_TRUE)); } /* * Of a zones shares, what percent of cpu time is it using. For instance, * if a zone has 50% of shares, and is using 50% of the cpu time, then it is * using 100% of its share. */ static uint_t zs_pset_zone_usage_pct_cpu_shares(zs_pset_zone_t *pz) { timestruc_t tot, time; double sharefactor; double total; double used; double pct; if (!(pz->zspz_scheds & ZS_SCHED_FSS)) return (ZS_PCT_NONE); if (pz->zspz_cpu_shares == ZS_LIMIT_NONE) return (ZS_PCT_NONE); if (pz->zspz_cpu_shares == ZS_SHARES_UNLIMITED) return (ZS_PCT_NONE); if (pz->zspz_cpu_shares == 0) return (ZS_PCT_NONE); sharefactor = (double)zs_pset_zone_usage_pct_pset_shares(pz); /* Common scaling function won't do sharefactor. */ time = pz->zspz_pset->zsp_total_time; tot = pz->zspz_cpu_usage; total = (double)time.tv_sec + ((double)time.tv_nsec / (double)NANOSEC); total = total * (sharefactor / ZSD_PCT_DOUBLE); used = (double)tot.tv_sec + ((double)tot.tv_nsec / (double)NANOSEC); pct = used / total * ZSD_PCT_DOUBLE; /* Allow percent of share used to exceed 100% */ return ((uint_t)pct); } static void zs_cpu_total_time(zs_usage_t *usage, timestruc_t *ts) { *ts = usage->zsu_system->zss_cpu_total_time; } static void zs_cpu_usage_all(zs_usage_t *usage, timestruc_t *ts) { timestruc_t tot; tot.tv_sec = 0; tot.tv_nsec = 0; TIMESTRUC_ADD_TIMESTRUC(tot, usage->zsu_system->zss_cpu_usage_kern); TIMESTRUC_ADD_TIMESTRUC(tot, usage->zsu_system->zss_cpu_usage_zones); *ts = tot; } static void zs_cpu_usage_idle(zs_usage_t *usage, timestruc_t *ts) { timestruc_t tot, time, idle; tot.tv_sec = 0; tot.tv_nsec = 0; tot = usage->zsu_system->zss_cpu_usage_kern; TIMESTRUC_ADD_TIMESTRUC(tot, usage->zsu_system->zss_cpu_usage_zones); time = usage->zsu_system->zss_cpu_total_time; TIMESTRUC_DELTA(idle, time, tot); *ts = idle; } static uint_t zs_cpu_usage_all_pct(zs_usage_t *usage) { timestruc_t tot; tot = usage->zsu_system->zss_cpu_usage_kern; TIMESTRUC_ADD_TIMESTRUC(tot, usage->zsu_system->zss_cpu_usage_zones); return (zs_ts_used_pct(&usage->zsu_system->zss_cpu_total_time, &tot, B_TRUE)); } static uint_t zs_cpu_usage_idle_pct(zs_usage_t *usage) { timestruc_t tot, idle; tot = usage->zsu_system->zss_cpu_usage_kern; TIMESTRUC_ADD_TIMESTRUC(tot, usage->zsu_system->zss_cpu_usage_zones); TIMESTRUC_DELTA(idle, usage->zsu_system->zss_cpu_total_time, tot); return (zs_ts_used_pct(&usage->zsu_system->zss_cpu_total_time, &idle, B_TRUE)); } static void zs_cpu_usage_kernel(zs_usage_t *usage, timestruc_t *ts) { *ts = usage->zsu_system->zss_cpu_usage_kern; } static uint_t zs_cpu_usage_kernel_pct(zs_usage_t *usage) { return (zs_ts_used_pct(&usage->zsu_system->zss_cpu_total_time, &usage->zsu_system->zss_cpu_usage_kern, B_TRUE)); } static void zs_cpu_usage_zones(zs_usage_t *usage, timestruc_t *ts) { *ts = usage->zsu_system->zss_cpu_usage_zones; } static uint_t zs_cpu_usage_zones_pct(zs_usage_t *usage) { return (zs_ts_used_pct(&usage->zsu_system->zss_cpu_total_time, &usage->zsu_system->zss_cpu_usage_zones, B_TRUE)); } static void zs_cpu_usage_zone(zs_zone_t *zone, timestruc_t *ts) { *ts = zone->zsz_cpu_usage; } static uint64_t zs_cpu_total_cpu(zs_usage_t *usage) { return (usage->zsu_system->zss_ncpus_online * ZSD_ONE_CPU); } static uint64_t zs_cpu_usage_all_cpu(zs_usage_t *usage) { timestruc_t tot; tot = usage->zsu_system->zss_cpu_usage_kern; TIMESTRUC_ADD_TIMESTRUC(tot, usage->zsu_system->zss_cpu_usage_zones); return (zs_ts_used_cpus(&usage->zsu_system->zss_cpu_total_time, &tot, usage->zsu_system->zss_ncpus_online, B_TRUE)); } static uint64_t zs_cpu_usage_idle_cpu(zs_usage_t *usage) { timestruc_t tot, idle; tot = usage->zsu_system->zss_cpu_usage_kern; TIMESTRUC_ADD_TIMESTRUC(tot, usage->zsu_system->zss_cpu_usage_zones); TIMESTRUC_DELTA(idle, usage->zsu_system->zss_cpu_total_time, tot); return (zs_ts_used_cpus(&usage->zsu_system->zss_cpu_total_time, &idle, usage->zsu_system->zss_ncpus_online, B_TRUE)); } static uint64_t zs_cpu_usage_kernel_cpu(zs_usage_t *usage) { return (zs_ts_used_cpus(&usage->zsu_system->zss_cpu_total_time, &usage->zsu_system->zss_cpu_usage_kern, usage->zsu_system->zss_ncpus_online, B_TRUE)); } static uint64_t zs_cpu_usage_zones_cpu(zs_usage_t *usage) { return (zs_ts_used_cpus(&usage->zsu_system->zss_cpu_total_time, &usage->zsu_system->zss_cpu_usage_kern, usage->zsu_system->zss_ncpus_online, B_TRUE)); } static uint64_t zs_cpu_usage_zone_cpu(zs_zone_t *zone) { return (zs_ts_used_cpus(&zone->zsz_pset_time, &zone->zsz_cpu_usage, zone->zsz_cpus_online, B_TRUE)); } static uint_t zs_cpu_usage_zone_pct(zs_zone_t *zone) { return (zs_ts_used_pct(&zone->zsz_pset_time, &zone->zsz_cpu_usage, B_TRUE)); } static uint64_t zs_physical_memory_total(zs_usage_t *usage) { return (usage->zsu_system->zss_ram_total); } static uint64_t zs_physical_memory_usage_all(zs_usage_t *usage) { return (usage->zsu_system->zss_ram_kern + usage->zsu_system->zss_ram_zones); } static uint_t zs_physical_memory_usage_all_pct(zs_usage_t *usage) { zs_system_t *system = usage->zsu_system; return (zs_uint64_used_pct(system->zss_ram_total, (system->zss_ram_kern + system->zss_ram_zones), B_TRUE)); } static uint64_t zs_physical_memory_usage_free(zs_usage_t *usage) { return (usage->zsu_system->zss_ram_total - (usage->zsu_system->zss_ram_kern + usage->zsu_system->zss_ram_zones)); } static uint_t zs_physical_memory_usage_free_pct(zs_usage_t *usage) { return (ZSD_PCT_INT - zs_physical_memory_usage_all_pct(usage)); } static uint64_t zs_physical_memory_usage_kernel(zs_usage_t *usage) { return (usage->zsu_system->zss_ram_kern); } static uint_t zs_physical_memory_usage_kernel_pct(zs_usage_t *usage) { zs_system_t *system = usage->zsu_system; return (zs_uint64_used_pct(system->zss_ram_total, system->zss_ram_kern, B_TRUE)); } static uint64_t zs_physical_memory_usage_zones(zs_usage_t *usage) { return (usage->zsu_system->zss_ram_zones); } static uint_t zs_physical_memory_usage_zones_pct(zs_usage_t *usage) { zs_system_t *system = usage->zsu_system; return (zs_uint64_used_pct(system->zss_ram_total, system->zss_ram_zones, B_TRUE)); } static uint64_t zs_physical_memory_usage_zone(zs_zone_t *zone) { return (zone->zsz_usage_ram); } static uint_t zs_physical_memory_usage_zone_pct(zs_zone_t *zone) { zs_system_t *system = zone->zsz_system; return (zs_uint64_used_pct(system->zss_ram_total, zone->zsz_usage_ram, B_TRUE)); } static uint_t zs_zone_physical_memory_cap_pct(zs_zone_t *zone) { if (zone->zsz_ram_cap == ZS_LIMIT_NONE) return (ZS_PCT_NONE); if (zone->zsz_ram_cap == 0) { return (0); } /* Allow ram cap to exeed 100% */ return (zs_uint64_used_pct(zone->zsz_ram_cap, zone->zsz_usage_ram, B_FALSE)); } static uint64_t zs_virtual_memory_total(zs_usage_t *usage) { return (usage->zsu_system->zss_vm_total); } static uint64_t zs_virtual_memory_usage_all(zs_usage_t *usage) { return (usage->zsu_system->zss_vm_kern + usage->zsu_system->zss_vm_zones); } static uint64_t zs_virtual_memory_usage_free(zs_usage_t *usage) { return (usage->zsu_system->zss_vm_total - (usage->zsu_system->zss_vm_kern + usage->zsu_system->zss_vm_zones)); } static uint_t zs_virtual_memory_usage_all_pct(zs_usage_t *usage) { zs_system_t *system = usage->zsu_system; return (zs_uint64_used_pct(system->zss_vm_total, (system->zss_vm_kern + system->zss_vm_zones), B_TRUE)); } static uint_t zs_virtual_memory_usage_free_pct(zs_usage_t *usage) { return (ZSD_PCT_INT - zs_virtual_memory_usage_all_pct(usage)); } static uint64_t zs_virtual_memory_usage_kernel(zs_usage_t *usage) { return (usage->zsu_system->zss_vm_kern); } static uint_t zs_virtual_memory_usage_kernel_pct(zs_usage_t *usage) { zs_system_t *system = usage->zsu_system; return (zs_uint64_used_pct(system->zss_vm_total, system->zss_vm_kern, B_TRUE)); } static uint64_t zs_virtual_memory_usage_zones(zs_usage_t *usage) { return (usage->zsu_system->zss_vm_zones); } static uint_t zs_virtual_memory_usage_zones_pct(zs_usage_t *usage) { zs_system_t *system = usage->zsu_system; return (zs_uint64_used_pct(system->zss_vm_total, system->zss_vm_zones, B_TRUE)); } static uint64_t zs_virtual_memory_usage_zone(zs_zone_t *zone) { return (zone->zsz_usage_vm); } static uint_t zs_virtual_memory_usage_zone_pct(zs_zone_t *zone) { zs_system_t *system = zone->zsz_system; return (zs_uint64_used_pct(system->zss_vm_total, zone->zsz_usage_vm, B_TRUE)); } static uint_t zs_zone_virtual_memory_cap_pct(zs_zone_t *zone) { if (zone->zsz_vm_cap == ZS_LIMIT_NONE) return (ZS_PCT_NONE); if (zone->zsz_vm_cap == 0) return (0); return (zs_uint64_used_pct(zone->zsz_vm_cap, zone->zsz_usage_vm, B_TRUE)); } static uint64_t zs_locked_memory_total(zs_usage_t *usage) { return (usage->zsu_system->zss_ram_total); } static uint64_t zs_locked_memory_usage_all(zs_usage_t *usage) { return (usage->zsu_system->zss_locked_kern + usage->zsu_system->zss_locked_zones); } static uint64_t zs_locked_memory_usage_free(zs_usage_t *usage) { return (usage->zsu_system->zss_ram_total - (usage->zsu_system->zss_locked_kern + usage->zsu_system->zss_locked_zones)); } static uint_t zs_locked_memory_usage_all_pct(zs_usage_t *usage) { zs_system_t *system = usage->zsu_system; return (zs_uint64_used_pct(system->zss_ram_total, (system->zss_locked_kern + system->zss_locked_zones), B_TRUE)); } static uint_t zs_locked_memory_usage_free_pct(zs_usage_t *usage) { return (ZSD_PCT_INT - zs_locked_memory_usage_all_pct(usage)); } static uint64_t zs_locked_memory_usage_kernel(zs_usage_t *usage) { return (usage->zsu_system->zss_locked_kern); } static uint_t zs_locked_memory_usage_kernel_pct(zs_usage_t *usage) { zs_system_t *system = usage->zsu_system; return (zs_uint64_used_pct(system->zss_ram_total, system->zss_locked_kern, B_TRUE)); } static uint64_t zs_locked_memory_usage_zones(zs_usage_t *usage) { return (usage->zsu_system->zss_locked_zones); } static uint_t zs_locked_memory_usage_zones_pct(zs_usage_t *usage) { zs_system_t *system = usage->zsu_system; return (zs_uint64_used_pct(system->zss_ram_total, system->zss_locked_zones, B_TRUE)); } static uint64_t zs_locked_memory_usage_zone(zs_zone_t *zone) { return (zone->zsz_usage_locked); } static uint_t zs_locked_memory_usage_zone_pct(zs_zone_t *zone) { zs_system_t *system = zone->zsz_system; return (zs_uint64_used_pct(system->zss_ram_total, zone->zsz_usage_locked, B_TRUE)); } static uint_t zs_zone_locked_memory_cap_pct(zs_zone_t *zone) { if (zone->zsz_locked_cap == ZS_LIMIT_NONE) return (ZS_PCT_NONE); if (zone->zsz_locked_cap == 0) return (0); return (zs_uint64_used_pct(zone->zsz_locked_cap, zone->zsz_usage_locked, B_TRUE)); } static uint64_t zs_disk_swap_total(zs_usage_t *usage) { return (usage->zsu_system->zss_swap_total); } static uint64_t zs_disk_swap_usage_all(zs_usage_t *usage) { return (usage->zsu_system->zss_swap_used); } static uint_t zs_disk_swap_usage_all_pct(zs_usage_t *usage) { return (zs_uint64_used_pct(usage->zsu_system->zss_swap_total, usage->zsu_system->zss_swap_used, B_TRUE)); } static uint64_t zs_disk_swap_usage_free(zs_usage_t *usage) { return (usage->zsu_system->zss_swap_total - usage->zsu_system->zss_swap_used); } static uint_t zs_disk_swap_usage_free_pct(zs_usage_t *usage) { return (ZSD_PCT_INT - zs_disk_swap_usage_all_pct(usage)); } static uint64_t zs_processes_total(zs_usage_t *usage) { return (usage->zsu_system->zss_processes_max); } static uint64_t zs_lwps_total(zs_usage_t *usage) { return (usage->zsu_system->zss_lwps_max); } static uint64_t zs_shm_total(zs_usage_t *usage) { return (usage->zsu_system->zss_shm_max); } static uint64_t zs_shmids_total(zs_usage_t *usage) { return (usage->zsu_system->zss_shmids_max); } static uint64_t zs_semids_total(zs_usage_t *usage) { return (usage->zsu_system->zss_semids_max); } static uint64_t zs_msgids_total(zs_usage_t *usage) { return (usage->zsu_system->zss_msgids_max); } static uint64_t zs_lofi_total(zs_usage_t *usage) { return (usage->zsu_system->zss_lofi_max); } static uint64_t zs_processes_usage_all(zs_usage_t *usage) { return (usage->zsu_system->zss_processes); } static uint64_t zs_lwps_usage_all(zs_usage_t *usage) { return (usage->zsu_system->zss_lwps); } static uint64_t zs_shm_usage_all(zs_usage_t *usage) { return (usage->zsu_system->zss_shm); } static uint64_t zs_shmids_usage_all(zs_usage_t *usage) { return (usage->zsu_system->zss_shmids); } static uint64_t zs_semids_usage_all(zs_usage_t *usage) { return (usage->zsu_system->zss_semids); } static uint64_t zs_msgids_usage_all(zs_usage_t *usage) { return (usage->zsu_system->zss_msgids); } static uint64_t zs_lofi_usage_all(zs_usage_t *usage) { return (usage->zsu_system->zss_lofi); } static uint64_t zs_processes_usage_all_pct(zs_usage_t *usage) { zs_system_t *system = usage->zsu_system; return (zs_uint64_used_pct(system->zss_processes_max, system->zss_processes, B_TRUE)); } static uint_t zs_lwps_usage_all_pct(zs_usage_t *usage) { zs_system_t *system = usage->zsu_system; return (zs_uint64_used_pct(system->zss_lwps_max, system->zss_lwps, B_TRUE)); } static uint_t zs_shm_usage_all_pct(zs_usage_t *usage) { zs_system_t *system = usage->zsu_system; return (zs_uint64_used_pct(system->zss_shm_max, system->zss_shm, B_TRUE)); } static uint_t zs_shmids_usage_all_pct(zs_usage_t *usage) { zs_system_t *system = usage->zsu_system; return (zs_uint64_used_pct(system->zss_shmids_max, system->zss_shmids, B_TRUE)); } static uint64_t zs_semids_usage_all_pct(zs_usage_t *usage) { zs_system_t *system = usage->zsu_system; return (zs_uint64_used_pct(system->zss_semids_max, system->zss_semids, B_TRUE)); } static uint64_t zs_msgids_usage_all_pct(zs_usage_t *usage) { zs_system_t *system = usage->zsu_system; return (zs_uint64_used_pct(system->zss_msgids_max, system->zss_msgids, B_TRUE)); } static uint64_t zs_lofi_usage_all_pct(zs_usage_t *usage) { zs_system_t *system = usage->zsu_system; return (zs_uint64_used_pct(system->zss_lofi_max, system->zss_lofi, B_TRUE)); } static uint64_t zs_processes_usage_zone(zs_zone_t *zone) { return (zone->zsz_processes); } static uint64_t zs_lwps_usage_zone(zs_zone_t *zone) { return (zone->zsz_lwps); } static uint64_t zs_shm_usage_zone(zs_zone_t *zone) { return (zone->zsz_shm); } static uint64_t zs_shmids_usage_zone(zs_zone_t *zone) { return (zone->zsz_shmids); } static uint64_t zs_semids_usage_zone(zs_zone_t *zone) { return (zone->zsz_semids); } static uint64_t zs_msgids_usage_zone(zs_zone_t *zone) { return (zone->zsz_msgids); } static uint64_t zs_lofi_usage_zone(zs_zone_t *zone) { return (zone->zsz_lofi); } static uint_t zs_processes_usage_zone_pct(zs_zone_t *zone) { zs_system_t *system = zone->zsz_system; return (zs_uint64_used_pct(system->zss_processes_max, zone->zsz_processes, B_TRUE)); } static uint_t zs_lwps_usage_zone_pct(zs_zone_t *zone) { zs_system_t *system = zone->zsz_system; return (zs_uint64_used_pct(system->zss_lwps_max, zone->zsz_lwps, B_TRUE)); } static uint_t zs_shm_usage_zone_pct(zs_zone_t *zone) { zs_system_t *system = zone->zsz_system; return (zs_uint64_used_pct(system->zss_shm_max, zone->zsz_shm, B_TRUE)); } static uint_t zs_shmids_usage_zone_pct(zs_zone_t *zone) { zs_system_t *system = zone->zsz_system; return (zs_uint64_used_pct(system->zss_shmids_max, zone->zsz_shmids, B_TRUE)); } static uint_t zs_semids_usage_zone_pct(zs_zone_t *zone) { zs_system_t *system = zone->zsz_system; return (zs_uint64_used_pct(system->zss_semids_max, zone->zsz_semids, B_TRUE)); } static uint_t zs_msgids_usage_zone_pct(zs_zone_t *zone) { zs_system_t *system = zone->zsz_system; return (zs_uint64_used_pct(system->zss_msgids_max, zone->zsz_msgids, B_TRUE)); } static uint_t zs_lofi_usage_zone_pct(zs_zone_t *zone) { zs_system_t *system = zone->zsz_system; return (zs_uint64_used_pct(system->zss_lofi_max, zone->zsz_lofi, B_TRUE)); } static uint_t zs_processes_zone_cap_pct(zs_zone_t *zone) { if (zone->zsz_processes_cap == ZS_LIMIT_NONE) return (ZS_PCT_NONE); if (zone->zsz_processes_cap == 0) return (0); return (zs_uint64_used_pct(zone->zsz_processes_cap, zone->zsz_processes, B_TRUE)); } static uint_t zs_lwps_zone_cap_pct(zs_zone_t *zone) { if (zone->zsz_lwps_cap == ZS_LIMIT_NONE) return (ZS_PCT_NONE); if (zone->zsz_lwps_cap == 0) return (0); return (zs_uint64_used_pct(zone->zsz_lwps_cap, zone->zsz_lwps, B_TRUE)); } static uint_t zs_shm_zone_cap_pct(zs_zone_t *zone) { if (zone->zsz_shm_cap == ZS_LIMIT_NONE) return (ZS_PCT_NONE); if (zone->zsz_shm_cap == 0) return (0); return (zs_uint64_used_pct(zone->zsz_shm_cap, zone->zsz_shm, B_TRUE)); } static uint_t zs_shmids_zone_cap_pct(zs_zone_t *zone) { if (zone->zsz_shmids_cap == ZS_LIMIT_NONE) return (ZS_PCT_NONE); if (zone->zsz_shmids_cap == 0) return (0); return (zs_uint64_used_pct(zone->zsz_shmids_cap, zone->zsz_shmids, B_TRUE)); } static uint_t zs_semids_zone_cap_pct(zs_zone_t *zone) { if (zone->zsz_semids_cap == ZS_LIMIT_NONE) return (ZS_PCT_NONE); if (zone->zsz_semids_cap == 0) return (0); return (zs_uint64_used_pct(zone->zsz_semids_cap, zone->zsz_semids, B_TRUE)); } static uint_t zs_msgids_zone_cap_pct(zs_zone_t *zone) { if (zone->zsz_msgids_cap == ZS_LIMIT_NONE) return (ZS_PCT_NONE); if (zone->zsz_msgids_cap == 0) return (0); return (zs_uint64_used_pct(zone->zsz_msgids_cap, zone->zsz_msgids, B_TRUE)); } static uint_t zs_lofi_zone_cap_pct(zs_zone_t *zone) { if (zone->zsz_lofi_cap == ZS_LIMIT_NONE) return (ZS_PCT_NONE); if (zone->zsz_lofi_cap == 0) return (0); return (zs_uint64_used_pct(zone->zsz_lofi_cap, zone->zsz_lofi, B_TRUE)); } /* All funcs this line should be static */ void zs_close(zs_ctl_t *ctl) { (void) close(ctl->zsctl_door); zs_usage_free(ctl->zsctl_start); free(ctl); } /* * ERRORS * * EINTR signal received, process forked, or zonestatd exited * ESRCH zonestatd not responding */ static zs_usage_t * zs_usage_read_internal(zs_ctl_t *ctl, int init) { int fd = -1; uint_t i, j; zs_usage_t *usage; zs_zone_t *zone = NULL; zs_pset_t *pset = NULL; zs_pset_zone_t *pz; char *next; uint64_t cmd[2]; door_arg_t params; fd = ctl->zsctl_door; cmd[0] = ZSD_CMD_READ; cmd[1] = ctl->zsctl_gen; params.data_ptr = (char *)cmd; params.data_size = sizeof (cmd); params.desc_ptr = NULL; params.desc_num = 0; params.rbuf = NULL; params.rsize = 0; if (door_call(fd, ¶ms) != 0) { if (errno != EINTR) errno = ESRCH; return (NULL); } if (params.rbuf == NULL) { errno = ESRCH; return (NULL); } /* LINTED */ usage = (zs_usage_t *)params.data_ptr; ctl->zsctl_gen = usage->zsu_gen; usage->zsu_mmap = B_TRUE; usage->zsu_intervals = 0; list_create(&usage->zsu_zone_list, sizeof (zs_zone_t), offsetof(zs_zone_t, zsz_next)); list_create(&usage->zsu_pset_list, sizeof (zs_pset_t), offsetof(zs_pset_t, zsp_next)); /* Fix up next pointers inside usage_t */ next = (char *)usage; next += sizeof (zs_usage_t); /* LINTED */ usage->zsu_system = (zs_system_t *)next; next += sizeof (zs_system_t); for (i = 0; i < usage->zsu_nzones; i++) { /* LINTED */ zone = (zs_zone_t *)next; list_insert_tail(&usage->zsu_zone_list, zone); next += sizeof (zs_zone_t); zone->zsz_system = usage->zsu_system; zone->zsz_intervals = 0; } for (i = 0; i < usage->zsu_npsets; i++) { /* LINTED */ pset = (zs_pset_t *)next; list_insert_tail(&usage->zsu_pset_list, pset); next += sizeof (zs_pset_t); list_create(&pset->zsp_usage_list, sizeof (zs_pset_zone_t), offsetof(zs_pset_zone_t, zspz_next)); for (j = 0; j < pset->zsp_nusage; j++) { /* LINTED */ pz = (zs_pset_zone_t *)next; list_insert_tail(&pset->zsp_usage_list, pz); next += sizeof (zs_pset_zone_t); pz->zspz_pset = pset; pz->zspz_zone = zs_lookup_zone_byid(usage, pz->zspz_zoneid); assert(pz->zspz_zone != NULL); pz->zspz_intervals = 0; } pset->zsp_intervals = 0; } if (init) return (usage); /* * If current usage tracking started after start usage, then * no need to subtract start usage. This really can't happen, * as zonestatd should never start over while this client is * connected. */ if (usage->zsu_hrstart > ctl->zsctl_start->zsu_hrtime) { return (usage); } /* * Compute usage relative to first open. Usage returned by * zonestatd starts at an arbitrary point in the past. * */ (void) zs_usage_compute(usage, ctl->zsctl_start, usage, ZS_COMPUTE_USAGE_INTERVAL); return (usage); } zs_usage_t * zs_usage_read(zs_ctl_t *ctl) { return (zs_usage_read_internal(ctl, B_FALSE)); } /* * Open connection to zonestatd. NULL of failure, with errno set: * * EPERM: Insufficent privilege (no PRIV_PROC_INFO) * ESRCH: Zones monitoring service not available or responding * ENOTSUP: Incompatiable zones monitoring service version. * EINTR: Server exited or client forked. * ENOMEM: as malloc(3c) * EAGAIN: asl malloc(3c) * */ zs_ctl_t * zs_open() { zs_ctl_t *ctl; int cmd[2]; int *res; int fd; door_arg_t params; door_desc_t *door; int errno_save; ctl = calloc(sizeof (zs_ctl_t), 1); if (ctl == NULL) return (NULL); fd = zs_connect_zonestatd(); if (fd < 0) { free(ctl); errno = ESRCH; return (NULL); } cmd[0] = ZSD_CMD_CONNECT; cmd[1] = ZS_VERSION; params.data_ptr = (char *)cmd; params.data_size = sizeof (cmd); params.desc_ptr = NULL; params.desc_num = 0; params.rbuf = NULL; params.rsize = 0; if (door_call(fd, ¶ms) != 0) { errno_save = errno; free(ctl); (void) close(fd); if (errno_save == EINTR) errno = EINTR; else errno = ESRCH; return (NULL); } (void) close(fd); /* LINTED */ res = (int *)params.data_ptr; if (res[1] == ZSD_STATUS_VERSION_MISMATCH) { free(ctl); errno = ENOTSUP; return (NULL); } if (res[1] == ZSD_STATUS_PERMISSION) { free(ctl); errno = EPERM; return (NULL); } if (res[1] != ZSD_STATUS_OK) { free(ctl); errno = ESRCH; return (NULL); } door = params.desc_ptr; if (door == NULL) { free(ctl); return (NULL); } ctl->zsctl_door = door->d_data.d_desc.d_descriptor; if (params.data_ptr != (char *)cmd) (void) munmap(params.data_ptr, params.data_size); /* * Get the initial usage from zonestatd. This creates a * zero-point on which to base future usages returned by * zs_read(). */ ctl->zsctl_start = zs_usage_read_internal(ctl, B_TRUE); if (ctl->zsctl_start == NULL) { errno_save = errno; (void) close(ctl->zsctl_door); free(ctl); if (errno_save == EINTR) errno = EINTR; else errno = ESRCH; return (NULL); } return (ctl); } /* * Return NULL on error. * * ERRORS: * EINVAL: Invalid function. */ zs_usage_t * zs_usage_compute(zs_usage_t *ures, zs_usage_t *uold, zs_usage_t *unew, int func) { zs_system_t *sold, *snew, *sres; boolean_t alloced = B_FALSE; if (func != ZS_COMPUTE_USAGE_INTERVAL && func != ZS_COMPUTE_USAGE_TOTAL && func != ZS_COMPUTE_USAGE_AVERAGE && func != ZS_COMPUTE_USAGE_HIGH) assert(0); if (ures == NULL) { alloced = B_TRUE; ures = zs_usage_alloc(); if (ures == NULL) return (NULL); } sres = ures->zsu_system; sold = uold->zsu_system; snew = unew->zsu_system; switch (func) { case ZS_COMPUTE_USAGE_INTERVAL: /* Use system totals from newer interval */ if (sres != snew) *sres = *snew; TIMESTRUC_DELTA(sres->zss_cpu_total_time, snew->zss_cpu_total_time, sold->zss_cpu_total_time); TIMESTRUC_DELTA(sres->zss_cpu_usage_kern, snew->zss_cpu_usage_kern, sold->zss_cpu_usage_kern); TIMESTRUC_DELTA(sres->zss_cpu_usage_zones, snew->zss_cpu_usage_zones, sold->zss_cpu_usage_zones); break; case ZS_COMPUTE_USAGE_HIGH: /* Find max cpus */ sres->zss_ncpus = MAX(sold->zss_ncpus, snew->zss_ncpus); sres->zss_ncpus_online = MAX(sold->zss_ncpus_online, snew->zss_ncpus_online); /* Find max cpu times */ sres->zss_cpu_total_time = ZS_MAXTS(sold->zss_cpu_total_time, snew->zss_cpu_total_time); sres->zss_cpu_usage_kern = ZS_MAXTS(sold->zss_cpu_usage_kern, snew->zss_cpu_usage_kern); sres->zss_cpu_usage_zones = ZS_MAXTS(sold->zss_cpu_usage_zones, snew->zss_cpu_usage_zones); /* These don't change */ sres->zss_processes_max = snew->zss_processes_max; sres->zss_lwps_max = snew->zss_lwps_max; sres->zss_shm_max = snew->zss_shm_max; sres->zss_shmids_max = snew->zss_shmids_max; sres->zss_semids_max = snew->zss_semids_max; sres->zss_msgids_max = snew->zss_msgids_max; sres->zss_lofi_max = snew->zss_lofi_max; /* * Add in memory values and limits. Scale memory to * avoid overflow. */ sres->zss_ram_total = MAX(sold->zss_ram_total, snew->zss_ram_total); sres->zss_ram_kern = MAX(sold->zss_ram_kern, snew->zss_ram_kern); sres->zss_ram_zones = MAX(sold->zss_ram_zones, snew->zss_ram_zones); sres->zss_locked_kern = MAX(sold->zss_locked_kern, snew->zss_locked_kern); sres->zss_locked_zones = MAX(sold->zss_locked_zones, snew->zss_locked_zones); sres->zss_vm_total = MAX(sold->zss_vm_total, snew->zss_vm_total); sres->zss_vm_kern = MAX(sold->zss_vm_kern, snew->zss_vm_kern); sres->zss_vm_zones = MAX(sold->zss_vm_zones, snew->zss_vm_zones); sres->zss_swap_total = MAX(sold->zss_swap_total, snew->zss_swap_total); sres->zss_swap_used = MAX(sold->zss_swap_used, snew->zss_swap_used); sres->zss_processes = MAX(sold->zss_processes, snew->zss_processes); sres->zss_lwps = MAX(sold->zss_lwps, snew->zss_lwps); sres->zss_shm = MAX(sold->zss_shm, snew->zss_shm); sres->zss_shmids = MAX(sold->zss_shmids, snew->zss_shmids); sres->zss_semids = MAX(sold->zss_semids, snew->zss_semids); sres->zss_msgids = MAX(sold->zss_msgids, snew->zss_msgids); sres->zss_lofi = MAX(sold->zss_msgids, snew->zss_lofi); break; case ZS_COMPUTE_USAGE_TOTAL: /* FALLTHROUGH */ case ZS_COMPUTE_USAGE_AVERAGE: ures->zsu_intervals++; /* * Add cpus. The total report will divide this by the * number of intervals to give the average number of cpus * over all intervals. */ sres->zss_ncpus = sold->zss_ncpus + snew->zss_ncpus; sres->zss_ncpus_online = sold->zss_ncpus_online + snew->zss_ncpus_online; /* Add in cpu times */ sres->zss_cpu_total_time = sold->zss_cpu_total_time; TIMESTRUC_ADD_TIMESTRUC(sres->zss_cpu_total_time, snew->zss_cpu_total_time); sres->zss_cpu_usage_kern = sold->zss_cpu_usage_kern; TIMESTRUC_ADD_TIMESTRUC(sres->zss_cpu_usage_kern, snew->zss_cpu_usage_kern); sres->zss_cpu_usage_zones = sold->zss_cpu_usage_zones; TIMESTRUC_ADD_TIMESTRUC(sres->zss_cpu_usage_zones, snew->zss_cpu_usage_zones); /* These don't change */ sres->zss_processes_max = snew->zss_processes_max; sres->zss_lwps_max = snew->zss_lwps_max; sres->zss_shm_max = snew->zss_shm_max; sres->zss_shmids_max = snew->zss_shmids_max; sres->zss_semids_max = snew->zss_semids_max; sres->zss_msgids_max = snew->zss_msgids_max; sres->zss_lofi_max = snew->zss_lofi_max; /* * Add in memory values and limits. Scale memory to * avoid overflow. */ if (sres != sold) { sres->zss_ram_total = sold->zss_ram_total / 1024; sres->zss_ram_kern = sold->zss_ram_kern / 1024; sres->zss_ram_zones = sold->zss_ram_zones / 1024; sres->zss_locked_kern = sold->zss_locked_kern / 1024; sres->zss_locked_zones = sold->zss_locked_zones / 1024; sres->zss_vm_total = sold->zss_vm_total / 1024; sres->zss_vm_kern = sold->zss_vm_kern / 1024; sres->zss_vm_zones = sold->zss_vm_zones / 1024; sres->zss_swap_total = sold->zss_swap_total / 1024; sres->zss_swap_used = sold->zss_swap_used / 1024; sres->zss_processes = sold->zss_processes; sres->zss_lwps = sold->zss_lwps; sres->zss_shm = sold->zss_shm / 1024; sres->zss_shmids = sold->zss_shmids; sres->zss_semids = sold->zss_semids; sres->zss_msgids = sold->zss_msgids; sres->zss_lofi = sold->zss_lofi; } /* Add in new values. */ sres->zss_ram_total += (snew->zss_ram_total / 1024); sres->zss_ram_kern += (snew->zss_ram_kern / 1024); sres->zss_ram_zones += (snew->zss_ram_zones / 1024); sres->zss_locked_kern += (snew->zss_locked_kern / 1024); sres->zss_locked_zones += (snew->zss_locked_zones / 1024); sres->zss_vm_total += (snew->zss_vm_total / 1024); sres->zss_vm_kern += (snew->zss_vm_kern / 1024); sres->zss_vm_zones += (snew->zss_vm_zones / 1024); sres->zss_swap_total += (snew->zss_swap_total / 1024); sres->zss_swap_used += (snew->zss_swap_used / 1024); sres->zss_processes += snew->zss_processes; sres->zss_lwps += snew->zss_lwps; sres->zss_shm += (snew->zss_shm / 1024); sres->zss_shmids += snew->zss_shmids; sres->zss_semids += snew->zss_semids; sres->zss_msgids += snew->zss_msgids; sres->zss_lofi += snew->zss_lofi; break; default: if (alloced) zs_usage_free(ures); assert(0); } if (zs_usage_compute_zones(ures, uold, unew, func) != 0) goto err; if (zs_usage_compute_psets(ures, uold, unew, func) != 0) goto err; return (ures); err: if (alloced) zs_usage_free(ures); return (NULL); } void zs_usage_free(zs_usage_t *usage) { zs_zone_t *zone, *ztmp; zs_pset_t *pset, *ptmp; zs_pset_zone_t *pz, *pztmp; if (usage->zsu_mmap) { (void) munmap((void *)usage, usage->zsu_size); return; } free(usage->zsu_system); zone = list_head(&usage->zsu_zone_list); while (zone != NULL) { ztmp = zone; zone = list_next(&usage->zsu_zone_list, zone); free(ztmp); } pset = list_head(&usage->zsu_pset_list); while (pset != NULL) { pz = list_head(&pset->zsp_usage_list); while (pz != NULL) { pztmp = pz; pz = list_next(&pset->zsp_usage_list, pz); free(pztmp); } ptmp = pset; pset = list_next(&usage->zsu_pset_list, pset); free(ptmp); } free(usage); } zs_usage_set_t * zs_usage_set_alloc() { zs_usage_set_t *set; set = calloc(sizeof (zs_usage_set_t), 1); if (set == NULL) return (NULL); if ((set->zsus_total = zs_usage_alloc()) == NULL) goto err; if ((set->zsus_avg = zs_usage_alloc()) == NULL) goto err; if ((set->zsus_high = zs_usage_alloc()) == NULL) goto err; return (set); err: if (set->zsus_total != NULL) free(set->zsus_total); if (set->zsus_avg != NULL) free(set->zsus_avg); if (set->zsus_high != NULL) free(set->zsus_high); return (NULL); } void zs_usage_set_free(zs_usage_set_t *set) { zs_usage_free(set->zsus_total); zs_usage_free(set->zsus_avg); zs_usage_free(set->zsus_high); free(set); } int zs_usage_set_add(zs_usage_set_t *set, zs_usage_t *usage) { /* Compute ongoing functions for usage set */ (void) zs_usage_compute(set->zsus_high, set->zsus_high, usage, ZS_COMPUTE_USAGE_HIGH); (void) zs_usage_compute(set->zsus_total, set->zsus_total, usage, ZS_COMPUTE_USAGE_TOTAL); (void) zs_usage_compute(set->zsus_avg, set->zsus_avg, usage, ZS_COMPUTE_USAGE_AVERAGE); set->zsus_count++; zs_usage_free(usage); return (0); } int zs_usage_set_count(zs_usage_set_t *set) { return (set->zsus_count); } zs_usage_t * zs_usage_set_compute(zs_usage_set_t *set, int func) { zs_usage_t *u; zs_system_t *s; zs_zone_t *z; zs_pset_t *p; zs_pset_zone_t *pz; uint_t intervals; boolean_t average; switch (func) { case ZS_COMPUTE_SET_HIGH: return (set->zsus_high); case ZS_COMPUTE_SET_TOTAL: u = set->zsus_total; average = B_FALSE; break; case ZS_COMPUTE_SET_AVERAGE: u = set->zsus_avg; average = B_TRUE; break; default: assert(0); } s = u->zsu_system; s->zss_ram_total /= u->zsu_intervals; s->zss_ram_total *= 1024; s->zss_ram_kern /= u->zsu_intervals; s->zss_ram_kern *= 1024; s->zss_ram_zones /= u->zsu_intervals; s->zss_ram_zones *= 1024; s->zss_locked_kern /= u->zsu_intervals; s->zss_locked_kern *= 1024; s->zss_locked_zones /= u->zsu_intervals; s->zss_locked_zones *= 1024; s->zss_vm_total /= u->zsu_intervals; s->zss_vm_total *= 1024; s->zss_vm_kern /= u->zsu_intervals; s->zss_vm_kern *= 1024; s->zss_vm_zones /= u->zsu_intervals; s->zss_vm_zones *= 1024; s->zss_swap_total /= u->zsu_intervals; s->zss_swap_total *= 1024; s->zss_swap_used /= u->zsu_intervals; s->zss_swap_used *= 1024; s->zss_processes /= u->zsu_intervals; s->zss_lwps /= u->zsu_intervals; s->zss_shm /= u->zsu_intervals; s->zss_shm *= 1024; s->zss_shmids /= u->zsu_intervals; s->zss_semids /= u->zsu_intervals; s->zss_msgids /= u->zsu_intervals; s->zss_lofi /= u->zsu_intervals; s->zss_ncpus /= u->zsu_intervals; s->zss_ncpus_online /= u->zsu_intervals; for (z = list_head(&u->zsu_zone_list); z != NULL; z = list_next(&u->zsu_zone_list, z)) { if (average) { intervals = z->zsz_intervals; } else { assert(z->zsz_intervals == 0); intervals = u->zsu_intervals; } if (z->zsz_cpu_cap != ZS_LIMIT_NONE) z->zsz_cpu_cap /= z->zsz_intervals; if (z->zsz_ram_cap != ZS_LIMIT_NONE) z->zsz_ram_cap /= z->zsz_intervals; if (z->zsz_vm_cap != ZS_LIMIT_NONE) z->zsz_vm_cap /= z->zsz_intervals; if (z->zsz_locked_cap != ZS_LIMIT_NONE) z->zsz_locked_cap /= z->zsz_intervals; if (z->zsz_processes_cap != ZS_LIMIT_NONE) z->zsz_processes_cap /= z->zsz_intervals; if (z->zsz_lwps_cap != ZS_LIMIT_NONE) z->zsz_lwps_cap /= z->zsz_intervals; if (z->zsz_shm_cap != ZS_LIMIT_NONE) z->zsz_shm_cap /= z->zsz_intervals; if (z->zsz_shmids_cap != ZS_LIMIT_NONE) z->zsz_shmids_cap /= z->zsz_intervals; if (z->zsz_semids_cap != ZS_LIMIT_NONE) z->zsz_semids_cap /= z->zsz_intervals; if (z->zsz_msgids_cap != ZS_LIMIT_NONE) z->zsz_msgids_cap /= z->zsz_intervals; if (z->zsz_lofi_cap != ZS_LIMIT_NONE) z->zsz_lofi_cap /= z->zsz_intervals; z->zsz_usage_ram /= intervals; z->zsz_usage_locked /= intervals; z->zsz_usage_vm /= intervals; z->zsz_processes /= intervals; z->zsz_lwps /= intervals; z->zsz_shm /= intervals; z->zsz_shmids /= intervals; z->zsz_semids /= intervals; z->zsz_msgids /= intervals; z->zsz_lofi /= intervals; z->zsz_cpus_online /= intervals; z->zsz_cpu_shares /= intervals; } for (p = list_head(&u->zsu_pset_list); p != NULL; p = list_next(&u->zsu_pset_list, p)) { intervals = p->zsp_intervals; p->zsp_online /= intervals; p->zsp_size /= intervals; p->zsp_min /= intervals; p->zsp_max /= intervals; p->zsp_importance /= intervals; p->zsp_cpu_shares /= intervals; for (pz = list_head(&p->zsp_usage_list); pz != NULL; pz = list_next(&p->zsp_usage_list, pz)) { if (average) { intervals = pz->zspz_intervals; } else { assert(pz->zspz_intervals == 0); intervals = p->zsp_intervals; } pz->zspz_cpu_shares /= intervals; } } return (u); } /* * Returns 0 on success. Trips assert on invalid property. */ void zs_resource_property(zs_usage_t *u, int res, int prop, zs_property_t *p) { switch (res) { case ZS_RESOURCE_CPU: switch (prop) { case ZS_RESOURCE_PROP_CPU_TOTAL: p->zsp_id = prop; p->zsp_type = ZS_PROP_TYPE_UINT64; p->zsp_v.zsv_uint64 = u->zsu_system->zss_ncpus; break; case ZS_RESOURCE_PROP_CPU_ONLINE: p->zsp_id = prop; p->zsp_type = ZS_PROP_TYPE_UINT64; p->zsp_v.zsv_uint64 = u->zsu_system->zss_ncpus_online; break; default: assert(0); } break; case ZS_RESOURCE_RAM_RSS: case ZS_RESOURCE_RAM_LOCKED: case ZS_RESOURCE_VM: case ZS_RESOURCE_DISK_SWAP: case ZS_RESOURCE_LWPS: case ZS_RESOURCE_PROCESSES: case ZS_RESOURCE_SHM_MEMORY: case ZS_RESOURCE_SHM_IDS: case ZS_RESOURCE_SEM_IDS: case ZS_RESOURCE_MSG_IDS: /* FALLTHROUGH */ default: assert(0); } } /* * Returns one of ZS_RESOURCE_TYPE_* on success. Asserts on invalid * resource. */ int zs_resource_type(int res) { switch (res) { case ZS_RESOURCE_CPU: return (ZS_RESOURCE_TYPE_TIME); break; case ZS_RESOURCE_RAM_RSS: case ZS_RESOURCE_RAM_LOCKED: case ZS_RESOURCE_VM: case ZS_RESOURCE_DISK_SWAP: case ZS_RESOURCE_SHM_MEMORY: return (ZS_RESOURCE_TYPE_BYTES); break; case ZS_RESOURCE_LWPS: case ZS_RESOURCE_PROCESSES: case ZS_RESOURCE_SHM_IDS: case ZS_RESOURCE_SEM_IDS: case ZS_RESOURCE_MSG_IDS: return (ZS_RESOURCE_TYPE_COUNT); break; default: assert(0); return (0); } } /* * Get total available resource on system */ uint64_t zs_resource_total_uint64(zs_usage_t *u, int res) { uint64_t v; switch (res) { case ZS_RESOURCE_CPU: v = zs_cpu_total_cpu(u); break; case ZS_RESOURCE_RAM_RSS: v = zs_physical_memory_total(u); break; case ZS_RESOURCE_RAM_LOCKED: v = zs_locked_memory_total(u); break; case ZS_RESOURCE_VM: v = zs_virtual_memory_total(u); break; case ZS_RESOURCE_DISK_SWAP: v = zs_disk_swap_total(u); break; case ZS_RESOURCE_LWPS: v = zs_lwps_total(u); break; case ZS_RESOURCE_PROCESSES: v = zs_processes_total(u); break; case ZS_RESOURCE_SHM_MEMORY: v = zs_shm_total(u); break; case ZS_RESOURCE_SHM_IDS: v = zs_shmids_total(u); break; case ZS_RESOURCE_SEM_IDS: v = zs_semids_total(u); break; case ZS_RESOURCE_MSG_IDS: v = zs_msgids_total(u); break; case ZS_RESOURCE_LOFI: v = zs_lofi_total(u); break; default: assert(0); } return (v); } /* * Get amount of used resource. */ uint64_t zs_resource_used_uint64(zs_usage_t *u, int res, int user) { uint64_t v; switch (res) { case ZS_RESOURCE_CPU: switch (user) { case ZS_USER_ALL: v = zs_cpu_usage_all_cpu(u); break; case ZS_USER_KERNEL: v = zs_cpu_usage_kernel_cpu(u); break; case ZS_USER_ZONES: v = zs_cpu_usage_zones_cpu(u); break; case ZS_USER_FREE: v = zs_cpu_usage_idle_cpu(u); break; default: assert(0); } break; case ZS_RESOURCE_RAM_RSS: switch (user) { case ZS_USER_ALL: v = zs_physical_memory_usage_all(u); break; case ZS_USER_KERNEL: v = zs_physical_memory_usage_kernel(u); break; case ZS_USER_ZONES: v = zs_physical_memory_usage_zones(u); break; case ZS_USER_FREE: v = zs_physical_memory_usage_free(u); break; default: assert(0); } break; case ZS_RESOURCE_RAM_LOCKED: switch (user) { case ZS_USER_ALL: v = zs_locked_memory_usage_all(u); break; case ZS_USER_KERNEL: v = zs_locked_memory_usage_kernel(u); break; case ZS_USER_ZONES: v = zs_locked_memory_usage_zones(u); break; case ZS_USER_FREE: v = zs_locked_memory_usage_free(u); break; default: assert(0); } break; case ZS_RESOURCE_VM: switch (user) { case ZS_USER_ALL: v = zs_virtual_memory_usage_all(u); break; case ZS_USER_KERNEL: v = zs_virtual_memory_usage_kernel(u); break; case ZS_USER_ZONES: v = zs_virtual_memory_usage_zones(u); break; case ZS_USER_FREE: v = zs_virtual_memory_usage_free(u); break; default: assert(0); } break; case ZS_RESOURCE_DISK_SWAP: switch (user) { case ZS_USER_ALL: v = zs_disk_swap_usage_all(u); break; case ZS_USER_FREE: v = zs_disk_swap_usage_free(u); break; case ZS_USER_KERNEL: case ZS_USER_ZONES: /* FALLTHROUGH */ default: assert(0); } break; case ZS_RESOURCE_LWPS: switch (user) { case ZS_USER_ALL: case ZS_USER_ZONES: v = zs_lwps_usage_all(u); break; case ZS_USER_FREE: v = zs_lwps_total(u) - zs_lwps_usage_all(u); break; case ZS_USER_KERNEL: v = 0; break; default: assert(0); } break; case ZS_RESOURCE_PROCESSES: switch (user) { case ZS_USER_ALL: case ZS_USER_ZONES: v = zs_processes_usage_all(u); break; case ZS_USER_FREE: v = zs_processes_total(u) - zs_processes_usage_all(u); break; case ZS_USER_KERNEL: v = 0; break; default: assert(0); } break; case ZS_RESOURCE_SHM_MEMORY: switch (user) { case ZS_USER_ALL: case ZS_USER_ZONES: v = zs_shm_usage_all(u); break; case ZS_USER_FREE: v = zs_shm_total(u) - zs_shm_usage_all(u); break; case ZS_USER_KERNEL: v = 0; break; default: assert(0); } break; case ZS_RESOURCE_SHM_IDS: switch (user) { case ZS_USER_ALL: case ZS_USER_ZONES: v = zs_shmids_usage_all(u); break; case ZS_USER_FREE: v = zs_shmids_total(u) - zs_shmids_usage_all(u); break; case ZS_USER_KERNEL: v = 0; break; default: assert(0); } break; case ZS_RESOURCE_SEM_IDS: switch (user) { case ZS_USER_ALL: case ZS_USER_ZONES: v = zs_semids_usage_all(u); break; case ZS_USER_FREE: v = zs_semids_total(u) - zs_semids_usage_all(u); break; case ZS_USER_KERNEL: v = 0; break; default: assert(0); } break; case ZS_RESOURCE_MSG_IDS: switch (user) { case ZS_USER_ALL: case ZS_USER_ZONES: v = zs_msgids_usage_all(u); break; case ZS_USER_FREE: v = zs_msgids_total(u) - zs_msgids_usage_all(u); break; case ZS_USER_KERNEL: v = 0; break; default: assert(0); } break; case ZS_RESOURCE_LOFI: switch (user) { case ZS_USER_ALL: case ZS_USER_ZONES: v = zs_lofi_usage_all(u); break; case ZS_USER_FREE: v = zs_lofi_total(u) - zs_lofi_usage_all(u); break; case ZS_USER_KERNEL: v = 0; break; default: assert(0); } break; default: assert(0); } return (v); } /* * Get used resource as a percent of total resource. */ uint_t zs_resource_used_pct(zs_usage_t *u, int res, int user) { uint64_t v; switch (res) { case ZS_RESOURCE_CPU: switch (user) { case ZS_USER_ALL: v = zs_cpu_usage_all_pct(u); break; case ZS_USER_KERNEL: v = zs_cpu_usage_kernel_pct(u); break; case ZS_USER_ZONES: v = zs_cpu_usage_zones_pct(u); break; case ZS_USER_FREE: v = zs_cpu_usage_idle_pct(u); break; default: assert(0); } break; case ZS_RESOURCE_RAM_RSS: switch (user) { case ZS_USER_ALL: v = zs_physical_memory_usage_all_pct(u); break; case ZS_USER_KERNEL: v = zs_physical_memory_usage_kernel_pct(u); break; case ZS_USER_ZONES: v = zs_physical_memory_usage_zones_pct(u); break; case ZS_USER_FREE: v = zs_physical_memory_usage_free_pct(u); break; default: assert(0); } break; case ZS_RESOURCE_RAM_LOCKED: switch (user) { case ZS_USER_ALL: v = zs_locked_memory_usage_all_pct(u); break; case ZS_USER_KERNEL: v = zs_locked_memory_usage_kernel_pct(u); break; case ZS_USER_ZONES: v = zs_locked_memory_usage_zones_pct(u); break; case ZS_USER_FREE: v = zs_locked_memory_usage_free_pct(u); break; default: assert(0); } break; case ZS_RESOURCE_VM: switch (user) { case ZS_USER_ALL: v = zs_virtual_memory_usage_all_pct(u); break; case ZS_USER_KERNEL: v = zs_virtual_memory_usage_kernel_pct(u); break; case ZS_USER_ZONES: v = zs_virtual_memory_usage_zones_pct(u); break; case ZS_USER_FREE: v = zs_virtual_memory_usage_free_pct(u); break; default: assert(0); } break; case ZS_RESOURCE_DISK_SWAP: switch (user) { case ZS_USER_ALL: v = zs_disk_swap_usage_all_pct(u); break; case ZS_USER_FREE: v = zs_disk_swap_usage_free_pct(u); break; case ZS_USER_KERNEL: case ZS_USER_ZONES: /* FALLTHROUGH */ default: assert(0); } break; case ZS_RESOURCE_LWPS: switch (user) { case ZS_USER_ALL: case ZS_USER_ZONES: v = zs_lwps_usage_all_pct(u); break; case ZS_USER_FREE: v = ZSD_PCT_INT - zs_lwps_usage_all_pct(u); break; case ZS_USER_KERNEL: v = 0; break; default: assert(0); } break; case ZS_RESOURCE_PROCESSES: switch (user) { case ZS_USER_ALL: case ZS_USER_ZONES: v = zs_processes_usage_all_pct(u); break; case ZS_USER_FREE: v = ZSD_PCT_INT - zs_processes_usage_all_pct(u); break; case ZS_USER_KERNEL: v = 0; break; default: assert(0); } break; case ZS_RESOURCE_SHM_MEMORY: switch (user) { case ZS_USER_ALL: case ZS_USER_ZONES: v = zs_shm_usage_all_pct(u); break; case ZS_USER_FREE: v = ZSD_PCT_INT - zs_shm_usage_all_pct(u); break; case ZS_USER_KERNEL: v = 0; break; default: assert(0); } break; case ZS_RESOURCE_SHM_IDS: switch (user) { case ZS_USER_ALL: case ZS_USER_ZONES: v = zs_shmids_usage_all_pct(u); break; case ZS_USER_FREE: v = ZSD_PCT_INT - zs_shmids_usage_all_pct(u); break; case ZS_USER_KERNEL: v = 0; break; default: assert(0); } break; case ZS_RESOURCE_SEM_IDS: switch (user) { case ZS_USER_ALL: case ZS_USER_ZONES: v = zs_semids_usage_all_pct(u); break; case ZS_USER_FREE: v = ZSD_PCT_INT - zs_semids_usage_all_pct(u); break; case ZS_USER_KERNEL: v = 0; break; default: assert(0); } break; case ZS_RESOURCE_MSG_IDS: switch (user) { case ZS_USER_ALL: case ZS_USER_ZONES: v = zs_msgids_usage_all_pct(u); break; case ZS_USER_FREE: v = ZSD_PCT_INT - zs_msgids_usage_all_pct(u); break; case ZS_USER_KERNEL: v = 0; break; default: assert(0); } break; case ZS_RESOURCE_LOFI: switch (user) { case ZS_USER_ALL: case ZS_USER_ZONES: v = zs_lofi_usage_all_pct(u); break; case ZS_USER_FREE: v = ZSD_PCT_INT - zs_lofi_usage_all_pct(u); break; case ZS_USER_KERNEL: v = 0; break; default: assert(0); } break; default: assert(0); } return (v); } /* * Get resource used by individual zone. */ uint64_t zs_resource_used_zone_uint64(zs_zone_t *z, int res) { uint64_t v; switch (res) { case ZS_RESOURCE_CPU: v = zs_cpu_usage_zone_cpu(z); break; case ZS_RESOURCE_RAM_RSS: v = zs_physical_memory_usage_zone(z); break; case ZS_RESOURCE_RAM_LOCKED: v = zs_locked_memory_usage_zone(z); break; case ZS_RESOURCE_VM: v = zs_virtual_memory_usage_zone(z); break; case ZS_RESOURCE_DISK_SWAP: assert(0); break; case ZS_RESOURCE_LWPS: v = zs_lwps_usage_zone(z); break; case ZS_RESOURCE_PROCESSES: v = zs_processes_usage_zone(z); break; case ZS_RESOURCE_SHM_MEMORY: v = zs_shm_usage_zone(z); break; case ZS_RESOURCE_SHM_IDS: v = zs_shmids_usage_zone(z); break; case ZS_RESOURCE_SEM_IDS: v = zs_semids_usage_zone(z); break; case ZS_RESOURCE_MSG_IDS: v = zs_msgids_usage_zone(z); break; case ZS_RESOURCE_LOFI: v = zs_lofi_usage_zone(z); break; default: assert(0); } return (v); } /* * Get resource used by individual zone as percent */ uint_t zs_resource_used_zone_pct(zs_zone_t *z, int res) { uint_t v; switch (res) { case ZS_RESOURCE_CPU: v = zs_cpu_usage_zone_pct(z); break; case ZS_RESOURCE_RAM_RSS: v = zs_physical_memory_usage_zone_pct(z); break; case ZS_RESOURCE_RAM_LOCKED: v = zs_locked_memory_usage_zone_pct(z); break; case ZS_RESOURCE_VM: v = zs_virtual_memory_usage_zone_pct(z); break; case ZS_RESOURCE_DISK_SWAP: assert(0); break; case ZS_RESOURCE_LWPS: v = zs_lwps_usage_zone_pct(z); break; case ZS_RESOURCE_PROCESSES: v = zs_processes_usage_zone_pct(z); break; case ZS_RESOURCE_SHM_MEMORY: v = zs_shm_usage_zone_pct(z); break; case ZS_RESOURCE_SHM_IDS: v = zs_shmids_usage_zone_pct(z); break; case ZS_RESOURCE_SEM_IDS: v = zs_semids_usage_zone_pct(z); break; case ZS_RESOURCE_MSG_IDS: v = zs_msgids_usage_zone_pct(z); break; case ZS_RESOURCE_LOFI: v = zs_lofi_usage_zone_pct(z); break; default: assert(0); } return (v); } /* * Get total time available for a resource */ void zs_resource_total_time(zs_usage_t *u, int res, timestruc_t *t) { switch (res) { case ZS_RESOURCE_CPU: zs_cpu_total_time(u, t); break; case ZS_RESOURCE_RAM_RSS: case ZS_RESOURCE_RAM_LOCKED: case ZS_RESOURCE_VM: case ZS_RESOURCE_DISK_SWAP: case ZS_RESOURCE_LWPS: case ZS_RESOURCE_PROCESSES: case ZS_RESOURCE_SHM_MEMORY: case ZS_RESOURCE_SHM_IDS: case ZS_RESOURCE_SEM_IDS: case ZS_RESOURCE_MSG_IDS: /* FALLTHROUGH */ default: assert(0); } } /* * Get total time used for a resource */ void zs_resource_used_time(zs_usage_t *u, int res, int user, timestruc_t *t) { switch (res) { case ZS_RESOURCE_CPU: switch (user) { case ZS_USER_ALL: zs_cpu_usage_all(u, t); break; case ZS_USER_KERNEL: zs_cpu_usage_kernel(u, t); break; case ZS_USER_ZONES: zs_cpu_usage_zones(u, t); break; case ZS_USER_FREE: zs_cpu_usage_idle(u, t); break; default: assert(0); } break; case ZS_RESOURCE_RAM_RSS: case ZS_RESOURCE_RAM_LOCKED: case ZS_RESOURCE_VM: case ZS_RESOURCE_DISK_SWAP: case ZS_RESOURCE_LWPS: case ZS_RESOURCE_PROCESSES: case ZS_RESOURCE_SHM_MEMORY: case ZS_RESOURCE_SHM_IDS: case ZS_RESOURCE_SEM_IDS: case ZS_RESOURCE_MSG_IDS: /* FALLTHROUGH */ default: assert(0); } } /* * Get total resource time used for a particular zone */ void zs_resource_used_zone_time(zs_zone_t *z, int res, timestruc_t *t) { switch (res) { case ZS_RESOURCE_CPU: zs_cpu_usage_zone(z, t); break; case ZS_RESOURCE_RAM_RSS: case ZS_RESOURCE_RAM_LOCKED: case ZS_RESOURCE_VM: case ZS_RESOURCE_DISK_SWAP: case ZS_RESOURCE_SHM_MEMORY: case ZS_RESOURCE_LWPS: case ZS_RESOURCE_PROCESSES: case ZS_RESOURCE_SHM_IDS: case ZS_RESOURCE_SEM_IDS: case ZS_RESOURCE_MSG_IDS: /* FALLTHROUGH */ default: assert(0); } } int zs_zone_list(zs_usage_t *usage, zs_zone_t **zonelist, int num) { int i = 0; zs_zone_t *zone, *tmp; /* copy what fits of the zone list into the buffer */ for (zone = list_head(&usage->zsu_zone_list); zone != NULL; zone = list_next(&usage->zsu_zone_list, zone)) { /* put the global zone at the first position */ if (i < num) { if (zone->zsz_id == GLOBAL_ZONEID) { tmp = zonelist[0]; zonelist[i] = tmp; zonelist[0] = zone; } else { zonelist[i] = zone; } } i++; } return (i); } zs_zone_t * zs_zone_first(zs_usage_t *usage) { return (list_head(&usage->zsu_zone_list)); } zs_zone_t * zs_zone_next(zs_usage_t *usage, zs_zone_t *zone) { return (list_next(&usage->zsu_zone_list, zone)); } /* * Gets a zone property */ void zs_zone_property(zs_zone_t *zone, int prop, zs_property_t *p) { switch (prop) { case ZS_ZONE_PROP_NAME: p->zsp_type = ZS_PROP_TYPE_STRING; p->zsp_id = prop; (void) zs_zone_name(zone, p->zsp_v.zsv_string, sizeof (p->zsp_v.zsv_string)); break; case ZS_ZONE_PROP_ID: p->zsp_type = ZS_PROP_TYPE_INT; p->zsp_id = prop; p->zsp_v.zsv_int = zs_zone_id(zone); break; case ZS_ZONE_PROP_IPTYPE: p->zsp_type = ZS_PROP_TYPE_UINT; p->zsp_id = prop; p->zsp_v.zsv_uint = zs_zone_iptype(zone); break; case ZS_ZONE_PROP_CPUTYPE: p->zsp_type = ZS_PROP_TYPE_UINT; p->zsp_id = prop; p->zsp_v.zsv_uint = zs_zone_cputype(zone); break; case ZS_ZONE_PROP_SCHEDULERS: p->zsp_type = ZS_PROP_TYPE_UINT; p->zsp_id = prop; p->zsp_v.zsv_uint = zs_zone_schedulers(zone); break; case ZS_ZONE_PROP_CPU_SHARES: p->zsp_type = ZS_PROP_TYPE_UINT64; p->zsp_id = prop; p->zsp_v.zsv_uint64 = zs_zone_cpu_shares(zone); break; case ZS_ZONE_PROP_POOLNAME: p->zsp_type = ZS_PROP_TYPE_STRING; p->zsp_id = prop; (void) zs_zone_poolname(zone, p->zsp_v.zsv_string, sizeof (p->zsp_v.zsv_string)); break; case ZS_ZONE_PROP_PSETNAME: p->zsp_type = ZS_PROP_TYPE_STRING; p->zsp_id = prop; (void) zs_zone_psetname(zone, p->zsp_v.zsv_string, sizeof (p->zsp_v.zsv_string)); break; /* Not implemented */ case ZS_ZONE_PROP_DEFAULT_SCHED: case ZS_ZONE_PROP_UPTIME: case ZS_ZONE_PROP_BOOTTIME: /* FALLTHROUGH */ default: assert(0); } } int zs_zone_limit_type(int limit) { switch (limit) { case ZS_LIMIT_CPU: case ZS_LIMIT_CPU_SHARES: return (ZS_LIMIT_TYPE_TIME); case ZS_LIMIT_RAM_RSS: case ZS_LIMIT_RAM_LOCKED: case ZS_LIMIT_VM: case ZS_LIMIT_SHM_MEMORY: return (ZS_LIMIT_TYPE_BYTES); case ZS_LIMIT_LWPS: case ZS_LIMIT_PROCESSES: case ZS_LIMIT_SHM_IDS: case ZS_LIMIT_MSG_IDS: case ZS_LIMIT_SEM_IDS: return (ZS_LIMIT_TYPE_COUNT); default: assert(0); return (0); } } /* * Gets the zones limit. Returns ZS_LIMIT_NONE if no limit set. */ uint64_t zs_zone_limit_uint64(zs_zone_t *z, int limit) { uint64_t v; switch (limit) { case ZS_LIMIT_CPU: v = zs_zone_cpu_cap(z); break; case ZS_LIMIT_CPU_SHARES: v = zs_zone_cpu_shares(z); break; case ZS_LIMIT_RAM_RSS: v = zs_zone_physical_memory_cap(z); break; case ZS_LIMIT_RAM_LOCKED: v = zs_zone_locked_memory_cap(z); break; case ZS_LIMIT_VM: v = zs_zone_virtual_memory_cap(z); break; case ZS_LIMIT_LWPS: v = z->zsz_lwps_cap; break; case ZS_LIMIT_PROCESSES: v = z->zsz_processes_cap; break; case ZS_LIMIT_SHM_MEMORY: v = z->zsz_shm_cap; break; case ZS_LIMIT_SHM_IDS: v = z->zsz_shmids_cap; break; case ZS_LIMIT_SEM_IDS: v = z->zsz_semids_cap; break; case ZS_LIMIT_MSG_IDS: v = z->zsz_msgids_cap; break; case ZS_LIMIT_LOFI: v = z->zsz_lofi_cap; break; default: assert(0); } return (v); } /* * Gets the amount of resource used for a limit. Returns ZS_LIMIT_NONE if * no limit configured. */ uint64_t zs_zone_limit_used_uint64(zs_zone_t *z, int limit) { uint64_t v; switch (limit) { case ZS_LIMIT_CPU: v = zs_zone_cpu_cap_used(z); break; case ZS_LIMIT_CPU_SHARES: v = zs_zone_cpu_shares_used(z); break; case ZS_LIMIT_RAM_RSS: v = zs_zone_physical_memory_cap_used(z); break; case ZS_LIMIT_RAM_LOCKED: v = zs_zone_locked_memory_cap_used(z); break; case ZS_LIMIT_VM: v = zs_zone_virtual_memory_cap_used(z); break; case ZS_LIMIT_LWPS: v = z->zsz_lwps; break; case ZS_LIMIT_PROCESSES: v = z->zsz_processes; break; case ZS_LIMIT_SHM_MEMORY: v = z->zsz_shm; break; case ZS_LIMIT_SHM_IDS: v = z->zsz_shmids; break; case ZS_LIMIT_SEM_IDS: v = z->zsz_semids; break; case ZS_LIMIT_MSG_IDS: v = z->zsz_msgids; break; case ZS_LIMIT_LOFI: v = z->zsz_lofi; break; default: assert(0); } return (v); } /* * Gets time used under limit. Time is zero if no limit is configured */ void zs_zone_limit_time(zs_zone_t *z, int limit, timestruc_t *v) { switch (limit) { case ZS_LIMIT_CPU: if (z->zsz_cpu_cap == ZS_LIMIT_NONE) { v->tv_sec = 0; v->tv_nsec = 0; break; } zs_zone_cpu_cap_time(z, v); break; case ZS_LIMIT_CPU_SHARES: if (z->zsz_cpu_shares == ZS_LIMIT_NONE || z->zsz_cpu_shares == ZS_SHARES_UNLIMITED || z->zsz_cpu_shares == 0 || (z->zsz_scheds & ZS_SCHED_FSS) == 0) { v->tv_sec = 0; v->tv_nsec = 0; break; } zs_zone_cpu_share_time(z, v); break; case ZS_LIMIT_RAM_RSS: case ZS_LIMIT_RAM_LOCKED: case ZS_LIMIT_VM: case ZS_LIMIT_SHM_MEMORY: case ZS_LIMIT_LWPS: case ZS_LIMIT_PROCESSES: case ZS_LIMIT_SHM_IDS: case ZS_LIMIT_MSG_IDS: case ZS_LIMIT_SEM_IDS: /* FALLTHROUGH */ default: assert(0); } } /* * Errno is set on error: * * EINVAL: No such property * ENOENT: No time value for the specified limit. * ESRCH: No limit is configured. * * If no limit is configured, the value will be ZS_PCT_NONE */ void zs_zone_limit_used_time(zs_zone_t *z, int limit, timestruc_t *t) { switch (limit) { case ZS_LIMIT_CPU: if (z->zsz_cpu_cap == ZS_LIMIT_NONE) { t->tv_sec = 0; t->tv_nsec = 0; break; } zs_zone_cpu_cap_time_used(z, t); break; case ZS_LIMIT_CPU_SHARES: if (z->zsz_cpu_shares == ZS_LIMIT_NONE || z->zsz_cpu_shares == ZS_SHARES_UNLIMITED || z->zsz_cpu_shares == 0 || (z->zsz_scheds & ZS_SCHED_FSS) == 0) { t->tv_sec = 0; t->tv_nsec = 0; break; } zs_zone_cpu_share_time_used(z, t); break; case ZS_LIMIT_RAM_RSS: case ZS_LIMIT_RAM_LOCKED: case ZS_LIMIT_VM: case ZS_LIMIT_SHM_MEMORY: case ZS_LIMIT_LWPS: case ZS_LIMIT_PROCESSES: case ZS_LIMIT_SHM_IDS: case ZS_LIMIT_MSG_IDS: case ZS_LIMIT_SEM_IDS: /* FALLTHROUGH */ default: assert(0); } } /* * Get a zones usage as a percent of the limit. Return ZS_PCT_NONE if * no limit is configured. */ uint_t zs_zone_limit_used_pct(zs_zone_t *z, int limit) { uint_t v; switch (limit) { case ZS_LIMIT_CPU: v = zs_zone_cpu_cap_pct(z); break; case ZS_LIMIT_CPU_SHARES: v = zs_zone_cpu_shares_pct(z); break; case ZS_LIMIT_RAM_RSS: v = zs_zone_physical_memory_cap_pct(z); break; case ZS_LIMIT_RAM_LOCKED: v = zs_zone_locked_memory_cap_pct(z); break; case ZS_LIMIT_VM: v = zs_zone_virtual_memory_cap_pct(z); break; case ZS_LIMIT_LWPS: v = zs_lwps_zone_cap_pct(z); break; case ZS_LIMIT_PROCESSES: v = zs_processes_zone_cap_pct(z); break; case ZS_LIMIT_SHM_MEMORY: v = zs_shm_zone_cap_pct(z); break; case ZS_LIMIT_SHM_IDS: v = zs_shmids_zone_cap_pct(z); break; case ZS_LIMIT_SEM_IDS: v = zs_semids_zone_cap_pct(z); break; case ZS_LIMIT_MSG_IDS: v = zs_msgids_zone_cap_pct(z); break; case ZS_LIMIT_LOFI: v = zs_lofi_zone_cap_pct(z); break; default: assert(0); } return (v); } int zs_pset_list(zs_usage_t *usage, zs_pset_t **psetlist, int num) { int i = 0; zs_pset_t *pset, *tmp; /* copy what fits of the pset list into the buffer */ for (pset = list_head(&usage->zsu_pset_list); pset != NULL; pset = list_next(&usage->zsu_pset_list, pset)) { /* put the default pset at the first position */ if (i < num) { if (pset->zsp_id == ZS_PSET_DEFAULT) { tmp = psetlist[0]; psetlist[i] = tmp; psetlist[0] = pset; } else { psetlist[i] = pset; } } i++; } return (i); } zs_pset_t * zs_pset_first(zs_usage_t *usage) { return (list_head(&usage->zsu_pset_list)); } zs_pset_t * zs_pset_next(zs_usage_t *usage, zs_pset_t *pset) { return (list_next(&usage->zsu_pset_list, pset)); } /* * Get various properties on a pset. */ void zs_pset_property(zs_pset_t *pset, int prop, zs_property_t *p) { switch (prop) { case ZS_PSET_PROP_NAME: p->zsp_type = ZS_PROP_TYPE_STRING; p->zsp_id = prop; (void) zs_pset_name(pset, p->zsp_v.zsv_string, sizeof (p->zsp_v.zsv_string)); break; case ZS_PSET_PROP_ID: p->zsp_type = ZS_PROP_TYPE_INT; p->zsp_id = prop; p->zsp_v.zsv_int = zs_pset_id(pset); break; case ZS_PSET_PROP_CPUTYPE: p->zsp_type = ZS_PROP_TYPE_UINT; p->zsp_id = prop; p->zsp_v.zsv_uint = zs_pset_cputype(pset); break; case ZS_PSET_PROP_SIZE: p->zsp_type = ZS_PROP_TYPE_UINT64; p->zsp_id = prop; p->zsp_v.zsv_uint64 = zs_pset_size(pset); break; case ZS_PSET_PROP_ONLINE: p->zsp_type = ZS_PROP_TYPE_UINT64; p->zsp_id = prop; p->zsp_v.zsv_uint64 = zs_pset_online(pset); break; case ZS_PSET_PROP_MIN: p->zsp_type = ZS_PROP_TYPE_UINT64; p->zsp_id = prop; p->zsp_v.zsv_uint64 = zs_pset_min(pset); break; case ZS_PSET_PROP_MAX: p->zsp_type = ZS_PROP_TYPE_UINT64; p->zsp_id = prop; p->zsp_v.zsv_uint64 = zs_pset_max(pset); break; case ZS_PSET_PROP_CPU_SHARES: p->zsp_type = ZS_PROP_TYPE_UINT64; p->zsp_id = prop; p->zsp_v.zsv_uint64 = zs_pset_cpu_shares(pset); break; case ZS_PSET_PROP_SCHEDULERS: p->zsp_type = ZS_PROP_TYPE_UINT; p->zsp_id = prop; p->zsp_v.zsv_uint = zs_pset_schedulers(pset); break; /* Not implemented */ case ZS_PSET_PROP_CREATETIME: case ZS_PSET_PROP_LOAD_1MIN: case ZS_PSET_PROP_LOAD_5MIN: case ZS_PSET_PROP_LOAD_15MIN: /* FALLTHROUGH */ default: assert(0); } } void zs_pset_total_time(zs_pset_t *pset, timestruc_t *t) { *t = pset->zsp_total_time; } uint64_t zs_pset_total_cpus(zs_pset_t *pset) { return (pset->zsp_online * ZSD_ONE_CPU); } /* * Get total time used for pset */ void zs_pset_used_time(zs_pset_t *pset, int user, timestruc_t *t) { switch (user) { case ZS_USER_ALL: zs_pset_usage_all(pset, t); break; case ZS_USER_KERNEL: zs_pset_usage_kernel(pset, t); break; case ZS_USER_ZONES: zs_pset_usage_zones(pset, t); break; case ZS_USER_FREE: zs_pset_usage_idle(pset, t); break; default: assert(0); } } /* * Returns 0 on success. -1 on failure. * * ERRORS * EINVAL: Invalid user. * */ uint64_t zs_pset_used_cpus(zs_pset_t *pset, int user) { uint_t v; switch (user) { case ZS_USER_ALL: v = zs_pset_usage_all_cpus(pset); break; case ZS_USER_KERNEL: v = zs_pset_usage_kernel_cpus(pset); break; case ZS_USER_ZONES: v = zs_pset_usage_zones_cpus(pset); break; case ZS_USER_FREE: v = zs_pset_usage_idle_cpus(pset); break; default: assert(0); } return (v); } /* * Get percent of pset cpu time used */ uint_t zs_pset_used_pct(zs_pset_t *pset, int user) { uint_t v; switch (user) { case ZS_USER_ALL: v = zs_pset_usage_all_pct(pset); break; case ZS_USER_KERNEL: v = zs_pset_usage_kernel_pct(pset); break; case ZS_USER_ZONES: v = zs_pset_usage_zones_pct(pset); break; case ZS_USER_FREE: v = zs_pset_usage_idle_pct(pset); break; default: assert(0); } return (v); } int zs_pset_zone_list(zs_pset_t *pset, zs_pset_zone_t **zonelist, int num) { int i = 0; zs_pset_zone_t *zone, *tmp; /* copy what fits of the pset's zone list into the buffer */ for (zone = list_head(&pset->zsp_usage_list); zone != NULL; zone = list_next(&pset->zsp_usage_list, zone)) { /* put the global zone at the first position */ if (i < num) { if (zone->zspz_zone->zsz_id == GLOBAL_ZONEID) { tmp = zonelist[0]; zonelist[i] = tmp; zonelist[0] = zone; } else { zonelist[i] = zone; } } i++; } return (i); } zs_pset_zone_t * zs_pset_zone_first(zs_pset_t *pset) { return (list_head(&pset->zsp_usage_list)); } zs_pset_zone_t * zs_pset_zone_next(zs_pset_t *pset, zs_pset_zone_t *pz) { return (list_next(&pset->zsp_usage_list, pz)); } zs_pset_t * zs_pset_zone_get_pset(zs_pset_zone_t *pz) { return (pz->zspz_pset); } zs_zone_t * zs_pset_zone_get_zone(zs_pset_zone_t *pz) { return (pz->zspz_zone); } /* * Get a property describing a zone's usage of a pset */ void zs_pset_zone_property(zs_pset_zone_t *pz, int prop, zs_property_t *p) { switch (prop) { case ZS_PZ_PROP_CPU_CAP: p->zsp_type = ZS_PROP_TYPE_UINT64; p->zsp_id = prop; p->zsp_v.zsv_uint64 = (int)zs_pset_zone_cpu_cap(pz); break; case ZS_PZ_PROP_CPU_SHARES: p->zsp_type = ZS_PROP_TYPE_UINT64; p->zsp_id = prop; p->zsp_v.zsv_uint64 = (int)zs_pset_zone_cpu_shares(pz); break; case ZS_PZ_PROP_SCHEDULERS: p->zsp_type = ZS_PROP_TYPE_UINT; p->zsp_id = prop; p->zsp_v.zsv_uint = (int)zs_pset_zone_schedulers(pz); break; default: assert(0); } } void zs_pset_zone_used_time(zs_pset_zone_t *pz, timestruc_t *t) { zs_pset_zone_usage_time(pz, t); } uint64_t zs_pset_zone_used_cpus(zs_pset_zone_t *pz) { return (zs_pset_zone_usage_cpus(pz)); } /* * Get percent of a psets cpus used by a zone */ uint_t zs_pset_zone_used_pct(zs_pset_zone_t *pz, int type) { uint_t v; switch (type) { case ZS_PZ_PCT_PSET: v = zs_pset_zone_usage_pct_pset(pz); break; case ZS_PZ_PCT_CPU_CAP: v = zs_pset_zone_usage_pct_cpu_cap(pz); break; case ZS_PZ_PCT_PSET_SHARES: v = zs_pset_zone_usage_pct_pset_shares(pz); break; case ZS_PZ_PCT_CPU_SHARES: v = zs_pset_zone_usage_pct_cpu_shares(pz); break; default: assert(0); } return (v); } /* * returns similar to malloc */ zs_property_t * zs_property_alloc() { return ((zs_property_t *)malloc(sizeof (zs_property_t))); } size_t zs_property_size() { return (sizeof (zs_property_t)); } void zs_property_free(zs_property_t *p) { free(p); } int zs_property_type(zs_property_t *p) { return (p->zsp_type); } int zs_property_id(zs_property_t *p) { return (p->zsp_id); } char * zs_property_string(zs_property_t *p) { assert(p->zsp_type == ZS_PROP_TYPE_STRING); return (p->zsp_v.zsv_string); } double zs_property_double(zs_property_t *p) { assert(p->zsp_type == ZS_PROP_TYPE_DOUBLE); return (p->zsp_v.zsv_double); } void zs_property_time(zs_property_t *p, timestruc_t *t) { assert(p->zsp_type == ZS_PROP_TYPE_TIME); *t = p->zsp_v.zsv_ts; } uint64_t zs_property_uint64(zs_property_t *p) { assert(p->zsp_type == ZS_PROP_TYPE_UINT64); return (p->zsp_v.zsv_uint64); } int64_t zs_property_int64(zs_property_t *p) { assert(p->zsp_type == ZS_PROP_TYPE_INT64); return (p->zsp_v.zsv_int64); } uint_t zs_property_uint(zs_property_t *p) { assert(p->zsp_type == ZS_PROP_TYPE_UINT); return (p->zsp_v.zsv_uint); } int zs_property_int(zs_property_t *p) { assert(p->zsp_type == ZS_PROP_TYPE_INT); return (p->zsp_v.zsv_uint); }