1efd4c9b6SSteve Lawrence /* 2efd4c9b6SSteve Lawrence * CDDL HEADER START 3efd4c9b6SSteve Lawrence * 4efd4c9b6SSteve Lawrence * The contents of this file are subject to the terms of the 5efd4c9b6SSteve Lawrence * Common Development and Distribution License (the "License"). 6efd4c9b6SSteve Lawrence * You may not use this file except in compliance with the License. 7efd4c9b6SSteve Lawrence * 8efd4c9b6SSteve Lawrence * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9efd4c9b6SSteve Lawrence * or http://www.opensolaris.org/os/licensing. 10efd4c9b6SSteve Lawrence * See the License for the specific language governing permissions 11efd4c9b6SSteve Lawrence * and limitations under the License. 12efd4c9b6SSteve Lawrence * 13efd4c9b6SSteve Lawrence * When distributing Covered Code, include this CDDL HEADER in each 14efd4c9b6SSteve Lawrence * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15efd4c9b6SSteve Lawrence * If applicable, add the following below this CDDL HEADER, with the 16efd4c9b6SSteve Lawrence * fields enclosed by brackets "[]" replaced with your own identifying 17efd4c9b6SSteve Lawrence * information: Portions Copyright [yyyy] [name of copyright owner] 18efd4c9b6SSteve Lawrence * 19efd4c9b6SSteve Lawrence * CDDL HEADER END 20efd4c9b6SSteve Lawrence */ 21efd4c9b6SSteve Lawrence 22efd4c9b6SSteve Lawrence /* 23efd4c9b6SSteve Lawrence * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 24efd4c9b6SSteve Lawrence */ 25efd4c9b6SSteve Lawrence #include <alloca.h> 26efd4c9b6SSteve Lawrence #include <assert.h> 27efd4c9b6SSteve Lawrence #include <dirent.h> 28efd4c9b6SSteve Lawrence #include <dlfcn.h> 29efd4c9b6SSteve Lawrence #include <door.h> 30efd4c9b6SSteve Lawrence #include <errno.h> 31efd4c9b6SSteve Lawrence #include <exacct.h> 32efd4c9b6SSteve Lawrence #include <ctype.h> 33efd4c9b6SSteve Lawrence #include <fcntl.h> 34efd4c9b6SSteve Lawrence #include <kstat.h> 35efd4c9b6SSteve Lawrence #include <libcontract.h> 36efd4c9b6SSteve Lawrence #include <libintl.h> 37efd4c9b6SSteve Lawrence #include <libscf.h> 38efd4c9b6SSteve Lawrence #include <zonestat.h> 39efd4c9b6SSteve Lawrence #include <zonestat_impl.h> 40efd4c9b6SSteve Lawrence #include <limits.h> 41efd4c9b6SSteve Lawrence #include <pool.h> 42efd4c9b6SSteve Lawrence #include <procfs.h> 43efd4c9b6SSteve Lawrence #include <rctl.h> 44efd4c9b6SSteve Lawrence #include <thread.h> 45efd4c9b6SSteve Lawrence #include <signal.h> 46efd4c9b6SSteve Lawrence #include <stdarg.h> 47efd4c9b6SSteve Lawrence #include <stddef.h> 48efd4c9b6SSteve Lawrence #include <stdio.h> 49efd4c9b6SSteve Lawrence #include <stdlib.h> 50efd4c9b6SSteve Lawrence #include <strings.h> 51efd4c9b6SSteve Lawrence #include <synch.h> 52efd4c9b6SSteve Lawrence #include <sys/acctctl.h> 53efd4c9b6SSteve Lawrence #include <sys/contract/process.h> 54efd4c9b6SSteve Lawrence #include <sys/ctfs.h> 55efd4c9b6SSteve Lawrence #include <sys/fork.h> 56efd4c9b6SSteve Lawrence #include <sys/param.h> 57efd4c9b6SSteve Lawrence #include <sys/priocntl.h> 58efd4c9b6SSteve Lawrence #include <sys/fxpriocntl.h> 59efd4c9b6SSteve Lawrence #include <sys/processor.h> 60efd4c9b6SSteve Lawrence #include <sys/pset.h> 61efd4c9b6SSteve Lawrence #include <sys/socket.h> 62efd4c9b6SSteve Lawrence #include <sys/stat.h> 63efd4c9b6SSteve Lawrence #include <sys/statvfs.h> 64efd4c9b6SSteve Lawrence #include <sys/swap.h> 65efd4c9b6SSteve Lawrence #include <sys/systeminfo.h> 66efd4c9b6SSteve Lawrence #include <thread.h> 67efd4c9b6SSteve Lawrence #include <sys/list.h> 68efd4c9b6SSteve Lawrence #include <sys/time.h> 69efd4c9b6SSteve Lawrence #include <sys/types.h> 70efd4c9b6SSteve Lawrence #include <sys/vm_usage.h> 71efd4c9b6SSteve Lawrence #include <sys/wait.h> 72efd4c9b6SSteve Lawrence #include <sys/zone.h> 73efd4c9b6SSteve Lawrence #include <time.h> 74efd4c9b6SSteve Lawrence #include <ucred.h> 75efd4c9b6SSteve Lawrence #include <unistd.h> 76efd4c9b6SSteve Lawrence #include <vm/anon.h> 77efd4c9b6SSteve Lawrence #include <zone.h> 78efd4c9b6SSteve Lawrence #include <zonestat.h> 79efd4c9b6SSteve Lawrence 80efd4c9b6SSteve Lawrence #define MAX_PSET_NAME 1024 /* Taken from PV_NAME_MAX_LEN */ 81efd4c9b6SSteve Lawrence #define ZSD_PSET_UNLIMITED UINT16_MAX 82efd4c9b6SSteve Lawrence #define ZONESTAT_EXACCT_FILE "/var/adm/exacct/zonestat-process" 83efd4c9b6SSteve Lawrence 84efd4c9b6SSteve Lawrence /* 85efd4c9b6SSteve Lawrence * zonestatd implements gathering cpu and memory utilization data for 86efd4c9b6SSteve Lawrence * running zones. It has these components: 87efd4c9b6SSteve Lawrence * 88efd4c9b6SSteve Lawrence * zsd_server: 89efd4c9b6SSteve Lawrence * Door server to respond to client connections. Each client 90efd4c9b6SSteve Lawrence * will connect using libzonestat.so, which will open and 91efd4c9b6SSteve Lawrence * call /var/tmp/.zonestat_door. Each connecting client is given 92efd4c9b6SSteve Lawrence * a file descriptor to the stat server. 93efd4c9b6SSteve Lawrence * 94efd4c9b6SSteve Lawrence * The zsd_server also responds to zoneadmd, which reports when a 95efd4c9b6SSteve Lawrence * new zone is booted. This is used to fattach the zsd_server door 96efd4c9b6SSteve Lawrence * into the new zone. 97efd4c9b6SSteve Lawrence * 98efd4c9b6SSteve Lawrence * zsd_stat_server: 99efd4c9b6SSteve Lawrence * Receives client requests for the current utilization data. Each 100efd4c9b6SSteve Lawrence * client request will cause zonestatd to update the current utilization 101efd4c9b6SSteve Lawrence * data by kicking the stat_thread. 102efd4c9b6SSteve Lawrence * 103efd4c9b6SSteve Lawrence * If the client is in a non-global zone, the utilization data will 104efd4c9b6SSteve Lawrence * be filtered to only show the given zone. The usage by all other zones 105efd4c9b6SSteve Lawrence * will be added to the system utilization. 106efd4c9b6SSteve Lawrence * 107efd4c9b6SSteve Lawrence * stat_thread: 108efd4c9b6SSteve Lawrence * The stat thread implements querying the system to determine the 109efd4c9b6SSteve Lawrence * current utilization data for each running zone. This includes 110efd4c9b6SSteve Lawrence * inspecting the system's processor set configuration, as well as details 111efd4c9b6SSteve Lawrence * of each zone, such as their configured limits, and which processor 112efd4c9b6SSteve Lawrence * sets they are running in. 113efd4c9b6SSteve Lawrence * 114efd4c9b6SSteve Lawrence * The stat_thread will only update memory utilization data as often as 115efd4c9b6SSteve Lawrence * the configured config/sample_interval on the zones-monitoring service. 116efd4c9b6SSteve Lawrence */ 117efd4c9b6SSteve Lawrence 118efd4c9b6SSteve Lawrence /* 119efd4c9b6SSteve Lawrence * The private vmusage structure unfortunately uses size_t types, and assumes 120efd4c9b6SSteve Lawrence * the caller's bitness matches the kernel's bitness. Since the getvmusage() 121efd4c9b6SSteve Lawrence * system call is contracted, and zonestatd is 32 bit, the following structures 122efd4c9b6SSteve Lawrence * are used to interact with a 32bit or 64 bit kernel. 123efd4c9b6SSteve Lawrence */ 124efd4c9b6SSteve Lawrence typedef struct zsd_vmusage32 { 125efd4c9b6SSteve Lawrence id_t vmu_zoneid; 126efd4c9b6SSteve Lawrence uint_t vmu_type; 127efd4c9b6SSteve Lawrence id_t vmu_id; 128efd4c9b6SSteve Lawrence 129efd4c9b6SSteve Lawrence uint32_t vmu_rss_all; 130efd4c9b6SSteve Lawrence uint32_t vmu_rss_private; 131efd4c9b6SSteve Lawrence uint32_t vmu_rss_shared; 132efd4c9b6SSteve Lawrence uint32_t vmu_swap_all; 133efd4c9b6SSteve Lawrence uint32_t vmu_swap_private; 134efd4c9b6SSteve Lawrence uint32_t vmu_swap_shared; 135efd4c9b6SSteve Lawrence } zsd_vmusage32_t; 136efd4c9b6SSteve Lawrence 137efd4c9b6SSteve Lawrence typedef struct zsd_vmusage64 { 138efd4c9b6SSteve Lawrence id_t vmu_zoneid; 139efd4c9b6SSteve Lawrence uint_t vmu_type; 140efd4c9b6SSteve Lawrence id_t vmu_id; 141efd4c9b6SSteve Lawrence /* 142efd4c9b6SSteve Lawrence * An amd64 kernel will align the following uint64_t members, but a 143efd4c9b6SSteve Lawrence * 32bit i386 process will not without help. 144efd4c9b6SSteve Lawrence */ 145efd4c9b6SSteve Lawrence int vmu_align_next_members_on_8_bytes; 146efd4c9b6SSteve Lawrence uint64_t vmu_rss_all; 147efd4c9b6SSteve Lawrence uint64_t vmu_rss_private; 148efd4c9b6SSteve Lawrence uint64_t vmu_rss_shared; 149efd4c9b6SSteve Lawrence uint64_t vmu_swap_all; 150efd4c9b6SSteve Lawrence uint64_t vmu_swap_private; 151efd4c9b6SSteve Lawrence uint64_t vmu_swap_shared; 152efd4c9b6SSteve Lawrence } zsd_vmusage64_t; 153efd4c9b6SSteve Lawrence 154efd4c9b6SSteve Lawrence struct zsd_zone; 155efd4c9b6SSteve Lawrence 156efd4c9b6SSteve Lawrence /* Used to store a zone's usage of a pset */ 157efd4c9b6SSteve Lawrence typedef struct zsd_pset_usage { 158efd4c9b6SSteve Lawrence struct zsd_zone *zsu_zone; 159efd4c9b6SSteve Lawrence struct zsd_pset *zsu_pset; 160efd4c9b6SSteve Lawrence 161efd4c9b6SSteve Lawrence list_node_t zsu_next; 162efd4c9b6SSteve Lawrence 163efd4c9b6SSteve Lawrence zoneid_t zsu_zoneid; 164efd4c9b6SSteve Lawrence boolean_t zsu_found; /* zone bound at end of interval */ 165efd4c9b6SSteve Lawrence boolean_t zsu_active; /* zone was bound during interval */ 166efd4c9b6SSteve Lawrence boolean_t zsu_new; /* zone newly bound in this interval */ 167efd4c9b6SSteve Lawrence boolean_t zsu_deleted; /* zone was unbound in this interval */ 168efd4c9b6SSteve Lawrence boolean_t zsu_empty; /* no procs in pset in this interval */ 169efd4c9b6SSteve Lawrence time_t zsu_start; /* time when zone was found in pset */ 170efd4c9b6SSteve Lawrence hrtime_t zsu_hrstart; /* time when zone was found in pset */ 171efd4c9b6SSteve Lawrence uint64_t zsu_cpu_shares; 172efd4c9b6SSteve Lawrence uint_t zsu_scheds; /* schedulers found in this pass */ 173efd4c9b6SSteve Lawrence timestruc_t zsu_cpu_usage; /* cpu time used */ 174efd4c9b6SSteve Lawrence } zsd_pset_usage_t; 175efd4c9b6SSteve Lawrence 176efd4c9b6SSteve Lawrence /* Used to store a pset's utilization */ 177efd4c9b6SSteve Lawrence typedef struct zsd_pset { 178efd4c9b6SSteve Lawrence psetid_t zsp_id; 179efd4c9b6SSteve Lawrence list_node_t zsp_next; 180efd4c9b6SSteve Lawrence char zsp_name[ZS_PSETNAME_MAX]; 181efd4c9b6SSteve Lawrence 182efd4c9b6SSteve Lawrence uint_t zsp_cputype; /* default, dedicated or shared */ 183efd4c9b6SSteve Lawrence boolean_t zsp_found; /* pset found at end of interval */ 184efd4c9b6SSteve Lawrence boolean_t zsp_new; /* pset new in this interval */ 185efd4c9b6SSteve Lawrence boolean_t zsp_deleted; /* pset deleted in this interval */ 186efd4c9b6SSteve Lawrence boolean_t zsp_active; /* pset existed during interval */ 187efd4c9b6SSteve Lawrence boolean_t zsp_empty; /* no processes in pset */ 188efd4c9b6SSteve Lawrence time_t zsp_start; 189efd4c9b6SSteve Lawrence hrtime_t zsp_hrstart; 190efd4c9b6SSteve Lawrence 191efd4c9b6SSteve Lawrence uint64_t zsp_online; /* online cpus in interval */ 192efd4c9b6SSteve Lawrence uint64_t zsp_size; /* size in this interval */ 193efd4c9b6SSteve Lawrence uint64_t zsp_min; /* configured min in this interval */ 194efd4c9b6SSteve Lawrence uint64_t zsp_max; /* configured max in this interval */ 195efd4c9b6SSteve Lawrence int64_t zsp_importance; /* configured max in this interval */ 196efd4c9b6SSteve Lawrence 197efd4c9b6SSteve Lawrence uint_t zsp_scheds; /* scheds of processes found in pset */ 198efd4c9b6SSteve Lawrence uint64_t zsp_cpu_shares; /* total shares in this interval */ 199efd4c9b6SSteve Lawrence 200efd4c9b6SSteve Lawrence timestruc_t zsp_total_time; 201efd4c9b6SSteve Lawrence timestruc_t zsp_usage_kern; 202efd4c9b6SSteve Lawrence timestruc_t zsp_usage_zones; 203efd4c9b6SSteve Lawrence 204efd4c9b6SSteve Lawrence /* Individual zone usages of pset */ 205efd4c9b6SSteve Lawrence list_t zsp_usage_list; 206efd4c9b6SSteve Lawrence int zsp_nusage; 207efd4c9b6SSteve Lawrence 208efd4c9b6SSteve Lawrence /* Summed kstat values from individual cpus in pset */ 209efd4c9b6SSteve Lawrence timestruc_t zsp_idle; 210efd4c9b6SSteve Lawrence timestruc_t zsp_intr; 211efd4c9b6SSteve Lawrence timestruc_t zsp_kern; 212efd4c9b6SSteve Lawrence timestruc_t zsp_user; 213efd4c9b6SSteve Lawrence 214efd4c9b6SSteve Lawrence } zsd_pset_t; 215efd4c9b6SSteve Lawrence 216efd4c9b6SSteve Lawrence /* Used to track an individual cpu's utilization as reported by kstats */ 217efd4c9b6SSteve Lawrence typedef struct zsd_cpu { 218efd4c9b6SSteve Lawrence processorid_t zsc_id; 219efd4c9b6SSteve Lawrence list_node_t zsc_next; 220efd4c9b6SSteve Lawrence psetid_t zsc_psetid; 221efd4c9b6SSteve Lawrence psetid_t zsc_psetid_prev; 222efd4c9b6SSteve Lawrence zsd_pset_t *zsc_pset; 223efd4c9b6SSteve Lawrence 224efd4c9b6SSteve Lawrence boolean_t zsc_found; /* cpu online in this interval */ 225efd4c9b6SSteve Lawrence boolean_t zsc_onlined; /* cpu onlined during this interval */ 226efd4c9b6SSteve Lawrence boolean_t zsc_offlined; /* cpu offlined during this interval */ 227efd4c9b6SSteve Lawrence boolean_t zsc_active; /* cpu online during this interval */ 228efd4c9b6SSteve Lawrence boolean_t zsc_allocated; /* True if cpu has ever been found */ 229efd4c9b6SSteve Lawrence 230efd4c9b6SSteve Lawrence /* kstats this interval */ 231efd4c9b6SSteve Lawrence uint64_t zsc_nsec_idle; 232efd4c9b6SSteve Lawrence uint64_t zsc_nsec_intr; 233efd4c9b6SSteve Lawrence uint64_t zsc_nsec_kern; 234efd4c9b6SSteve Lawrence uint64_t zsc_nsec_user; 235efd4c9b6SSteve Lawrence 236efd4c9b6SSteve Lawrence /* kstats in most recent interval */ 237efd4c9b6SSteve Lawrence uint64_t zsc_nsec_idle_prev; 238efd4c9b6SSteve Lawrence uint64_t zsc_nsec_intr_prev; 239efd4c9b6SSteve Lawrence uint64_t zsc_nsec_kern_prev; 240efd4c9b6SSteve Lawrence uint64_t zsc_nsec_user_prev; 241efd4c9b6SSteve Lawrence 242efd4c9b6SSteve Lawrence /* Total kstat increases since zonestatd started reading kstats */ 243efd4c9b6SSteve Lawrence timestruc_t zsc_idle; 244efd4c9b6SSteve Lawrence timestruc_t zsc_intr; 245efd4c9b6SSteve Lawrence timestruc_t zsc_kern; 246efd4c9b6SSteve Lawrence timestruc_t zsc_user; 247efd4c9b6SSteve Lawrence 248efd4c9b6SSteve Lawrence } zsd_cpu_t; 249efd4c9b6SSteve Lawrence 250efd4c9b6SSteve Lawrence /* Used to describe an individual zone and its utilization */ 251efd4c9b6SSteve Lawrence typedef struct zsd_zone { 252efd4c9b6SSteve Lawrence zoneid_t zsz_id; 253efd4c9b6SSteve Lawrence list_node_t zsz_next; 254efd4c9b6SSteve Lawrence char zsz_name[ZS_ZONENAME_MAX]; 255efd4c9b6SSteve Lawrence uint_t zsz_cputype; 256efd4c9b6SSteve Lawrence uint_t zsz_iptype; 257efd4c9b6SSteve Lawrence time_t zsz_start; 258efd4c9b6SSteve Lawrence hrtime_t zsz_hrstart; 259efd4c9b6SSteve Lawrence 260efd4c9b6SSteve Lawrence char zsz_pool[ZS_POOLNAME_MAX]; 261efd4c9b6SSteve Lawrence char zsz_pset[ZS_PSETNAME_MAX]; 262efd4c9b6SSteve Lawrence int zsz_default_sched; 263efd4c9b6SSteve Lawrence /* These are deduced by inspecting processes */ 264efd4c9b6SSteve Lawrence psetid_t zsz_psetid; 265efd4c9b6SSteve Lawrence uint_t zsz_scheds; 266efd4c9b6SSteve Lawrence 267efd4c9b6SSteve Lawrence boolean_t zsz_new; /* zone booted during this interval */ 268efd4c9b6SSteve Lawrence boolean_t zsz_deleted; /* halted during this interval */ 269efd4c9b6SSteve Lawrence boolean_t zsz_active; /* running in this interval */ 270efd4c9b6SSteve Lawrence boolean_t zsz_empty; /* no processes in this interval */ 271efd4c9b6SSteve Lawrence boolean_t zsz_gone; /* not installed in this interval */ 272efd4c9b6SSteve Lawrence boolean_t zsz_found; /* Running at end of this interval */ 273efd4c9b6SSteve Lawrence 274efd4c9b6SSteve Lawrence uint64_t zsz_cpu_shares; 275efd4c9b6SSteve Lawrence uint64_t zsz_cpu_cap; 276efd4c9b6SSteve Lawrence uint64_t zsz_ram_cap; 277efd4c9b6SSteve Lawrence uint64_t zsz_locked_cap; 278efd4c9b6SSteve Lawrence uint64_t zsz_vm_cap; 279efd4c9b6SSteve Lawrence 280efd4c9b6SSteve Lawrence uint64_t zsz_cpus_online; 281efd4c9b6SSteve Lawrence timestruc_t zsz_cpu_usage; /* cpu time of cpu cap */ 282efd4c9b6SSteve Lawrence timestruc_t zsz_cap_time; /* cpu time of cpu cap */ 283efd4c9b6SSteve Lawrence timestruc_t zsz_share_time; /* cpu time of share of cpu */ 284efd4c9b6SSteve Lawrence timestruc_t zsz_pset_time; /* time of all psets zone is bound to */ 285efd4c9b6SSteve Lawrence 286efd4c9b6SSteve Lawrence uint64_t zsz_usage_ram; 287efd4c9b6SSteve Lawrence uint64_t zsz_usage_locked; 288efd4c9b6SSteve Lawrence uint64_t zsz_usage_vm; 289efd4c9b6SSteve Lawrence 290efd4c9b6SSteve Lawrence uint64_t zsz_processes_cap; 291efd4c9b6SSteve Lawrence uint64_t zsz_lwps_cap; 292efd4c9b6SSteve Lawrence uint64_t zsz_shm_cap; 293efd4c9b6SSteve Lawrence uint64_t zsz_shmids_cap; 294efd4c9b6SSteve Lawrence uint64_t zsz_semids_cap; 295efd4c9b6SSteve Lawrence uint64_t zsz_msgids_cap; 296efd4c9b6SSteve Lawrence uint64_t zsz_lofi_cap; 297efd4c9b6SSteve Lawrence 298efd4c9b6SSteve Lawrence uint64_t zsz_processes; 299efd4c9b6SSteve Lawrence uint64_t zsz_lwps; 300efd4c9b6SSteve Lawrence uint64_t zsz_shm; 301efd4c9b6SSteve Lawrence uint64_t zsz_shmids; 302efd4c9b6SSteve Lawrence uint64_t zsz_semids; 303efd4c9b6SSteve Lawrence uint64_t zsz_msgids; 304efd4c9b6SSteve Lawrence uint64_t zsz_lofi; 305efd4c9b6SSteve Lawrence 306efd4c9b6SSteve Lawrence } zsd_zone_t; 307efd4c9b6SSteve Lawrence 308efd4c9b6SSteve Lawrence /* 309efd4c9b6SSteve Lawrence * Used to track the cpu usage of an individual processes. 310efd4c9b6SSteve Lawrence * 311efd4c9b6SSteve Lawrence * zonestatd sweeps /proc each interval and charges the cpu usage of processes. 312efd4c9b6SSteve Lawrence * to their zone. As processes exit, their extended accounting records are 313efd4c9b6SSteve Lawrence * read and the difference of their total and known usage is charged to their 314efd4c9b6SSteve Lawrence * zone. 315efd4c9b6SSteve Lawrence * 316efd4c9b6SSteve Lawrence * If a process is never seen in /proc, the total usage on its extended 317efd4c9b6SSteve Lawrence * accounting record will be charged to its zone. 318efd4c9b6SSteve Lawrence */ 319efd4c9b6SSteve Lawrence typedef struct zsd_proc { 320efd4c9b6SSteve Lawrence list_node_t zspr_next; 321efd4c9b6SSteve Lawrence pid_t zspr_ppid; 322efd4c9b6SSteve Lawrence psetid_t zspr_psetid; 323efd4c9b6SSteve Lawrence zoneid_t zspr_zoneid; 324efd4c9b6SSteve Lawrence int zspr_sched; 325efd4c9b6SSteve Lawrence timestruc_t zspr_usage; 326efd4c9b6SSteve Lawrence } zsd_proc_t; 327efd4c9b6SSteve Lawrence 328efd4c9b6SSteve Lawrence /* Used to track the overall resource usage of the system */ 329efd4c9b6SSteve Lawrence typedef struct zsd_system { 330efd4c9b6SSteve Lawrence 331efd4c9b6SSteve Lawrence uint64_t zss_ram_total; 332efd4c9b6SSteve Lawrence uint64_t zss_ram_kern; 333efd4c9b6SSteve Lawrence uint64_t zss_ram_zones; 334efd4c9b6SSteve Lawrence 335efd4c9b6SSteve Lawrence uint64_t zss_locked_kern; 336efd4c9b6SSteve Lawrence uint64_t zss_locked_zones; 337efd4c9b6SSteve Lawrence 338efd4c9b6SSteve Lawrence uint64_t zss_vm_total; 339efd4c9b6SSteve Lawrence uint64_t zss_vm_kern; 340efd4c9b6SSteve Lawrence uint64_t zss_vm_zones; 341efd4c9b6SSteve Lawrence 342efd4c9b6SSteve Lawrence uint64_t zss_swap_total; 343efd4c9b6SSteve Lawrence uint64_t zss_swap_used; 344efd4c9b6SSteve Lawrence 345efd4c9b6SSteve Lawrence timestruc_t zss_idle; 346efd4c9b6SSteve Lawrence timestruc_t zss_intr; 347efd4c9b6SSteve Lawrence timestruc_t zss_kern; 348efd4c9b6SSteve Lawrence timestruc_t zss_user; 349efd4c9b6SSteve Lawrence 350efd4c9b6SSteve Lawrence timestruc_t zss_cpu_total_time; 351efd4c9b6SSteve Lawrence timestruc_t zss_cpu_usage_kern; 352efd4c9b6SSteve Lawrence timestruc_t zss_cpu_usage_zones; 353efd4c9b6SSteve Lawrence 354efd4c9b6SSteve Lawrence uint64_t zss_maxpid; 355efd4c9b6SSteve Lawrence uint64_t zss_processes_max; 356efd4c9b6SSteve Lawrence uint64_t zss_lwps_max; 357efd4c9b6SSteve Lawrence uint64_t zss_shm_max; 358efd4c9b6SSteve Lawrence uint64_t zss_shmids_max; 359efd4c9b6SSteve Lawrence uint64_t zss_semids_max; 360efd4c9b6SSteve Lawrence uint64_t zss_msgids_max; 361efd4c9b6SSteve Lawrence uint64_t zss_lofi_max; 362efd4c9b6SSteve Lawrence 363efd4c9b6SSteve Lawrence uint64_t zss_processes; 364efd4c9b6SSteve Lawrence uint64_t zss_lwps; 365efd4c9b6SSteve Lawrence uint64_t zss_shm; 366efd4c9b6SSteve Lawrence uint64_t zss_shmids; 367efd4c9b6SSteve Lawrence uint64_t zss_semids; 368efd4c9b6SSteve Lawrence uint64_t zss_msgids; 369efd4c9b6SSteve Lawrence uint64_t zss_lofi; 370efd4c9b6SSteve Lawrence 371efd4c9b6SSteve Lawrence uint64_t zss_ncpus; 372efd4c9b6SSteve Lawrence uint64_t zss_ncpus_online; 373efd4c9b6SSteve Lawrence 374efd4c9b6SSteve Lawrence } zsd_system_t; 375efd4c9b6SSteve Lawrence 376efd4c9b6SSteve Lawrence /* 377efd4c9b6SSteve Lawrence * A dumping ground for various information and structures used to compute 378efd4c9b6SSteve Lawrence * utilization. 379efd4c9b6SSteve Lawrence * 380efd4c9b6SSteve Lawrence * This structure is used to track the system while clients are connected. 381efd4c9b6SSteve Lawrence * When The first client connects, a zsd_ctl is allocated and configured by 382efd4c9b6SSteve Lawrence * zsd_open(). When all clients disconnect, the zsd_ctl is closed. 383efd4c9b6SSteve Lawrence */ 384efd4c9b6SSteve Lawrence typedef struct zsd_ctl { 385efd4c9b6SSteve Lawrence kstat_ctl_t *zsctl_kstat_ctl; 386efd4c9b6SSteve Lawrence 387efd4c9b6SSteve Lawrence /* To track extended accounting */ 388efd4c9b6SSteve Lawrence int zsctl_proc_fd; /* Log currently being used */ 389efd4c9b6SSteve Lawrence ea_file_t zsctl_proc_eaf; 390efd4c9b6SSteve Lawrence struct stat64 zsctl_proc_stat; 391efd4c9b6SSteve Lawrence int zsctl_proc_open; 392efd4c9b6SSteve Lawrence int zsctl_proc_fd_next; /* Log file to use next */ 393efd4c9b6SSteve Lawrence ea_file_t zsctl_proc_eaf_next; 394efd4c9b6SSteve Lawrence struct stat64 zsctl_proc_stat_next; 395efd4c9b6SSteve Lawrence int zsctl_proc_open_next; 396efd4c9b6SSteve Lawrence 397efd4c9b6SSteve Lawrence /* pool configuration handle */ 398efd4c9b6SSteve Lawrence pool_conf_t *zsctl_pool_conf; 399efd4c9b6SSteve Lawrence int zsctl_pool_status; 400efd4c9b6SSteve Lawrence int zsctl_pool_changed; 401efd4c9b6SSteve Lawrence 402efd4c9b6SSteve Lawrence /* The above usage tacking structures */ 403efd4c9b6SSteve Lawrence zsd_system_t *zsctl_system; 404efd4c9b6SSteve Lawrence list_t zsctl_zones; 405efd4c9b6SSteve Lawrence list_t zsctl_psets; 406efd4c9b6SSteve Lawrence list_t zsctl_cpus; 407efd4c9b6SSteve Lawrence zsd_cpu_t *zsctl_cpu_array; 408efd4c9b6SSteve Lawrence zsd_proc_t *zsctl_proc_array; 409efd4c9b6SSteve Lawrence 410efd4c9b6SSteve Lawrence /* Various system info */ 411efd4c9b6SSteve Lawrence uint64_t zsctl_maxcpuid; 412efd4c9b6SSteve Lawrence uint64_t zsctl_maxproc; 413efd4c9b6SSteve Lawrence uint64_t zsctl_kern_bits; 414efd4c9b6SSteve Lawrence uint64_t zsctl_pagesize; 415efd4c9b6SSteve Lawrence 416efd4c9b6SSteve Lawrence /* Used to track time available under a cpu cap. */ 417efd4c9b6SSteve Lawrence uint64_t zsctl_hrtime; 418efd4c9b6SSteve Lawrence uint64_t zsctl_hrtime_prev; 419efd4c9b6SSteve Lawrence timestruc_t zsctl_hrtime_total; 420efd4c9b6SSteve Lawrence 421efd4c9b6SSteve Lawrence struct timeval zsctl_timeofday; 422efd4c9b6SSteve Lawrence 423efd4c9b6SSteve Lawrence /* Caches for arrays allocated for use by various system calls */ 424efd4c9b6SSteve Lawrence psetid_t *zsctl_pset_cache; 425efd4c9b6SSteve Lawrence uint_t zsctl_pset_ncache; 426efd4c9b6SSteve Lawrence processorid_t *zsctl_cpu_cache; 427efd4c9b6SSteve Lawrence uint_t zsctl_cpu_ncache; 428efd4c9b6SSteve Lawrence zoneid_t *zsctl_zone_cache; 429efd4c9b6SSteve Lawrence uint_t zsctl_zone_ncache; 430efd4c9b6SSteve Lawrence struct swaptable *zsctl_swap_cache; 431efd4c9b6SSteve Lawrence uint64_t zsctl_swap_cache_size; 432efd4c9b6SSteve Lawrence uint64_t zsctl_swap_cache_num; 433efd4c9b6SSteve Lawrence zsd_vmusage64_t *zsctl_vmusage_cache; 434efd4c9b6SSteve Lawrence uint64_t zsctl_vmusage_cache_num; 435efd4c9b6SSteve Lawrence 436efd4c9b6SSteve Lawrence /* Info about procfs for scanning /proc */ 437efd4c9b6SSteve Lawrence struct dirent *zsctl_procfs_dent; 438efd4c9b6SSteve Lawrence long zsctl_procfs_dent_size; 439efd4c9b6SSteve Lawrence pool_value_t *zsctl_pool_vals[3]; 440efd4c9b6SSteve Lawrence 441efd4c9b6SSteve Lawrence /* Counts on tracked entities */ 442efd4c9b6SSteve Lawrence uint_t zsctl_nzones; 443efd4c9b6SSteve Lawrence uint_t zsctl_npsets; 444efd4c9b6SSteve Lawrence uint_t zsctl_npset_usages; 445efd4c9b6SSteve Lawrence } zsd_ctl_t; 446efd4c9b6SSteve Lawrence 447efd4c9b6SSteve Lawrence zsd_ctl_t *g_ctl; 448efd4c9b6SSteve Lawrence boolean_t g_open; /* True if g_ctl is open */ 449efd4c9b6SSteve Lawrence int g_hasclient; /* True if any clients are connected */ 450efd4c9b6SSteve Lawrence 451efd4c9b6SSteve Lawrence /* 452efd4c9b6SSteve Lawrence * The usage cache is updated by the stat_thread, and copied to clients by 453efd4c9b6SSteve Lawrence * the zsd_stat_server. Mutex and cond are to synchronize between the 454efd4c9b6SSteve Lawrence * stat_thread and the stat_server. 455efd4c9b6SSteve Lawrence */ 456efd4c9b6SSteve Lawrence zs_usage_cache_t *g_usage_cache; 457efd4c9b6SSteve Lawrence mutex_t g_usage_cache_lock; 458efd4c9b6SSteve Lawrence cond_t g_usage_cache_kick; 459efd4c9b6SSteve Lawrence uint_t g_usage_cache_kickers; 460efd4c9b6SSteve Lawrence cond_t g_usage_cache_wait; 461efd4c9b6SSteve Lawrence char *g_usage_cache_buf; 462efd4c9b6SSteve Lawrence uint_t g_usage_cache_bufsz; 463efd4c9b6SSteve Lawrence uint64_t g_gen_next; 464efd4c9b6SSteve Lawrence 465efd4c9b6SSteve Lawrence /* fds of door servers */ 466efd4c9b6SSteve Lawrence int g_server_door; 467efd4c9b6SSteve Lawrence int g_stat_door; 468efd4c9b6SSteve Lawrence 469efd4c9b6SSteve Lawrence /* 470efd4c9b6SSteve Lawrence * Starting and current time. Used to throttle memory calculation, and to 471efd4c9b6SSteve Lawrence * mark new zones and psets with their boot and creation time. 472efd4c9b6SSteve Lawrence */ 473efd4c9b6SSteve Lawrence time_t g_now; 474efd4c9b6SSteve Lawrence time_t g_start; 475efd4c9b6SSteve Lawrence hrtime_t g_hrnow; 476efd4c9b6SSteve Lawrence hrtime_t g_hrstart; 477efd4c9b6SSteve Lawrence uint64_t g_interval; 478efd4c9b6SSteve Lawrence 479efd4c9b6SSteve Lawrence /* 480efd4c9b6SSteve Lawrence * main() thread. 481efd4c9b6SSteve Lawrence */ 482efd4c9b6SSteve Lawrence thread_t g_main; 483efd4c9b6SSteve Lawrence 484efd4c9b6SSteve Lawrence /* PRINTFLIKE1 */ 485efd4c9b6SSteve Lawrence static void 486efd4c9b6SSteve Lawrence zsd_warn(const char *fmt, ...) 487efd4c9b6SSteve Lawrence { 488efd4c9b6SSteve Lawrence va_list alist; 489efd4c9b6SSteve Lawrence 490efd4c9b6SSteve Lawrence va_start(alist, fmt); 491efd4c9b6SSteve Lawrence 492efd4c9b6SSteve Lawrence (void) fprintf(stderr, gettext("zonestat: Warning: ")); 493efd4c9b6SSteve Lawrence (void) vfprintf(stderr, fmt, alist); 494efd4c9b6SSteve Lawrence (void) fprintf(stderr, "\n"); 495efd4c9b6SSteve Lawrence va_end(alist); 496efd4c9b6SSteve Lawrence } 497efd4c9b6SSteve Lawrence 498efd4c9b6SSteve Lawrence /* PRINTFLIKE1 */ 499efd4c9b6SSteve Lawrence static void 500efd4c9b6SSteve Lawrence zsd_error(const char *fmt, ...) 501efd4c9b6SSteve Lawrence { 502efd4c9b6SSteve Lawrence va_list alist; 503efd4c9b6SSteve Lawrence 504efd4c9b6SSteve Lawrence va_start(alist, fmt); 505efd4c9b6SSteve Lawrence 506efd4c9b6SSteve Lawrence (void) fprintf(stderr, gettext("zonestat: Error: ")); 507efd4c9b6SSteve Lawrence (void) vfprintf(stderr, fmt, alist); 508efd4c9b6SSteve Lawrence (void) fprintf(stderr, "\n"); 509efd4c9b6SSteve Lawrence va_end(alist); 510efd4c9b6SSteve Lawrence exit(1); 511efd4c9b6SSteve Lawrence } 512efd4c9b6SSteve Lawrence 513efd4c9b6SSteve Lawrence /* Turns on extended accounting if not configured externally */ 514efd4c9b6SSteve Lawrence int 515efd4c9b6SSteve Lawrence zsd_enable_cpu_stats() 516efd4c9b6SSteve Lawrence { 517efd4c9b6SSteve Lawrence char *path = ZONESTAT_EXACCT_FILE; 518efd4c9b6SSteve Lawrence char oldfile[MAXPATHLEN]; 519efd4c9b6SSteve Lawrence int ret, state = AC_ON; 520efd4c9b6SSteve Lawrence ac_res_t res[6]; 521efd4c9b6SSteve Lawrence 522efd4c9b6SSteve Lawrence /* 523efd4c9b6SSteve Lawrence * Start a new accounting file if accounting not configured 524efd4c9b6SSteve Lawrence * externally. 525efd4c9b6SSteve Lawrence */ 526efd4c9b6SSteve Lawrence 527efd4c9b6SSteve Lawrence res[0].ar_id = AC_PROC_PID; 528efd4c9b6SSteve Lawrence res[0].ar_state = AC_ON; 529efd4c9b6SSteve Lawrence res[1].ar_id = AC_PROC_ANCPID; 530efd4c9b6SSteve Lawrence res[1].ar_state = AC_ON; 531efd4c9b6SSteve Lawrence res[2].ar_id = AC_PROC_CPU; 532efd4c9b6SSteve Lawrence res[2].ar_state = AC_ON; 533efd4c9b6SSteve Lawrence res[3].ar_id = AC_PROC_TIME; 534efd4c9b6SSteve Lawrence res[3].ar_state = AC_ON; 535efd4c9b6SSteve Lawrence res[4].ar_id = AC_PROC_ZONENAME; 536efd4c9b6SSteve Lawrence res[4].ar_state = AC_ON; 537efd4c9b6SSteve Lawrence res[5].ar_id = AC_NONE; 538efd4c9b6SSteve Lawrence res[5].ar_state = AC_ON; 539efd4c9b6SSteve Lawrence if (acctctl(AC_PROC | AC_RES_SET, res, sizeof (res)) != 0) { 540efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to set accounting resources")); 541efd4c9b6SSteve Lawrence return (-1); 542efd4c9b6SSteve Lawrence } 543efd4c9b6SSteve Lawrence /* Only set accounting file if none is configured */ 544efd4c9b6SSteve Lawrence ret = acctctl(AC_PROC | AC_FILE_GET, oldfile, sizeof (oldfile)); 545efd4c9b6SSteve Lawrence if (ret < 0) { 546efd4c9b6SSteve Lawrence 547efd4c9b6SSteve Lawrence (void) unlink(path); 548efd4c9b6SSteve Lawrence if (acctctl(AC_PROC | AC_FILE_SET, path, strlen(path) + 1) 549efd4c9b6SSteve Lawrence == -1) { 550efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to set accounting file")); 551efd4c9b6SSteve Lawrence return (-1); 552efd4c9b6SSteve Lawrence } 553efd4c9b6SSteve Lawrence } 554efd4c9b6SSteve Lawrence if (acctctl(AC_PROC | AC_STATE_SET, &state, sizeof (state)) == -1) { 555efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to enable accounting")); 556efd4c9b6SSteve Lawrence return (-1); 557efd4c9b6SSteve Lawrence } 558efd4c9b6SSteve Lawrence return (0); 559efd4c9b6SSteve Lawrence } 560efd4c9b6SSteve Lawrence 561efd4c9b6SSteve Lawrence /* Turns off extended accounting if not configured externally */ 562efd4c9b6SSteve Lawrence int 563efd4c9b6SSteve Lawrence zsd_disable_cpu_stats() 564efd4c9b6SSteve Lawrence { 565efd4c9b6SSteve Lawrence char *path = ZONESTAT_EXACCT_FILE; 566efd4c9b6SSteve Lawrence int ret, state = AC_OFF; 567efd4c9b6SSteve Lawrence ac_res_t res[6]; 568efd4c9b6SSteve Lawrence char oldfile[MAXPATHLEN]; 569efd4c9b6SSteve Lawrence 570efd4c9b6SSteve Lawrence /* If accounting file is externally configured, leave it alone */ 571efd4c9b6SSteve Lawrence ret = acctctl(AC_PROC | AC_FILE_GET, oldfile, sizeof (oldfile)); 572efd4c9b6SSteve Lawrence if (ret == 0 && strcmp(oldfile, path) != 0) 573efd4c9b6SSteve Lawrence return (0); 574efd4c9b6SSteve Lawrence 575efd4c9b6SSteve Lawrence res[0].ar_id = AC_PROC_PID; 576efd4c9b6SSteve Lawrence res[0].ar_state = AC_OFF; 577efd4c9b6SSteve Lawrence res[1].ar_id = AC_PROC_ANCPID; 578efd4c9b6SSteve Lawrence res[1].ar_state = AC_OFF; 579efd4c9b6SSteve Lawrence res[2].ar_id = AC_PROC_CPU; 580efd4c9b6SSteve Lawrence res[2].ar_state = AC_OFF; 581efd4c9b6SSteve Lawrence res[3].ar_id = AC_PROC_TIME; 582efd4c9b6SSteve Lawrence res[3].ar_state = AC_OFF; 583efd4c9b6SSteve Lawrence res[4].ar_id = AC_PROC_ZONENAME; 584efd4c9b6SSteve Lawrence res[4].ar_state = AC_OFF; 585efd4c9b6SSteve Lawrence res[5].ar_id = AC_NONE; 586efd4c9b6SSteve Lawrence res[5].ar_state = AC_OFF; 587efd4c9b6SSteve Lawrence if (acctctl(AC_PROC | AC_RES_SET, res, sizeof (res)) != 0) { 588efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to clear accounting resources")); 589efd4c9b6SSteve Lawrence return (-1); 590efd4c9b6SSteve Lawrence } 591efd4c9b6SSteve Lawrence if (acctctl(AC_PROC | AC_FILE_SET, NULL, 0) == -1) { 592efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to clear accounting file")); 593efd4c9b6SSteve Lawrence return (-1); 594efd4c9b6SSteve Lawrence } 595efd4c9b6SSteve Lawrence if (acctctl(AC_PROC | AC_STATE_SET, &state, sizeof (state)) == -1) { 596efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to diable accounting")); 597efd4c9b6SSteve Lawrence return (-1); 598efd4c9b6SSteve Lawrence } 599efd4c9b6SSteve Lawrence 600efd4c9b6SSteve Lawrence (void) unlink(path); 601efd4c9b6SSteve Lawrence return (0); 602efd4c9b6SSteve Lawrence } 603efd4c9b6SSteve Lawrence 604efd4c9b6SSteve Lawrence /* 605efd4c9b6SSteve Lawrence * If not configured externally, deletes the current extended accounting file 606efd4c9b6SSteve Lawrence * and starts a new one. 607efd4c9b6SSteve Lawrence * 608efd4c9b6SSteve Lawrence * Since the stat_thread holds an open handle to the accounting file, it will 609efd4c9b6SSteve Lawrence * read all remaining entries from the old file before switching to 610efd4c9b6SSteve Lawrence * read the new one. 611efd4c9b6SSteve Lawrence */ 612efd4c9b6SSteve Lawrence int 613efd4c9b6SSteve Lawrence zsd_roll_exacct(void) 614efd4c9b6SSteve Lawrence { 615efd4c9b6SSteve Lawrence int ret; 616efd4c9b6SSteve Lawrence char *path = ZONESTAT_EXACCT_FILE; 617efd4c9b6SSteve Lawrence char oldfile[MAXPATHLEN]; 618efd4c9b6SSteve Lawrence 619efd4c9b6SSteve Lawrence /* If accounting file is externally configured, leave it alone */ 620efd4c9b6SSteve Lawrence ret = acctctl(AC_PROC | AC_FILE_GET, oldfile, sizeof (oldfile)); 621efd4c9b6SSteve Lawrence if (ret == 0 && strcmp(oldfile, path) != 0) 622efd4c9b6SSteve Lawrence return (0); 623efd4c9b6SSteve Lawrence 624efd4c9b6SSteve Lawrence if (unlink(path) != 0) 625efd4c9b6SSteve Lawrence /* Roll it next time */ 626efd4c9b6SSteve Lawrence return (0); 627efd4c9b6SSteve Lawrence 628efd4c9b6SSteve Lawrence if (acctctl(AC_PROC | AC_FILE_SET, path, strlen(path) + 1) == -1) { 629efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to set accounting file")); 630efd4c9b6SSteve Lawrence return (-1); 631efd4c9b6SSteve Lawrence } 632efd4c9b6SSteve Lawrence return (0); 633efd4c9b6SSteve Lawrence } 634efd4c9b6SSteve Lawrence 635efd4c9b6SSteve Lawrence /* Contract stuff for zone_enter() */ 636efd4c9b6SSteve Lawrence int 637efd4c9b6SSteve Lawrence init_template(void) 638efd4c9b6SSteve Lawrence { 639efd4c9b6SSteve Lawrence int fd; 640efd4c9b6SSteve Lawrence int err = 0; 641efd4c9b6SSteve Lawrence 642efd4c9b6SSteve Lawrence fd = open64(CTFS_ROOT "/process/template", O_RDWR); 643efd4c9b6SSteve Lawrence if (fd == -1) 644efd4c9b6SSteve Lawrence return (-1); 645efd4c9b6SSteve Lawrence 646efd4c9b6SSteve Lawrence /* 647efd4c9b6SSteve Lawrence * For now, zoneadmd doesn't do anything with the contract. 648efd4c9b6SSteve Lawrence * Deliver no events, don't inherit, and allow it to be orphaned. 649efd4c9b6SSteve Lawrence */ 650efd4c9b6SSteve Lawrence err |= ct_tmpl_set_critical(fd, 0); 651efd4c9b6SSteve Lawrence err |= ct_tmpl_set_informative(fd, 0); 652efd4c9b6SSteve Lawrence err |= ct_pr_tmpl_set_fatal(fd, CT_PR_EV_HWERR); 653efd4c9b6SSteve Lawrence err |= ct_pr_tmpl_set_param(fd, CT_PR_PGRPONLY | CT_PR_REGENT); 654efd4c9b6SSteve Lawrence if (err || ct_tmpl_activate(fd)) { 655efd4c9b6SSteve Lawrence (void) close(fd); 656efd4c9b6SSteve Lawrence return (-1); 657efd4c9b6SSteve Lawrence } 658efd4c9b6SSteve Lawrence 659efd4c9b6SSteve Lawrence return (fd); 660efd4c9b6SSteve Lawrence } 661efd4c9b6SSteve Lawrence 662efd4c9b6SSteve Lawrence /* 663efd4c9b6SSteve Lawrence * Contract stuff for zone_enter() 664efd4c9b6SSteve Lawrence */ 665efd4c9b6SSteve Lawrence int 666efd4c9b6SSteve Lawrence contract_latest(ctid_t *id) 667efd4c9b6SSteve Lawrence { 668efd4c9b6SSteve Lawrence int cfd, r; 669efd4c9b6SSteve Lawrence ct_stathdl_t st; 670efd4c9b6SSteve Lawrence ctid_t result; 671efd4c9b6SSteve Lawrence 672efd4c9b6SSteve Lawrence if ((cfd = open64(CTFS_ROOT "/process/latest", O_RDONLY)) == -1) 673efd4c9b6SSteve Lawrence return (errno); 674efd4c9b6SSteve Lawrence 675efd4c9b6SSteve Lawrence if ((r = ct_status_read(cfd, CTD_COMMON, &st)) != 0) { 676efd4c9b6SSteve Lawrence (void) close(cfd); 677efd4c9b6SSteve Lawrence return (r); 678efd4c9b6SSteve Lawrence } 679efd4c9b6SSteve Lawrence 680efd4c9b6SSteve Lawrence result = ct_status_get_id(st); 681efd4c9b6SSteve Lawrence ct_status_free(st); 682efd4c9b6SSteve Lawrence (void) close(cfd); 683efd4c9b6SSteve Lawrence 684efd4c9b6SSteve Lawrence *id = result; 685efd4c9b6SSteve Lawrence return (0); 686efd4c9b6SSteve Lawrence } 687efd4c9b6SSteve Lawrence 688efd4c9b6SSteve Lawrence static int 689efd4c9b6SSteve Lawrence close_on_exec(int fd) 690efd4c9b6SSteve Lawrence { 691efd4c9b6SSteve Lawrence int flags = fcntl(fd, F_GETFD, 0); 692efd4c9b6SSteve Lawrence if ((flags != -1) && (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != -1)) 693efd4c9b6SSteve Lawrence return (0); 694efd4c9b6SSteve Lawrence return (-1); 695efd4c9b6SSteve Lawrence } 696efd4c9b6SSteve Lawrence 697efd4c9b6SSteve Lawrence int 698efd4c9b6SSteve Lawrence contract_open(ctid_t ctid, const char *type, const char *file, int oflag) 699efd4c9b6SSteve Lawrence { 700efd4c9b6SSteve Lawrence char path[PATH_MAX]; 701efd4c9b6SSteve Lawrence int n, fd; 702efd4c9b6SSteve Lawrence 703efd4c9b6SSteve Lawrence if (type == NULL) 704efd4c9b6SSteve Lawrence type = "all"; 705efd4c9b6SSteve Lawrence 706efd4c9b6SSteve Lawrence n = snprintf(path, PATH_MAX, CTFS_ROOT "/%s/%ld/%s", type, ctid, file); 707efd4c9b6SSteve Lawrence if (n >= sizeof (path)) { 708efd4c9b6SSteve Lawrence errno = ENAMETOOLONG; 709efd4c9b6SSteve Lawrence return (-1); 710efd4c9b6SSteve Lawrence } 711efd4c9b6SSteve Lawrence 712efd4c9b6SSteve Lawrence fd = open64(path, oflag); 713efd4c9b6SSteve Lawrence if (fd != -1) { 714efd4c9b6SSteve Lawrence if (close_on_exec(fd) == -1) { 715efd4c9b6SSteve Lawrence int err = errno; 716efd4c9b6SSteve Lawrence (void) close(fd); 717efd4c9b6SSteve Lawrence errno = err; 718efd4c9b6SSteve Lawrence return (-1); 719efd4c9b6SSteve Lawrence } 720efd4c9b6SSteve Lawrence } 721efd4c9b6SSteve Lawrence return (fd); 722efd4c9b6SSteve Lawrence } 723efd4c9b6SSteve Lawrence 724efd4c9b6SSteve Lawrence int 725efd4c9b6SSteve Lawrence contract_abandon_id(ctid_t ctid) 726efd4c9b6SSteve Lawrence { 727efd4c9b6SSteve Lawrence int fd, err; 728efd4c9b6SSteve Lawrence 729efd4c9b6SSteve Lawrence fd = contract_open(ctid, "all", "ctl", O_WRONLY); 730efd4c9b6SSteve Lawrence if (fd == -1) 731efd4c9b6SSteve Lawrence return (errno); 732efd4c9b6SSteve Lawrence 733efd4c9b6SSteve Lawrence err = ct_ctl_abandon(fd); 734efd4c9b6SSteve Lawrence (void) close(fd); 735efd4c9b6SSteve Lawrence 736efd4c9b6SSteve Lawrence return (err); 737efd4c9b6SSteve Lawrence } 738efd4c9b6SSteve Lawrence /* 739efd4c9b6SSteve Lawrence * Attach the zsd_server to a zone. Called for each zone when zonestatd 740efd4c9b6SSteve Lawrence * starts, and for each newly booted zone when zoneadmd contacts the zsd_server 741efd4c9b6SSteve Lawrence * 742efd4c9b6SSteve Lawrence * Zone_enter is used to avoid reaching into zone to fattach door. 743efd4c9b6SSteve Lawrence */ 744efd4c9b6SSteve Lawrence static void 745efd4c9b6SSteve Lawrence zsd_fattach_zone(zoneid_t zid, int door, boolean_t detach_only) 746efd4c9b6SSteve Lawrence { 747efd4c9b6SSteve Lawrence char *path = ZS_DOOR_PATH; 748efd4c9b6SSteve Lawrence int fd, pid, stat, tmpl_fd; 749efd4c9b6SSteve Lawrence ctid_t ct; 750efd4c9b6SSteve Lawrence 751efd4c9b6SSteve Lawrence if ((tmpl_fd = init_template()) == -1) { 752efd4c9b6SSteve Lawrence zsd_warn("Unable to init template"); 753efd4c9b6SSteve Lawrence return; 754efd4c9b6SSteve Lawrence } 755efd4c9b6SSteve Lawrence 756efd4c9b6SSteve Lawrence pid = forkx(0); 757efd4c9b6SSteve Lawrence if (pid < 0) { 758efd4c9b6SSteve Lawrence (void) ct_tmpl_clear(tmpl_fd); 759efd4c9b6SSteve Lawrence zsd_warn(gettext( 760efd4c9b6SSteve Lawrence "Unable to fork to add zonestat to zoneid %d\n"), zid); 761efd4c9b6SSteve Lawrence return; 762efd4c9b6SSteve Lawrence } 763efd4c9b6SSteve Lawrence 764efd4c9b6SSteve Lawrence if (pid == 0) { 765efd4c9b6SSteve Lawrence (void) ct_tmpl_clear(tmpl_fd); 766efd4c9b6SSteve Lawrence (void) close(tmpl_fd); 767efd4c9b6SSteve Lawrence if (zid != 0 && zone_enter(zid) != 0) { 768efd4c9b6SSteve Lawrence if (errno == EINVAL) { 769efd4c9b6SSteve Lawrence _exit(0); 770efd4c9b6SSteve Lawrence } 771efd4c9b6SSteve Lawrence _exit(1); 772efd4c9b6SSteve Lawrence } 773efd4c9b6SSteve Lawrence (void) fdetach(path); 774efd4c9b6SSteve Lawrence (void) unlink(path); 775efd4c9b6SSteve Lawrence if (detach_only) 776efd4c9b6SSteve Lawrence _exit(0); 777efd4c9b6SSteve Lawrence fd = open(path, O_CREAT|O_RDWR, 0644); 778efd4c9b6SSteve Lawrence if (fd < 0) 779efd4c9b6SSteve Lawrence _exit(2); 780efd4c9b6SSteve Lawrence if (fattach(door, path) != 0) 781efd4c9b6SSteve Lawrence _exit(3); 782efd4c9b6SSteve Lawrence _exit(0); 783efd4c9b6SSteve Lawrence } 784efd4c9b6SSteve Lawrence if (contract_latest(&ct) == -1) 785efd4c9b6SSteve Lawrence ct = -1; 786efd4c9b6SSteve Lawrence (void) ct_tmpl_clear(tmpl_fd); 787efd4c9b6SSteve Lawrence (void) close(tmpl_fd); 788efd4c9b6SSteve Lawrence (void) contract_abandon_id(ct); 789efd4c9b6SSteve Lawrence while (waitpid(pid, &stat, 0) != pid) 790efd4c9b6SSteve Lawrence ; 791efd4c9b6SSteve Lawrence if (WIFEXITED(stat) && WEXITSTATUS(stat) == 0) 792efd4c9b6SSteve Lawrence return; 793efd4c9b6SSteve Lawrence 794efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to attach door to zoneid: %d"), zid); 795efd4c9b6SSteve Lawrence 796efd4c9b6SSteve Lawrence if (WEXITSTATUS(stat) == 1) 797efd4c9b6SSteve Lawrence zsd_warn(gettext("Cannot entering zone")); 798efd4c9b6SSteve Lawrence else if (WEXITSTATUS(stat) == 2) 799efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to create door file: %s"), path); 800efd4c9b6SSteve Lawrence else if (WEXITSTATUS(stat) == 3) 801efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to fattach file: %s"), path); 802efd4c9b6SSteve Lawrence 803efd4c9b6SSteve Lawrence zsd_warn(gettext("Internal error entering zone: %d"), zid); 804efd4c9b6SSteve Lawrence } 805efd4c9b6SSteve Lawrence 806efd4c9b6SSteve Lawrence /* 807efd4c9b6SSteve Lawrence * Zone lookup and allocation functions to manage list of currently running 808efd4c9b6SSteve Lawrence * zones. 809efd4c9b6SSteve Lawrence */ 810efd4c9b6SSteve Lawrence static zsd_zone_t * 811efd4c9b6SSteve Lawrence zsd_lookup_zone(zsd_ctl_t *ctl, char *zonename, zoneid_t zoneid) 812efd4c9b6SSteve Lawrence { 813efd4c9b6SSteve Lawrence zsd_zone_t *zone; 814efd4c9b6SSteve Lawrence 815efd4c9b6SSteve Lawrence for (zone = list_head(&ctl->zsctl_zones); zone != NULL; 816efd4c9b6SSteve Lawrence zone = list_next(&ctl->zsctl_zones, zone)) { 817efd4c9b6SSteve Lawrence if (strcmp(zone->zsz_name, zonename) == 0) { 818efd4c9b6SSteve Lawrence if (zoneid != -1) 819efd4c9b6SSteve Lawrence zone->zsz_id = zoneid; 820efd4c9b6SSteve Lawrence return (zone); 821efd4c9b6SSteve Lawrence } 822efd4c9b6SSteve Lawrence } 823efd4c9b6SSteve Lawrence return (NULL); 824efd4c9b6SSteve Lawrence } 825efd4c9b6SSteve Lawrence 826efd4c9b6SSteve Lawrence static zsd_zone_t * 827efd4c9b6SSteve Lawrence zsd_lookup_zone_byid(zsd_ctl_t *ctl, zoneid_t zoneid) 828efd4c9b6SSteve Lawrence { 829efd4c9b6SSteve Lawrence zsd_zone_t *zone; 830efd4c9b6SSteve Lawrence 831efd4c9b6SSteve Lawrence for (zone = list_head(&ctl->zsctl_zones); zone != NULL; 832efd4c9b6SSteve Lawrence zone = list_next(&ctl->zsctl_zones, zone)) { 833efd4c9b6SSteve Lawrence if (zone->zsz_id == zoneid) 834efd4c9b6SSteve Lawrence return (zone); 835efd4c9b6SSteve Lawrence } 836efd4c9b6SSteve Lawrence return (NULL); 837efd4c9b6SSteve Lawrence } 838efd4c9b6SSteve Lawrence 839efd4c9b6SSteve Lawrence static zsd_zone_t * 840efd4c9b6SSteve Lawrence zsd_allocate_zone(zsd_ctl_t *ctl, char *zonename, zoneid_t zoneid) 841efd4c9b6SSteve Lawrence { 842efd4c9b6SSteve Lawrence zsd_zone_t *zone; 843efd4c9b6SSteve Lawrence 844efd4c9b6SSteve Lawrence if ((zone = (zsd_zone_t *)calloc(1, sizeof (zsd_zone_t))) == NULL) 845efd4c9b6SSteve Lawrence return (NULL); 846efd4c9b6SSteve Lawrence 847efd4c9b6SSteve Lawrence (void) strlcpy(zone->zsz_name, zonename, sizeof (zone->zsz_name)); 848efd4c9b6SSteve Lawrence zone->zsz_id = zoneid; 849efd4c9b6SSteve Lawrence zone->zsz_found = B_FALSE; 850efd4c9b6SSteve Lawrence 851efd4c9b6SSteve Lawrence /* 852efd4c9b6SSteve Lawrence * Allocate as deleted so if not found in first pass, zone is deleted 853efd4c9b6SSteve Lawrence * from list. This can happen if zone is returned by zone_list, but 854efd4c9b6SSteve Lawrence * exits before first attempt to fetch zone details. 855efd4c9b6SSteve Lawrence */ 856efd4c9b6SSteve Lawrence zone->zsz_start = g_now; 857efd4c9b6SSteve Lawrence zone->zsz_hrstart = g_hrnow; 858efd4c9b6SSteve Lawrence zone->zsz_deleted = B_TRUE; 859efd4c9b6SSteve Lawrence 860efd4c9b6SSteve Lawrence zone->zsz_cpu_shares = ZS_LIMIT_NONE; 861efd4c9b6SSteve Lawrence zone->zsz_cpu_cap = ZS_LIMIT_NONE; 862efd4c9b6SSteve Lawrence zone->zsz_ram_cap = ZS_LIMIT_NONE; 863efd4c9b6SSteve Lawrence zone->zsz_locked_cap = ZS_LIMIT_NONE; 864efd4c9b6SSteve Lawrence zone->zsz_vm_cap = ZS_LIMIT_NONE; 865efd4c9b6SSteve Lawrence 866efd4c9b6SSteve Lawrence zone->zsz_processes_cap = ZS_LIMIT_NONE; 867efd4c9b6SSteve Lawrence zone->zsz_lwps_cap = ZS_LIMIT_NONE; 868efd4c9b6SSteve Lawrence zone->zsz_shm_cap = ZS_LIMIT_NONE; 869efd4c9b6SSteve Lawrence zone->zsz_shmids_cap = ZS_LIMIT_NONE; 870efd4c9b6SSteve Lawrence zone->zsz_semids_cap = ZS_LIMIT_NONE; 871efd4c9b6SSteve Lawrence zone->zsz_msgids_cap = ZS_LIMIT_NONE; 872efd4c9b6SSteve Lawrence zone->zsz_lofi_cap = ZS_LIMIT_NONE; 873efd4c9b6SSteve Lawrence 874efd4c9b6SSteve Lawrence ctl->zsctl_nzones++; 875efd4c9b6SSteve Lawrence 876efd4c9b6SSteve Lawrence return (zone); 877efd4c9b6SSteve Lawrence } 878efd4c9b6SSteve Lawrence 879efd4c9b6SSteve Lawrence static zsd_zone_t * 880efd4c9b6SSteve Lawrence zsd_lookup_insert_zone(zsd_ctl_t *ctl, char *zonename, zoneid_t zoneid) 881efd4c9b6SSteve Lawrence { 882efd4c9b6SSteve Lawrence zsd_zone_t *zone, *tmp; 883efd4c9b6SSteve Lawrence 884efd4c9b6SSteve Lawrence if ((zone = zsd_lookup_zone(ctl, zonename, zoneid)) != NULL) 885efd4c9b6SSteve Lawrence return (zone); 886efd4c9b6SSteve Lawrence 887efd4c9b6SSteve Lawrence if ((zone = zsd_allocate_zone(ctl, zonename, zoneid)) == NULL) 888efd4c9b6SSteve Lawrence return (NULL); 889efd4c9b6SSteve Lawrence 890efd4c9b6SSteve Lawrence /* Insert sorted by zonename */ 891efd4c9b6SSteve Lawrence tmp = list_head(&ctl->zsctl_zones); 892efd4c9b6SSteve Lawrence while (tmp != NULL && strcmp(zonename, tmp->zsz_name) > 0) 893efd4c9b6SSteve Lawrence tmp = list_next(&ctl->zsctl_zones, tmp); 894efd4c9b6SSteve Lawrence 895efd4c9b6SSteve Lawrence list_insert_before(&ctl->zsctl_zones, tmp, zone); 896efd4c9b6SSteve Lawrence return (zone); 897efd4c9b6SSteve Lawrence } 898efd4c9b6SSteve Lawrence 899efd4c9b6SSteve Lawrence /* 900efd4c9b6SSteve Lawrence * Mark all zones as not existing. As zones are found, they will 901efd4c9b6SSteve Lawrence * be marked as existing. If a zone is not found, then it must have 902efd4c9b6SSteve Lawrence * halted. 903efd4c9b6SSteve Lawrence */ 904efd4c9b6SSteve Lawrence static void 905efd4c9b6SSteve Lawrence zsd_mark_zones_start(zsd_ctl_t *ctl) 906efd4c9b6SSteve Lawrence { 907efd4c9b6SSteve Lawrence 908efd4c9b6SSteve Lawrence zsd_zone_t *zone; 909efd4c9b6SSteve Lawrence 910efd4c9b6SSteve Lawrence for (zone = list_head(&ctl->zsctl_zones); zone != NULL; 911efd4c9b6SSteve Lawrence zone = list_next(&ctl->zsctl_zones, zone)) { 912efd4c9b6SSteve Lawrence zone->zsz_found = B_FALSE; 913efd4c9b6SSteve Lawrence } 914efd4c9b6SSteve Lawrence } 915efd4c9b6SSteve Lawrence 916efd4c9b6SSteve Lawrence /* 917efd4c9b6SSteve Lawrence * Mark each zone as not using pset. If processes are found using the 918efd4c9b6SSteve Lawrence * pset, the zone will remain bound to the pset. If none of a zones 919efd4c9b6SSteve Lawrence * processes are bound to the pset, the zone's usage of the pset will 920efd4c9b6SSteve Lawrence * be deleted. 921efd4c9b6SSteve Lawrence * 922efd4c9b6SSteve Lawrence */ 923efd4c9b6SSteve Lawrence static void 924efd4c9b6SSteve Lawrence zsd_mark_pset_usage_start(zsd_pset_t *pset) 925efd4c9b6SSteve Lawrence { 926efd4c9b6SSteve Lawrence zsd_pset_usage_t *usage; 927efd4c9b6SSteve Lawrence 928efd4c9b6SSteve Lawrence for (usage = list_head(&pset->zsp_usage_list); 929efd4c9b6SSteve Lawrence usage != NULL; 930efd4c9b6SSteve Lawrence usage = list_next(&pset->zsp_usage_list, usage)) { 931efd4c9b6SSteve Lawrence usage->zsu_found = B_FALSE; 932efd4c9b6SSteve Lawrence usage->zsu_empty = B_TRUE; 933efd4c9b6SSteve Lawrence } 934efd4c9b6SSteve Lawrence } 935efd4c9b6SSteve Lawrence 936efd4c9b6SSteve Lawrence /* 937efd4c9b6SSteve Lawrence * Mark each pset as not existing. If a pset is found, it will be marked 938efd4c9b6SSteve Lawrence * as existing. If a pset is not found, it wil be deleted. 939efd4c9b6SSteve Lawrence */ 940efd4c9b6SSteve Lawrence static void 941efd4c9b6SSteve Lawrence zsd_mark_psets_start(zsd_ctl_t *ctl) 942efd4c9b6SSteve Lawrence { 943efd4c9b6SSteve Lawrence zsd_pset_t *pset; 944efd4c9b6SSteve Lawrence 945efd4c9b6SSteve Lawrence for (pset = list_head(&ctl->zsctl_psets); pset != NULL; 946efd4c9b6SSteve Lawrence pset = list_next(&ctl->zsctl_psets, pset)) { 947efd4c9b6SSteve Lawrence pset->zsp_found = B_FALSE; 948efd4c9b6SSteve Lawrence zsd_mark_pset_usage_start(pset); 949efd4c9b6SSteve Lawrence } 950efd4c9b6SSteve Lawrence } 951efd4c9b6SSteve Lawrence 952efd4c9b6SSteve Lawrence /* 953efd4c9b6SSteve Lawrence * A pset was found. Update its information 954efd4c9b6SSteve Lawrence */ 955efd4c9b6SSteve Lawrence static void 956efd4c9b6SSteve Lawrence zsd_mark_pset_found(zsd_pset_t *pset, uint_t type, uint64_t online, 957efd4c9b6SSteve Lawrence uint64_t size, uint64_t min, uint64_t max, int64_t importance) 958efd4c9b6SSteve Lawrence { 959efd4c9b6SSteve Lawrence pset->zsp_empty = B_TRUE; 960efd4c9b6SSteve Lawrence pset->zsp_deleted = B_FALSE; 961efd4c9b6SSteve Lawrence 962efd4c9b6SSteve Lawrence assert(pset->zsp_found == B_FALSE); 963efd4c9b6SSteve Lawrence 964efd4c9b6SSteve Lawrence /* update pset flags */ 965efd4c9b6SSteve Lawrence if (pset->zsp_active == B_FALSE) 966efd4c9b6SSteve Lawrence /* pset not seen on previous interval. It is new. */ 967efd4c9b6SSteve Lawrence pset->zsp_new = B_TRUE; 968efd4c9b6SSteve Lawrence else 969efd4c9b6SSteve Lawrence pset->zsp_new = B_FALSE; 970efd4c9b6SSteve Lawrence 971efd4c9b6SSteve Lawrence pset->zsp_found = B_TRUE; 972efd4c9b6SSteve Lawrence pset->zsp_cputype = type; 973efd4c9b6SSteve Lawrence pset->zsp_online = online; 974efd4c9b6SSteve Lawrence pset->zsp_size = size; 975efd4c9b6SSteve Lawrence pset->zsp_min = min; 976efd4c9b6SSteve Lawrence pset->zsp_max = max; 977efd4c9b6SSteve Lawrence pset->zsp_importance = importance; 978efd4c9b6SSteve Lawrence pset->zsp_cpu_shares = 0; 979efd4c9b6SSteve Lawrence pset->zsp_scheds = 0; 980efd4c9b6SSteve Lawrence pset->zsp_active = B_TRUE; 981efd4c9b6SSteve Lawrence } 982efd4c9b6SSteve Lawrence 983efd4c9b6SSteve Lawrence /* 984efd4c9b6SSteve Lawrence * A zone's process was found using a pset. Charge the process to the pset and 985efd4c9b6SSteve Lawrence * the per-zone data for the pset. 986efd4c9b6SSteve Lawrence */ 987efd4c9b6SSteve Lawrence static void 988efd4c9b6SSteve Lawrence zsd_mark_pset_usage_found(zsd_pset_usage_t *usage, uint_t sched) 989efd4c9b6SSteve Lawrence { 990efd4c9b6SSteve Lawrence zsd_zone_t *zone = usage->zsu_zone; 991efd4c9b6SSteve Lawrence zsd_pset_t *pset = usage->zsu_pset; 992efd4c9b6SSteve Lawrence 993efd4c9b6SSteve Lawrence /* Nothing to do if already found */ 994efd4c9b6SSteve Lawrence if (usage->zsu_found == B_TRUE) 995efd4c9b6SSteve Lawrence goto add_stats; 996efd4c9b6SSteve Lawrence 997efd4c9b6SSteve Lawrence usage->zsu_found = B_TRUE; 998efd4c9b6SSteve Lawrence usage->zsu_empty = B_FALSE; 999efd4c9b6SSteve Lawrence 1000efd4c9b6SSteve Lawrence usage->zsu_deleted = B_FALSE; 1001efd4c9b6SSteve Lawrence /* update usage flags */ 1002efd4c9b6SSteve Lawrence if (usage->zsu_active == B_FALSE) 1003efd4c9b6SSteve Lawrence usage->zsu_new = B_TRUE; 1004efd4c9b6SSteve Lawrence else 1005efd4c9b6SSteve Lawrence usage->zsu_new = B_FALSE; 1006efd4c9b6SSteve Lawrence 1007efd4c9b6SSteve Lawrence usage->zsu_scheds = 0; 1008efd4c9b6SSteve Lawrence usage->zsu_cpu_shares = ZS_LIMIT_NONE; 1009efd4c9b6SSteve Lawrence usage->zsu_active = B_TRUE; 1010efd4c9b6SSteve Lawrence pset->zsp_empty = B_FALSE; 1011efd4c9b6SSteve Lawrence zone->zsz_empty = B_FALSE; 1012efd4c9b6SSteve Lawrence 1013efd4c9b6SSteve Lawrence add_stats: 1014efd4c9b6SSteve Lawrence /* Detect zone's pset id, and if it is bound to multiple psets */ 1015efd4c9b6SSteve Lawrence if (zone->zsz_psetid == ZS_PSET_ERROR) 1016efd4c9b6SSteve Lawrence zone->zsz_psetid = pset->zsp_id; 1017efd4c9b6SSteve Lawrence else if (zone->zsz_psetid != pset->zsp_id) 1018efd4c9b6SSteve Lawrence zone->zsz_psetid = ZS_PSET_MULTI; 1019efd4c9b6SSteve Lawrence 1020efd4c9b6SSteve Lawrence usage->zsu_scheds |= sched; 1021efd4c9b6SSteve Lawrence pset->zsp_scheds |= sched; 1022efd4c9b6SSteve Lawrence zone->zsz_scheds |= sched; 1023efd4c9b6SSteve Lawrence 1024efd4c9b6SSteve Lawrence /* Record if FSS is co-habitating with conflicting scheduler */ 1025efd4c9b6SSteve Lawrence if ((pset->zsp_scheds & ZS_SCHED_FSS) && 1026efd4c9b6SSteve Lawrence usage->zsu_scheds & ( 1027efd4c9b6SSteve Lawrence ZS_SCHED_TS | ZS_SCHED_IA | ZS_SCHED_FX)) { 1028efd4c9b6SSteve Lawrence usage->zsu_scheds |= ZS_SCHED_CONFLICT; 1029efd4c9b6SSteve Lawrence 1030efd4c9b6SSteve Lawrence pset->zsp_scheds |= ZS_SCHED_CONFLICT; 1031efd4c9b6SSteve Lawrence } 1032efd4c9b6SSteve Lawrence 1033efd4c9b6SSteve Lawrence } 1034efd4c9b6SSteve Lawrence 1035efd4c9b6SSteve Lawrence /* Add cpu time for a process to a pset, zone, and system totals */ 1036efd4c9b6SSteve Lawrence static void 1037efd4c9b6SSteve Lawrence zsd_add_usage(zsd_ctl_t *ctl, zsd_pset_usage_t *usage, timestruc_t *delta) 1038efd4c9b6SSteve Lawrence { 1039efd4c9b6SSteve Lawrence zsd_system_t *system = ctl->zsctl_system; 1040efd4c9b6SSteve Lawrence zsd_zone_t *zone = usage->zsu_zone; 1041efd4c9b6SSteve Lawrence zsd_pset_t *pset = usage->zsu_pset; 1042efd4c9b6SSteve Lawrence 1043efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(usage->zsu_cpu_usage, *delta); 1044efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(pset->zsp_usage_zones, *delta); 1045efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(zone->zsz_cpu_usage, *delta); 1046efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(system->zss_cpu_usage_zones, *delta); 1047efd4c9b6SSteve Lawrence } 1048efd4c9b6SSteve Lawrence 1049efd4c9b6SSteve Lawrence /* Determine which processor sets have been deleted */ 1050efd4c9b6SSteve Lawrence static void 1051efd4c9b6SSteve Lawrence zsd_mark_psets_end(zsd_ctl_t *ctl) 1052efd4c9b6SSteve Lawrence { 1053efd4c9b6SSteve Lawrence zsd_pset_t *pset, *tmp; 1054efd4c9b6SSteve Lawrence 1055efd4c9b6SSteve Lawrence /* 1056efd4c9b6SSteve Lawrence * Mark pset as not exists, and deleted if it existed 1057efd4c9b6SSteve Lawrence * previous interval. 1058efd4c9b6SSteve Lawrence */ 1059efd4c9b6SSteve Lawrence pset = list_head(&ctl->zsctl_psets); 1060efd4c9b6SSteve Lawrence while (pset != NULL) { 1061efd4c9b6SSteve Lawrence if (pset->zsp_found == B_FALSE) { 1062efd4c9b6SSteve Lawrence pset->zsp_empty = B_TRUE; 1063efd4c9b6SSteve Lawrence if (pset->zsp_deleted == B_TRUE) { 1064efd4c9b6SSteve Lawrence tmp = pset; 1065efd4c9b6SSteve Lawrence pset = list_next(&ctl->zsctl_psets, pset); 1066efd4c9b6SSteve Lawrence list_remove(&ctl->zsctl_psets, tmp); 1067efd4c9b6SSteve Lawrence free(tmp); 1068efd4c9b6SSteve Lawrence ctl->zsctl_npsets--; 1069efd4c9b6SSteve Lawrence continue; 1070efd4c9b6SSteve Lawrence } else { 1071efd4c9b6SSteve Lawrence /* Pset vanished during this interval */ 1072efd4c9b6SSteve Lawrence pset->zsp_new = B_FALSE; 1073efd4c9b6SSteve Lawrence pset->zsp_deleted = B_TRUE; 1074efd4c9b6SSteve Lawrence pset->zsp_active = B_TRUE; 1075efd4c9b6SSteve Lawrence } 1076efd4c9b6SSteve Lawrence } 1077efd4c9b6SSteve Lawrence pset = list_next(&ctl->zsctl_psets, pset); 1078efd4c9b6SSteve Lawrence } 1079efd4c9b6SSteve Lawrence } 1080efd4c9b6SSteve Lawrence 1081efd4c9b6SSteve Lawrence /* Determine which zones are no longer bound to processor sets */ 1082efd4c9b6SSteve Lawrence static void 1083efd4c9b6SSteve Lawrence zsd_mark_pset_usages_end(zsd_ctl_t *ctl) 1084efd4c9b6SSteve Lawrence { 1085efd4c9b6SSteve Lawrence zsd_pset_t *pset; 1086efd4c9b6SSteve Lawrence zsd_zone_t *zone; 1087efd4c9b6SSteve Lawrence zsd_pset_usage_t *usage, *tmp; 1088efd4c9b6SSteve Lawrence 1089efd4c9b6SSteve Lawrence /* 1090efd4c9b6SSteve Lawrence * Mark pset as not exists, and deleted if it existed previous 1091efd4c9b6SSteve Lawrence * interval. 1092efd4c9b6SSteve Lawrence */ 1093efd4c9b6SSteve Lawrence for (pset = list_head(&ctl->zsctl_psets); pset != NULL; 1094efd4c9b6SSteve Lawrence pset = list_next(&ctl->zsctl_psets, pset)) { 1095efd4c9b6SSteve Lawrence usage = list_head(&pset->zsp_usage_list); 1096efd4c9b6SSteve Lawrence while (usage != NULL) { 1097efd4c9b6SSteve Lawrence /* 1098efd4c9b6SSteve Lawrence * Mark pset as not exists, and deleted if it existed 1099efd4c9b6SSteve Lawrence * previous interval. 1100efd4c9b6SSteve Lawrence */ 1101efd4c9b6SSteve Lawrence if (usage->zsu_found == B_FALSE || 1102efd4c9b6SSteve Lawrence usage->zsu_zone->zsz_deleted == B_TRUE || 1103efd4c9b6SSteve Lawrence usage->zsu_pset->zsp_deleted == B_TRUE) { 1104efd4c9b6SSteve Lawrence tmp = usage; 1105efd4c9b6SSteve Lawrence usage = list_next(&pset->zsp_usage_list, 1106efd4c9b6SSteve Lawrence usage); 1107efd4c9b6SSteve Lawrence list_remove(&pset->zsp_usage_list, tmp); 1108efd4c9b6SSteve Lawrence free(tmp); 1109efd4c9b6SSteve Lawrence pset->zsp_nusage--; 1110efd4c9b6SSteve Lawrence ctl->zsctl_npset_usages--; 1111efd4c9b6SSteve Lawrence continue; 1112efd4c9b6SSteve Lawrence } else { 1113efd4c9b6SSteve Lawrence usage->zsu_new = B_FALSE; 1114efd4c9b6SSteve Lawrence usage->zsu_deleted = B_TRUE; 1115efd4c9b6SSteve Lawrence usage->zsu_active = B_TRUE; 1116efd4c9b6SSteve Lawrence } 1117efd4c9b6SSteve Lawrence /* Add cpu shares for usages that are in FSS */ 1118efd4c9b6SSteve Lawrence zone = usage->zsu_zone; 1119efd4c9b6SSteve Lawrence if (usage->zsu_scheds & ZS_SCHED_FSS && 1120efd4c9b6SSteve Lawrence zone->zsz_cpu_shares != ZS_SHARES_UNLIMITED && 1121efd4c9b6SSteve Lawrence zone->zsz_cpu_shares != 0) { 1122efd4c9b6SSteve Lawrence zone = usage->zsu_zone; 1123efd4c9b6SSteve Lawrence usage->zsu_cpu_shares = zone->zsz_cpu_shares; 1124efd4c9b6SSteve Lawrence pset->zsp_cpu_shares += zone->zsz_cpu_shares; 1125efd4c9b6SSteve Lawrence } 1126efd4c9b6SSteve Lawrence usage = list_next(&pset->zsp_usage_list, 1127efd4c9b6SSteve Lawrence usage); 1128efd4c9b6SSteve Lawrence } 1129efd4c9b6SSteve Lawrence } 1130efd4c9b6SSteve Lawrence } 1131efd4c9b6SSteve Lawrence 1132efd4c9b6SSteve Lawrence /* A zone has been found. Update its information */ 1133efd4c9b6SSteve Lawrence static void 1134efd4c9b6SSteve Lawrence zsd_mark_zone_found(zsd_ctl_t *ctl, zsd_zone_t *zone, uint64_t cpu_shares, 1135efd4c9b6SSteve Lawrence uint64_t cpu_cap, uint64_t ram_cap, uint64_t locked_cap, 1136efd4c9b6SSteve Lawrence uint64_t vm_cap, uint64_t processes_cap, uint64_t processes, 1137efd4c9b6SSteve Lawrence uint64_t lwps_cap, uint64_t lwps, uint64_t shm_cap, uint64_t shm, 1138efd4c9b6SSteve Lawrence uint64_t shmids_cap, uint64_t shmids, uint64_t semids_cap, 1139efd4c9b6SSteve Lawrence uint64_t semids, uint64_t msgids_cap, uint64_t msgids, uint64_t lofi_cap, 1140efd4c9b6SSteve Lawrence uint64_t lofi, char *poolname, char *psetname, uint_t sched, uint_t cputype, 1141efd4c9b6SSteve Lawrence uint_t iptype) 1142efd4c9b6SSteve Lawrence { 1143efd4c9b6SSteve Lawrence zsd_system_t *sys = ctl->zsctl_system; 1144efd4c9b6SSteve Lawrence 1145efd4c9b6SSteve Lawrence assert(zone->zsz_found == B_FALSE); 1146efd4c9b6SSteve Lawrence 1147efd4c9b6SSteve Lawrence /* 1148efd4c9b6SSteve Lawrence * Mark zone as exists, and new if it did not exist in previous 1149efd4c9b6SSteve Lawrence * interval. 1150efd4c9b6SSteve Lawrence */ 1151efd4c9b6SSteve Lawrence zone->zsz_found = B_TRUE; 1152efd4c9b6SSteve Lawrence zone->zsz_empty = B_TRUE; 1153efd4c9b6SSteve Lawrence zone->zsz_deleted = B_FALSE; 1154efd4c9b6SSteve Lawrence 1155efd4c9b6SSteve Lawrence /* 1156efd4c9b6SSteve Lawrence * Zone is new. Assume zone's properties are the same over entire 1157efd4c9b6SSteve Lawrence * interval. 1158efd4c9b6SSteve Lawrence */ 1159efd4c9b6SSteve Lawrence if (zone->zsz_active == B_FALSE) 1160efd4c9b6SSteve Lawrence zone->zsz_new = B_TRUE; 1161efd4c9b6SSteve Lawrence else 1162efd4c9b6SSteve Lawrence zone->zsz_new = B_FALSE; 1163efd4c9b6SSteve Lawrence 1164efd4c9b6SSteve Lawrence (void) strlcpy(zone->zsz_pool, poolname, sizeof (zone->zsz_pool)); 1165efd4c9b6SSteve Lawrence (void) strlcpy(zone->zsz_pset, psetname, sizeof (zone->zsz_pset)); 1166efd4c9b6SSteve Lawrence zone->zsz_default_sched = sched; 1167efd4c9b6SSteve Lawrence 1168efd4c9b6SSteve Lawrence /* Schedulers updated later as processes are found */ 1169efd4c9b6SSteve Lawrence zone->zsz_scheds = 0; 1170efd4c9b6SSteve Lawrence 1171efd4c9b6SSteve Lawrence /* Cpus updated later as psets bound are identified */ 1172efd4c9b6SSteve Lawrence zone->zsz_cpus_online = 0; 1173efd4c9b6SSteve Lawrence 1174efd4c9b6SSteve Lawrence zone->zsz_cputype = cputype; 1175efd4c9b6SSteve Lawrence zone->zsz_iptype = iptype; 1176efd4c9b6SSteve Lawrence zone->zsz_psetid = ZS_PSET_ERROR; 1177efd4c9b6SSteve Lawrence zone->zsz_cpu_cap = cpu_cap; 1178efd4c9b6SSteve Lawrence zone->zsz_cpu_shares = cpu_shares; 1179efd4c9b6SSteve Lawrence zone->zsz_ram_cap = ram_cap; 1180efd4c9b6SSteve Lawrence zone->zsz_locked_cap = locked_cap; 1181efd4c9b6SSteve Lawrence zone->zsz_vm_cap = vm_cap; 1182efd4c9b6SSteve Lawrence zone->zsz_processes_cap = processes_cap; 1183efd4c9b6SSteve Lawrence zone->zsz_processes = processes; 1184efd4c9b6SSteve Lawrence zone->zsz_lwps_cap = lwps_cap; 1185efd4c9b6SSteve Lawrence zone->zsz_lwps = lwps; 1186efd4c9b6SSteve Lawrence zone->zsz_shm_cap = shm_cap; 1187efd4c9b6SSteve Lawrence zone->zsz_shm = shm; 1188efd4c9b6SSteve Lawrence zone->zsz_shmids_cap = shmids_cap; 1189efd4c9b6SSteve Lawrence zone->zsz_shmids = shmids; 1190efd4c9b6SSteve Lawrence zone->zsz_semids_cap = semids_cap; 1191efd4c9b6SSteve Lawrence zone->zsz_semids = semids; 1192efd4c9b6SSteve Lawrence zone->zsz_msgids_cap = msgids_cap; 1193efd4c9b6SSteve Lawrence zone->zsz_msgids = msgids; 1194efd4c9b6SSteve Lawrence zone->zsz_lofi_cap = lofi_cap; 1195efd4c9b6SSteve Lawrence zone->zsz_lofi = lofi; 1196efd4c9b6SSteve Lawrence 1197efd4c9b6SSteve Lawrence sys->zss_processes += processes; 1198efd4c9b6SSteve Lawrence sys->zss_lwps += lwps; 1199efd4c9b6SSteve Lawrence sys->zss_shm += shm; 1200efd4c9b6SSteve Lawrence sys->zss_shmids += shmids; 1201efd4c9b6SSteve Lawrence sys->zss_semids += semids; 1202efd4c9b6SSteve Lawrence sys->zss_msgids += msgids; 1203efd4c9b6SSteve Lawrence sys->zss_lofi += lofi; 1204efd4c9b6SSteve Lawrence zone->zsz_active = B_TRUE; 1205efd4c9b6SSteve Lawrence } 1206efd4c9b6SSteve Lawrence 1207efd4c9b6SSteve Lawrence 1208efd4c9b6SSteve Lawrence /* Determine which zones have halted */ 1209efd4c9b6SSteve Lawrence static void 1210efd4c9b6SSteve Lawrence zsd_mark_zones_end(zsd_ctl_t *ctl) 1211efd4c9b6SSteve Lawrence { 1212efd4c9b6SSteve Lawrence zsd_zone_t *zone, *tmp; 1213efd4c9b6SSteve Lawrence 1214efd4c9b6SSteve Lawrence /* 1215efd4c9b6SSteve Lawrence * Mark zone as not existing, or delete if it did not exist in 1216efd4c9b6SSteve Lawrence * previous interval. 1217efd4c9b6SSteve Lawrence */ 1218efd4c9b6SSteve Lawrence zone = list_head(&ctl->zsctl_zones); 1219efd4c9b6SSteve Lawrence while (zone != NULL) { 1220efd4c9b6SSteve Lawrence if (zone->zsz_found == B_FALSE) { 1221efd4c9b6SSteve Lawrence zone->zsz_empty = B_TRUE; 1222efd4c9b6SSteve Lawrence if (zone->zsz_deleted == B_TRUE) { 1223efd4c9b6SSteve Lawrence /* 1224efd4c9b6SSteve Lawrence * Zone deleted in prior interval, 1225efd4c9b6SSteve Lawrence * so it no longer exists. 1226efd4c9b6SSteve Lawrence */ 1227efd4c9b6SSteve Lawrence tmp = zone; 1228efd4c9b6SSteve Lawrence zone = list_next(&ctl->zsctl_zones, zone); 1229efd4c9b6SSteve Lawrence list_remove(&ctl->zsctl_zones, tmp); 1230efd4c9b6SSteve Lawrence free(tmp); 1231efd4c9b6SSteve Lawrence ctl->zsctl_nzones--; 1232efd4c9b6SSteve Lawrence continue; 1233efd4c9b6SSteve Lawrence } else { 1234efd4c9b6SSteve Lawrence zone->zsz_new = B_FALSE; 1235efd4c9b6SSteve Lawrence zone->zsz_deleted = B_TRUE; 1236efd4c9b6SSteve Lawrence zone->zsz_active = B_TRUE; 1237efd4c9b6SSteve Lawrence } 1238efd4c9b6SSteve Lawrence } 1239efd4c9b6SSteve Lawrence zone = list_next(&ctl->zsctl_zones, zone); 1240efd4c9b6SSteve Lawrence } 1241efd4c9b6SSteve Lawrence } 1242efd4c9b6SSteve Lawrence 1243efd4c9b6SSteve Lawrence /* 1244efd4c9b6SSteve Lawrence * Mark cpus as not existing. If a cpu is found, it will be updated. If 1245efd4c9b6SSteve Lawrence * a cpu is not found, then it must have gone offline, so it will be 1246efd4c9b6SSteve Lawrence * deleted. 1247efd4c9b6SSteve Lawrence * 1248efd4c9b6SSteve Lawrence * The kstat tracking data is rolled so that the usage since the previous 1249efd4c9b6SSteve Lawrence * interval can be determined. 1250efd4c9b6SSteve Lawrence */ 1251efd4c9b6SSteve Lawrence static void 1252efd4c9b6SSteve Lawrence zsd_mark_cpus_start(zsd_ctl_t *ctl, boolean_t roll) 1253efd4c9b6SSteve Lawrence { 1254efd4c9b6SSteve Lawrence zsd_cpu_t *cpu; 1255efd4c9b6SSteve Lawrence 1256efd4c9b6SSteve Lawrence /* 1257efd4c9b6SSteve Lawrence * Mark all cpus as not existing. As cpus are found, they will 1258efd4c9b6SSteve Lawrence * be marked as existing. 1259efd4c9b6SSteve Lawrence */ 1260efd4c9b6SSteve Lawrence for (cpu = list_head(&ctl->zsctl_cpus); cpu != NULL; 1261efd4c9b6SSteve Lawrence cpu = list_next(&ctl->zsctl_cpus, cpu)) { 1262efd4c9b6SSteve Lawrence cpu->zsc_found = B_FALSE; 1263efd4c9b6SSteve Lawrence if (cpu->zsc_active == B_TRUE && roll) { 1264efd4c9b6SSteve Lawrence cpu->zsc_psetid_prev = cpu->zsc_psetid; 1265efd4c9b6SSteve Lawrence cpu->zsc_nsec_idle_prev = cpu->zsc_nsec_idle; 1266efd4c9b6SSteve Lawrence cpu->zsc_nsec_intr_prev = cpu->zsc_nsec_intr; 1267efd4c9b6SSteve Lawrence cpu->zsc_nsec_kern_prev = cpu->zsc_nsec_kern; 1268efd4c9b6SSteve Lawrence cpu->zsc_nsec_user_prev = cpu->zsc_nsec_user; 1269efd4c9b6SSteve Lawrence } 1270efd4c9b6SSteve Lawrence } 1271efd4c9b6SSteve Lawrence } 1272efd4c9b6SSteve Lawrence 1273efd4c9b6SSteve Lawrence /* 1274efd4c9b6SSteve Lawrence * An array the size of the maximum number of cpus is kept. Within this array 1275efd4c9b6SSteve Lawrence * a list of the online cpus is maintained. 1276efd4c9b6SSteve Lawrence */ 1277efd4c9b6SSteve Lawrence zsd_cpu_t * 1278efd4c9b6SSteve Lawrence zsd_lookup_insert_cpu(zsd_ctl_t *ctl, processorid_t cpuid) 1279efd4c9b6SSteve Lawrence { 1280efd4c9b6SSteve Lawrence zsd_cpu_t *cpu; 1281efd4c9b6SSteve Lawrence 1282efd4c9b6SSteve Lawrence assert(cpuid < ctl->zsctl_maxcpuid); 1283efd4c9b6SSteve Lawrence cpu = &(ctl->zsctl_cpu_array[cpuid]); 1284efd4c9b6SSteve Lawrence assert(cpuid == cpu->zsc_id); 1285efd4c9b6SSteve Lawrence 1286efd4c9b6SSteve Lawrence if (cpu->zsc_allocated == B_FALSE) { 1287efd4c9b6SSteve Lawrence cpu->zsc_allocated = B_TRUE; 1288efd4c9b6SSteve Lawrence list_insert_tail(&ctl->zsctl_cpus, cpu); 1289efd4c9b6SSteve Lawrence } 1290efd4c9b6SSteve Lawrence return (cpu); 1291efd4c9b6SSteve Lawrence } 1292efd4c9b6SSteve Lawrence 1293efd4c9b6SSteve Lawrence /* A cpu has been found. Update its information */ 1294efd4c9b6SSteve Lawrence static void 1295efd4c9b6SSteve Lawrence zsd_mark_cpu_found(zsd_cpu_t *cpu, zsd_pset_t *pset, psetid_t psetid) 1296efd4c9b6SSteve Lawrence { 1297efd4c9b6SSteve Lawrence /* 1298efd4c9b6SSteve Lawrence * legacy processor sets, the cpu may move while zonestatd is 1299efd4c9b6SSteve Lawrence * inspecting, causing it to be found twice. In this case, just 1300efd4c9b6SSteve Lawrence * leave cpu in the first processor set in which it was found. 1301efd4c9b6SSteve Lawrence */ 1302efd4c9b6SSteve Lawrence if (cpu->zsc_found == B_TRUE) 1303efd4c9b6SSteve Lawrence return; 1304efd4c9b6SSteve Lawrence 1305efd4c9b6SSteve Lawrence /* Mark cpu as online */ 1306efd4c9b6SSteve Lawrence cpu->zsc_found = B_TRUE; 1307efd4c9b6SSteve Lawrence cpu->zsc_offlined = B_FALSE; 1308efd4c9b6SSteve Lawrence cpu->zsc_pset = pset; 1309efd4c9b6SSteve Lawrence /* 1310efd4c9b6SSteve Lawrence * cpu is newly online. 1311efd4c9b6SSteve Lawrence */ 1312efd4c9b6SSteve Lawrence if (cpu->zsc_active == B_FALSE) { 1313efd4c9b6SSteve Lawrence /* 1314efd4c9b6SSteve Lawrence * Cpu is newly online. 1315efd4c9b6SSteve Lawrence */ 1316efd4c9b6SSteve Lawrence cpu->zsc_onlined = B_TRUE; 1317efd4c9b6SSteve Lawrence cpu->zsc_psetid = psetid; 1318efd4c9b6SSteve Lawrence cpu->zsc_psetid_prev = psetid; 1319efd4c9b6SSteve Lawrence } else { 1320efd4c9b6SSteve Lawrence /* 1321efd4c9b6SSteve Lawrence * cpu online during previous interval. Save properties at 1322efd4c9b6SSteve Lawrence * start of interval 1323efd4c9b6SSteve Lawrence */ 1324efd4c9b6SSteve Lawrence cpu->zsc_onlined = B_FALSE; 1325efd4c9b6SSteve Lawrence cpu->zsc_psetid = psetid; 1326efd4c9b6SSteve Lawrence 1327efd4c9b6SSteve Lawrence } 1328efd4c9b6SSteve Lawrence cpu->zsc_active = B_TRUE; 1329efd4c9b6SSteve Lawrence } 1330efd4c9b6SSteve Lawrence 1331efd4c9b6SSteve Lawrence /* Remove all offlined cpus from the list of tracked cpus */ 1332efd4c9b6SSteve Lawrence static void 1333efd4c9b6SSteve Lawrence zsd_mark_cpus_end(zsd_ctl_t *ctl) 1334efd4c9b6SSteve Lawrence { 1335efd4c9b6SSteve Lawrence zsd_cpu_t *cpu, *tmp; 1336efd4c9b6SSteve Lawrence int id; 1337efd4c9b6SSteve Lawrence 1338efd4c9b6SSteve Lawrence /* Mark cpu as online or offline */ 1339efd4c9b6SSteve Lawrence cpu = list_head(&ctl->zsctl_cpus); 1340efd4c9b6SSteve Lawrence while (cpu != NULL) { 1341efd4c9b6SSteve Lawrence if (cpu->zsc_found == B_FALSE) { 1342efd4c9b6SSteve Lawrence if (cpu->zsc_offlined == B_TRUE) { 1343efd4c9b6SSteve Lawrence /* 1344efd4c9b6SSteve Lawrence * cpu offlined in prior interval. It is gone. 1345efd4c9b6SSteve Lawrence */ 1346efd4c9b6SSteve Lawrence tmp = cpu; 1347efd4c9b6SSteve Lawrence cpu = list_next(&ctl->zsctl_cpus, cpu); 1348efd4c9b6SSteve Lawrence list_remove(&ctl->zsctl_cpus, tmp); 1349efd4c9b6SSteve Lawrence /* Clear structure for future use */ 1350efd4c9b6SSteve Lawrence id = tmp->zsc_id; 1351efd4c9b6SSteve Lawrence bzero(tmp, sizeof (zsd_cpu_t)); 1352efd4c9b6SSteve Lawrence tmp->zsc_id = id; 1353efd4c9b6SSteve Lawrence tmp->zsc_allocated = B_FALSE; 1354efd4c9b6SSteve Lawrence tmp->zsc_psetid = ZS_PSET_ERROR; 1355efd4c9b6SSteve Lawrence tmp->zsc_psetid_prev = ZS_PSET_ERROR; 1356efd4c9b6SSteve Lawrence 1357efd4c9b6SSteve Lawrence } else { 1358efd4c9b6SSteve Lawrence /* 1359efd4c9b6SSteve Lawrence * cpu online at start of interval. Treat 1360efd4c9b6SSteve Lawrence * as still online, since it was online for 1361efd4c9b6SSteve Lawrence * some portion of the interval. 1362efd4c9b6SSteve Lawrence */ 1363efd4c9b6SSteve Lawrence cpu->zsc_offlined = B_TRUE; 1364efd4c9b6SSteve Lawrence cpu->zsc_onlined = B_FALSE; 1365efd4c9b6SSteve Lawrence cpu->zsc_active = B_TRUE; 1366efd4c9b6SSteve Lawrence cpu->zsc_psetid = cpu->zsc_psetid_prev; 1367efd4c9b6SSteve Lawrence cpu->zsc_pset = NULL; 1368efd4c9b6SSteve Lawrence } 1369efd4c9b6SSteve Lawrence } 1370efd4c9b6SSteve Lawrence cpu = list_next(&ctl->zsctl_cpus, cpu); 1371efd4c9b6SSteve Lawrence } 1372efd4c9b6SSteve Lawrence } 1373efd4c9b6SSteve Lawrence 1374efd4c9b6SSteve Lawrence /* Some utility functions for managing the list of processor sets */ 1375efd4c9b6SSteve Lawrence static zsd_pset_t * 1376efd4c9b6SSteve Lawrence zsd_lookup_pset_byid(zsd_ctl_t *ctl, psetid_t psetid) 1377efd4c9b6SSteve Lawrence { 1378efd4c9b6SSteve Lawrence zsd_pset_t *pset; 1379efd4c9b6SSteve Lawrence 1380efd4c9b6SSteve Lawrence for (pset = list_head(&ctl->zsctl_psets); pset != NULL; 1381efd4c9b6SSteve Lawrence pset = list_next(&ctl->zsctl_psets, pset)) { 1382efd4c9b6SSteve Lawrence if (pset->zsp_id == psetid) 1383efd4c9b6SSteve Lawrence return (pset); 1384efd4c9b6SSteve Lawrence } 1385efd4c9b6SSteve Lawrence return (NULL); 1386efd4c9b6SSteve Lawrence } 1387efd4c9b6SSteve Lawrence 1388efd4c9b6SSteve Lawrence static zsd_pset_t * 1389efd4c9b6SSteve Lawrence zsd_lookup_pset(zsd_ctl_t *ctl, char *psetname, psetid_t psetid) 1390efd4c9b6SSteve Lawrence { 1391efd4c9b6SSteve Lawrence zsd_pset_t *pset; 1392efd4c9b6SSteve Lawrence 1393efd4c9b6SSteve Lawrence for (pset = list_head(&ctl->zsctl_psets); pset != NULL; 1394efd4c9b6SSteve Lawrence pset = list_next(&ctl->zsctl_psets, pset)) { 1395efd4c9b6SSteve Lawrence if (strcmp(pset->zsp_name, psetname) == 0) { 1396efd4c9b6SSteve Lawrence if (psetid != -1) 1397efd4c9b6SSteve Lawrence pset->zsp_id = psetid; 1398efd4c9b6SSteve Lawrence return (pset); 1399efd4c9b6SSteve Lawrence } 1400efd4c9b6SSteve Lawrence } 1401efd4c9b6SSteve Lawrence return (NULL); 1402efd4c9b6SSteve Lawrence } 1403efd4c9b6SSteve Lawrence 1404efd4c9b6SSteve Lawrence static zsd_pset_t * 1405efd4c9b6SSteve Lawrence zsd_allocate_pset(zsd_ctl_t *ctl, char *psetname, psetid_t psetid) 1406efd4c9b6SSteve Lawrence { 1407efd4c9b6SSteve Lawrence zsd_pset_t *pset; 1408efd4c9b6SSteve Lawrence 1409efd4c9b6SSteve Lawrence if ((pset = (zsd_pset_t *)calloc(1, sizeof (zsd_pset_t))) == NULL) 1410efd4c9b6SSteve Lawrence return (NULL); 1411efd4c9b6SSteve Lawrence 1412efd4c9b6SSteve Lawrence (void) strlcpy(pset->zsp_name, psetname, sizeof (pset->zsp_name)); 1413efd4c9b6SSteve Lawrence pset->zsp_id = psetid; 1414efd4c9b6SSteve Lawrence pset->zsp_found = B_FALSE; 1415efd4c9b6SSteve Lawrence /* 1416efd4c9b6SSteve Lawrence * Allocate as deleted so if not found in first pass, pset is deleted 1417efd4c9b6SSteve Lawrence * from list. This can happen if pset is returned by pset_list, but 1418efd4c9b6SSteve Lawrence * is destroyed before first attempt to fetch pset details. 1419efd4c9b6SSteve Lawrence */ 1420efd4c9b6SSteve Lawrence list_create(&pset->zsp_usage_list, sizeof (zsd_pset_usage_t), 1421efd4c9b6SSteve Lawrence offsetof(zsd_pset_usage_t, zsu_next)); 1422efd4c9b6SSteve Lawrence 1423efd4c9b6SSteve Lawrence pset->zsp_hrstart = g_hrnow; 1424efd4c9b6SSteve Lawrence pset->zsp_deleted = B_TRUE; 1425efd4c9b6SSteve Lawrence pset->zsp_empty = B_TRUE; 1426efd4c9b6SSteve Lawrence ctl->zsctl_npsets++; 1427efd4c9b6SSteve Lawrence 1428efd4c9b6SSteve Lawrence return (pset); 1429efd4c9b6SSteve Lawrence } 1430efd4c9b6SSteve Lawrence 1431efd4c9b6SSteve Lawrence static zsd_pset_t * 1432efd4c9b6SSteve Lawrence zsd_lookup_insert_pset(zsd_ctl_t *ctl, char *psetname, psetid_t psetid) 1433efd4c9b6SSteve Lawrence { 1434efd4c9b6SSteve Lawrence zsd_pset_t *pset, *tmp; 1435efd4c9b6SSteve Lawrence 1436efd4c9b6SSteve Lawrence if ((pset = zsd_lookup_pset(ctl, psetname, psetid)) != NULL) 1437efd4c9b6SSteve Lawrence return (pset); 1438efd4c9b6SSteve Lawrence 1439efd4c9b6SSteve Lawrence if ((pset = zsd_allocate_pset(ctl, psetname, psetid)) == NULL) 1440efd4c9b6SSteve Lawrence return (NULL); 1441efd4c9b6SSteve Lawrence 1442efd4c9b6SSteve Lawrence /* Insert sorted by psetname */ 1443efd4c9b6SSteve Lawrence tmp = list_head(&ctl->zsctl_psets); 1444efd4c9b6SSteve Lawrence while (tmp != NULL && strcmp(psetname, tmp->zsp_name) > 0) 1445efd4c9b6SSteve Lawrence tmp = list_next(&ctl->zsctl_psets, tmp); 1446efd4c9b6SSteve Lawrence 1447efd4c9b6SSteve Lawrence list_insert_before(&ctl->zsctl_psets, tmp, pset); 1448efd4c9b6SSteve Lawrence return (pset); 1449efd4c9b6SSteve Lawrence } 1450efd4c9b6SSteve Lawrence 1451efd4c9b6SSteve Lawrence /* Some utility functions for managing the list of zones using each pset */ 1452efd4c9b6SSteve Lawrence static zsd_pset_usage_t * 1453efd4c9b6SSteve Lawrence zsd_lookup_usage(zsd_pset_t *pset, zsd_zone_t *zone) 1454efd4c9b6SSteve Lawrence { 1455efd4c9b6SSteve Lawrence zsd_pset_usage_t *usage; 1456efd4c9b6SSteve Lawrence 1457efd4c9b6SSteve Lawrence for (usage = list_head(&pset->zsp_usage_list); usage != NULL; 1458efd4c9b6SSteve Lawrence usage = list_next(&pset->zsp_usage_list, usage)) 1459efd4c9b6SSteve Lawrence if (usage->zsu_zone == zone) 1460efd4c9b6SSteve Lawrence return (usage); 1461efd4c9b6SSteve Lawrence 1462efd4c9b6SSteve Lawrence return (NULL); 1463efd4c9b6SSteve Lawrence } 1464efd4c9b6SSteve Lawrence 1465efd4c9b6SSteve Lawrence static zsd_pset_usage_t * 1466efd4c9b6SSteve Lawrence zsd_allocate_pset_usage(zsd_ctl_t *ctl, zsd_pset_t *pset, zsd_zone_t *zone) 1467efd4c9b6SSteve Lawrence { 1468efd4c9b6SSteve Lawrence zsd_pset_usage_t *usage; 1469efd4c9b6SSteve Lawrence 1470efd4c9b6SSteve Lawrence if ((usage = (zsd_pset_usage_t *)calloc(1, sizeof (zsd_pset_usage_t))) 1471efd4c9b6SSteve Lawrence == NULL) 1472efd4c9b6SSteve Lawrence return (NULL); 1473efd4c9b6SSteve Lawrence 1474efd4c9b6SSteve Lawrence list_link_init(&usage->zsu_next); 1475efd4c9b6SSteve Lawrence usage->zsu_zone = zone; 1476efd4c9b6SSteve Lawrence usage->zsu_zoneid = zone->zsz_id; 1477efd4c9b6SSteve Lawrence usage->zsu_pset = pset; 1478efd4c9b6SSteve Lawrence usage->zsu_found = B_FALSE; 1479efd4c9b6SSteve Lawrence usage->zsu_active = B_FALSE; 1480efd4c9b6SSteve Lawrence usage->zsu_new = B_FALSE; 1481efd4c9b6SSteve Lawrence /* 1482efd4c9b6SSteve Lawrence * Allocate as not deleted. If a process is found in a pset for 1483efd4c9b6SSteve Lawrence * a zone, the usage will not be deleted until at least the next 1484efd4c9b6SSteve Lawrence * interval. 1485efd4c9b6SSteve Lawrence */ 1486efd4c9b6SSteve Lawrence usage->zsu_start = g_now; 1487efd4c9b6SSteve Lawrence usage->zsu_hrstart = g_hrnow; 1488efd4c9b6SSteve Lawrence usage->zsu_deleted = B_FALSE; 1489efd4c9b6SSteve Lawrence usage->zsu_empty = B_TRUE; 1490efd4c9b6SSteve Lawrence usage->zsu_scheds = 0; 1491efd4c9b6SSteve Lawrence usage->zsu_cpu_shares = ZS_LIMIT_NONE; 1492efd4c9b6SSteve Lawrence 1493efd4c9b6SSteve Lawrence ctl->zsctl_npset_usages++; 1494efd4c9b6SSteve Lawrence pset->zsp_nusage++; 1495efd4c9b6SSteve Lawrence 1496efd4c9b6SSteve Lawrence return (usage); 1497efd4c9b6SSteve Lawrence } 1498efd4c9b6SSteve Lawrence 1499efd4c9b6SSteve Lawrence static zsd_pset_usage_t * 1500efd4c9b6SSteve Lawrence zsd_lookup_insert_usage(zsd_ctl_t *ctl, zsd_pset_t *pset, zsd_zone_t *zone) 1501efd4c9b6SSteve Lawrence { 1502efd4c9b6SSteve Lawrence zsd_pset_usage_t *usage, *tmp; 1503efd4c9b6SSteve Lawrence 1504efd4c9b6SSteve Lawrence if ((usage = zsd_lookup_usage(pset, zone)) 1505efd4c9b6SSteve Lawrence != NULL) 1506efd4c9b6SSteve Lawrence return (usage); 1507efd4c9b6SSteve Lawrence 1508efd4c9b6SSteve Lawrence if ((usage = zsd_allocate_pset_usage(ctl, pset, zone)) == NULL) 1509efd4c9b6SSteve Lawrence return (NULL); 1510efd4c9b6SSteve Lawrence 1511efd4c9b6SSteve Lawrence tmp = list_head(&pset->zsp_usage_list); 1512efd4c9b6SSteve Lawrence while (tmp != NULL && strcmp(zone->zsz_name, tmp->zsu_zone->zsz_name) 1513efd4c9b6SSteve Lawrence > 0) 1514efd4c9b6SSteve Lawrence tmp = list_next(&pset->zsp_usage_list, tmp); 1515efd4c9b6SSteve Lawrence 1516efd4c9b6SSteve Lawrence list_insert_before(&pset->zsp_usage_list, tmp, usage); 1517efd4c9b6SSteve Lawrence return (usage); 1518efd4c9b6SSteve Lawrence } 1519efd4c9b6SSteve Lawrence 1520efd4c9b6SSteve Lawrence static void 1521efd4c9b6SSteve Lawrence zsd_refresh_system(zsd_ctl_t *ctl) 1522efd4c9b6SSteve Lawrence { 1523efd4c9b6SSteve Lawrence zsd_system_t *system = ctl->zsctl_system; 1524efd4c9b6SSteve Lawrence 1525efd4c9b6SSteve Lawrence /* Re-count these values each interval */ 1526efd4c9b6SSteve Lawrence system->zss_processes = 0; 1527efd4c9b6SSteve Lawrence system->zss_lwps = 0; 1528efd4c9b6SSteve Lawrence system->zss_shm = 0; 1529efd4c9b6SSteve Lawrence system->zss_shmids = 0; 1530efd4c9b6SSteve Lawrence system->zss_semids = 0; 1531efd4c9b6SSteve Lawrence system->zss_msgids = 0; 1532efd4c9b6SSteve Lawrence system->zss_lofi = 0; 1533efd4c9b6SSteve Lawrence } 1534efd4c9b6SSteve Lawrence 1535efd4c9b6SSteve Lawrence 1536efd4c9b6SSteve Lawrence /* Reads each cpu's kstats, and adds the usage to the cpu's pset */ 1537efd4c9b6SSteve Lawrence static void 1538efd4c9b6SSteve Lawrence zsd_update_cpu_stats(zsd_ctl_t *ctl, zsd_cpu_t *cpu) 1539efd4c9b6SSteve Lawrence { 1540efd4c9b6SSteve Lawrence zsd_system_t *sys; 1541efd4c9b6SSteve Lawrence processorid_t cpuid; 1542efd4c9b6SSteve Lawrence zsd_pset_t *pset_prev; 1543efd4c9b6SSteve Lawrence zsd_pset_t *pset; 1544efd4c9b6SSteve Lawrence kstat_t *kstat; 1545efd4c9b6SSteve Lawrence kstat_named_t *knp; 1546efd4c9b6SSteve Lawrence kid_t kid; 1547efd4c9b6SSteve Lawrence uint64_t idle, intr, kern, user; 1548efd4c9b6SSteve Lawrence 1549efd4c9b6SSteve Lawrence sys = ctl->zsctl_system; 1550efd4c9b6SSteve Lawrence pset = cpu->zsc_pset; 1551efd4c9b6SSteve Lawrence knp = NULL; 1552efd4c9b6SSteve Lawrence kid = -1; 1553efd4c9b6SSteve Lawrence cpuid = cpu->zsc_id; 1554efd4c9b6SSteve Lawrence 1555efd4c9b6SSteve Lawrence /* Get the cpu time totals for this cpu */ 1556efd4c9b6SSteve Lawrence kstat = kstat_lookup(ctl->zsctl_kstat_ctl, "cpu", cpuid, "sys"); 1557efd4c9b6SSteve Lawrence if (kstat == NULL) 1558efd4c9b6SSteve Lawrence return; 1559efd4c9b6SSteve Lawrence 1560efd4c9b6SSteve Lawrence kid = kstat_read(ctl->zsctl_kstat_ctl, kstat, NULL); 1561efd4c9b6SSteve Lawrence if (kid == -1) 1562efd4c9b6SSteve Lawrence return; 1563efd4c9b6SSteve Lawrence 1564efd4c9b6SSteve Lawrence knp = kstat_data_lookup(kstat, "cpu_nsec_idle"); 1565efd4c9b6SSteve Lawrence if (knp == NULL || knp->data_type != KSTAT_DATA_UINT64) 1566efd4c9b6SSteve Lawrence return; 1567efd4c9b6SSteve Lawrence 1568efd4c9b6SSteve Lawrence idle = knp->value.ui64; 1569efd4c9b6SSteve Lawrence 1570efd4c9b6SSteve Lawrence knp = kstat_data_lookup(kstat, "cpu_nsec_kernel"); 1571efd4c9b6SSteve Lawrence if (knp == NULL || knp->data_type != KSTAT_DATA_UINT64) 1572efd4c9b6SSteve Lawrence return; 1573efd4c9b6SSteve Lawrence 1574efd4c9b6SSteve Lawrence kern = knp->value.ui64; 1575efd4c9b6SSteve Lawrence 1576efd4c9b6SSteve Lawrence knp = kstat_data_lookup(kstat, "cpu_nsec_user"); 1577efd4c9b6SSteve Lawrence if (knp == NULL || knp->data_type != KSTAT_DATA_UINT64) 1578efd4c9b6SSteve Lawrence return; 1579efd4c9b6SSteve Lawrence 1580efd4c9b6SSteve Lawrence user = knp->value.ui64; 1581efd4c9b6SSteve Lawrence 1582efd4c9b6SSteve Lawrence /* 1583efd4c9b6SSteve Lawrence * Tracking intr time per cpu just exists for future enhancements. 1584efd4c9b6SSteve Lawrence * The value is presently always zero. 1585efd4c9b6SSteve Lawrence */ 1586efd4c9b6SSteve Lawrence intr = 0; 1587efd4c9b6SSteve Lawrence cpu->zsc_nsec_idle = idle; 1588efd4c9b6SSteve Lawrence cpu->zsc_nsec_intr = intr; 1589efd4c9b6SSteve Lawrence cpu->zsc_nsec_kern = kern; 1590efd4c9b6SSteve Lawrence cpu->zsc_nsec_user = user; 1591efd4c9b6SSteve Lawrence 1592efd4c9b6SSteve Lawrence if (cpu->zsc_onlined == B_TRUE) { 1593efd4c9b6SSteve Lawrence /* 1594efd4c9b6SSteve Lawrence * cpu is newly online. There is no reference value, 1595efd4c9b6SSteve Lawrence * so just record its current stats for comparison 1596efd4c9b6SSteve Lawrence * on next stat read. 1597efd4c9b6SSteve Lawrence */ 1598efd4c9b6SSteve Lawrence cpu->zsc_nsec_idle_prev = cpu->zsc_nsec_idle; 1599efd4c9b6SSteve Lawrence cpu->zsc_nsec_intr_prev = cpu->zsc_nsec_intr; 1600efd4c9b6SSteve Lawrence cpu->zsc_nsec_kern_prev = cpu->zsc_nsec_kern; 1601efd4c9b6SSteve Lawrence cpu->zsc_nsec_user_prev = cpu->zsc_nsec_user; 1602efd4c9b6SSteve Lawrence return; 1603efd4c9b6SSteve Lawrence } 1604efd4c9b6SSteve Lawrence 1605efd4c9b6SSteve Lawrence /* 1606efd4c9b6SSteve Lawrence * Calculate relative time since previous refresh. 1607efd4c9b6SSteve Lawrence * Paranoia. Don't let time go backwards. 1608efd4c9b6SSteve Lawrence */ 1609efd4c9b6SSteve Lawrence idle = intr = kern = user = 0; 1610efd4c9b6SSteve Lawrence if (cpu->zsc_nsec_idle > cpu->zsc_nsec_idle_prev) 1611efd4c9b6SSteve Lawrence idle = cpu->zsc_nsec_idle - cpu->zsc_nsec_idle_prev; 1612efd4c9b6SSteve Lawrence 1613efd4c9b6SSteve Lawrence if (cpu->zsc_nsec_intr > cpu->zsc_nsec_intr_prev) 1614efd4c9b6SSteve Lawrence intr = cpu->zsc_nsec_intr - cpu->zsc_nsec_intr_prev; 1615efd4c9b6SSteve Lawrence 1616efd4c9b6SSteve Lawrence if (cpu->zsc_nsec_kern > cpu->zsc_nsec_kern_prev) 1617efd4c9b6SSteve Lawrence kern = cpu->zsc_nsec_kern - cpu->zsc_nsec_kern_prev; 1618efd4c9b6SSteve Lawrence 1619efd4c9b6SSteve Lawrence if (cpu->zsc_nsec_user > cpu->zsc_nsec_user_prev) 1620efd4c9b6SSteve Lawrence user = cpu->zsc_nsec_user - cpu->zsc_nsec_user_prev; 1621efd4c9b6SSteve Lawrence 1622efd4c9b6SSteve Lawrence /* Update totals for cpu usage */ 1623efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(cpu->zsc_idle, idle); 1624efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(cpu->zsc_intr, intr); 1625efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(cpu->zsc_kern, kern); 1626efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(cpu->zsc_user, user); 1627efd4c9b6SSteve Lawrence 1628efd4c9b6SSteve Lawrence /* 1629efd4c9b6SSteve Lawrence * Add cpu's stats to its pset if it is known to be in 1630efd4c9b6SSteve Lawrence * the pset since previous read. 1631efd4c9b6SSteve Lawrence */ 1632efd4c9b6SSteve Lawrence if (cpu->zsc_psetid == cpu->zsc_psetid_prev || 1633efd4c9b6SSteve Lawrence cpu->zsc_psetid_prev == ZS_PSET_ERROR || 1634efd4c9b6SSteve Lawrence (pset_prev = zsd_lookup_pset_byid(ctl, 1635efd4c9b6SSteve Lawrence cpu->zsc_psetid_prev)) == NULL) { 1636efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(pset->zsp_idle, idle); 1637efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(pset->zsp_intr, intr); 1638efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(pset->zsp_kern, kern); 1639efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(pset->zsp_user, user); 1640efd4c9b6SSteve Lawrence } else { 1641efd4c9b6SSteve Lawrence /* 1642efd4c9b6SSteve Lawrence * Last pset was different than current pset. 1643efd4c9b6SSteve Lawrence * Best guess is to split usage between the two. 1644efd4c9b6SSteve Lawrence */ 1645efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(pset_prev->zsp_idle, idle / 2); 1646efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(pset_prev->zsp_intr, intr / 2); 1647efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(pset_prev->zsp_kern, kern / 2); 1648efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(pset_prev->zsp_user, user / 2); 1649efd4c9b6SSteve Lawrence 1650efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(pset->zsp_idle, 1651efd4c9b6SSteve Lawrence (idle / 2) + (idle % 2)); 1652efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(pset->zsp_intr, 1653efd4c9b6SSteve Lawrence (intr / 2) + (intr % 2)); 1654efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(pset->zsp_kern, 1655efd4c9b6SSteve Lawrence (kern / 2) + (kern % 2)); 1656efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(pset->zsp_user, 1657efd4c9b6SSteve Lawrence (user / 2) + (user % 2)); 1658efd4c9b6SSteve Lawrence } 1659efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(sys->zss_idle, idle); 1660efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(sys->zss_intr, intr); 1661efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(sys->zss_kern, kern); 1662efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(sys->zss_user, user); 1663efd4c9b6SSteve Lawrence } 1664efd4c9b6SSteve Lawrence 1665efd4c9b6SSteve Lawrence /* Determine the details of a processor set by pset_id */ 1666efd4c9b6SSteve Lawrence static int 1667efd4c9b6SSteve Lawrence zsd_get_pool_pset(zsd_ctl_t *ctl, psetid_t psetid, char *psetname, 1668efd4c9b6SSteve Lawrence size_t namelen, uint_t *cputype, uint64_t *online, uint64_t *size, 1669efd4c9b6SSteve Lawrence uint64_t *min, uint64_t *max, int64_t *importance) 1670efd4c9b6SSteve Lawrence { 1671efd4c9b6SSteve Lawrence uint_t old, num; 1672efd4c9b6SSteve Lawrence 1673efd4c9b6SSteve Lawrence pool_conf_t *conf = ctl->zsctl_pool_conf; 1674efd4c9b6SSteve Lawrence pool_value_t **vals = ctl->zsctl_pool_vals; 1675efd4c9b6SSteve Lawrence pool_resource_t **res_list = NULL; 1676efd4c9b6SSteve Lawrence pool_resource_t *pset; 1677efd4c9b6SSteve Lawrence pool_component_t **cpus = NULL; 1678efd4c9b6SSteve Lawrence processorid_t *cache; 1679efd4c9b6SSteve Lawrence const char *string; 1680efd4c9b6SSteve Lawrence uint64_t uint64; 1681efd4c9b6SSteve Lawrence int64_t int64; 1682efd4c9b6SSteve Lawrence int i, ret, type; 1683efd4c9b6SSteve Lawrence 1684efd4c9b6SSteve Lawrence if (ctl->zsctl_pool_status == POOL_DISABLED) { 1685efd4c9b6SSteve Lawrence 1686efd4c9b6SSteve Lawrence /* 1687efd4c9b6SSteve Lawrence * Inspect legacy psets 1688efd4c9b6SSteve Lawrence */ 1689efd4c9b6SSteve Lawrence for (;;) { 1690efd4c9b6SSteve Lawrence old = num = ctl->zsctl_cpu_ncache; 1691efd4c9b6SSteve Lawrence ret = pset_info(psetid, &type, &num, 1692efd4c9b6SSteve Lawrence ctl->zsctl_cpu_cache); 1693efd4c9b6SSteve Lawrence if (ret < 0) { 1694efd4c9b6SSteve Lawrence /* pset is gone. Tell caller to retry */ 1695efd4c9b6SSteve Lawrence errno = EINTR; 1696efd4c9b6SSteve Lawrence return (-1); 1697efd4c9b6SSteve Lawrence } 1698efd4c9b6SSteve Lawrence if (num <= old) { 1699efd4c9b6SSteve Lawrence /* Success */ 1700efd4c9b6SSteve Lawrence break; 1701efd4c9b6SSteve Lawrence } 1702efd4c9b6SSteve Lawrence if ((cache = (processorid_t *)realloc( 1703efd4c9b6SSteve Lawrence ctl->zsctl_cpu_cache, num * 1704efd4c9b6SSteve Lawrence sizeof (processorid_t))) != NULL) { 1705efd4c9b6SSteve Lawrence ctl->zsctl_cpu_ncache = num; 1706efd4c9b6SSteve Lawrence ctl->zsctl_cpu_cache = cache; 1707efd4c9b6SSteve Lawrence } else { 1708efd4c9b6SSteve Lawrence /* 1709efd4c9b6SSteve Lawrence * Could not allocate to get new cpu list. 1710efd4c9b6SSteve Lawrence */ 1711efd4c9b6SSteve Lawrence zsd_warn(gettext( 1712efd4c9b6SSteve Lawrence "Could not allocate for cpu list")); 1713efd4c9b6SSteve Lawrence errno = ENOMEM; 1714efd4c9b6SSteve Lawrence return (-1); 1715efd4c9b6SSteve Lawrence } 1716efd4c9b6SSteve Lawrence } 1717efd4c9b6SSteve Lawrence /* 1718efd4c9b6SSteve Lawrence * Old school pset. Just make min and max equal 1719efd4c9b6SSteve Lawrence * to its size 1720efd4c9b6SSteve Lawrence */ 1721efd4c9b6SSteve Lawrence if (psetid == ZS_PSET_DEFAULT) { 1722efd4c9b6SSteve Lawrence *cputype = ZS_CPUTYPE_DEFAULT_PSET; 1723efd4c9b6SSteve Lawrence (void) strlcpy(psetname, "pset_default", namelen); 1724efd4c9b6SSteve Lawrence } else { 1725efd4c9b6SSteve Lawrence *cputype = ZS_CPUTYPE_PSRSET_PSET; 1726efd4c9b6SSteve Lawrence (void) snprintf(psetname, namelen, 1727efd4c9b6SSteve Lawrence "SUNWlegacy_pset_%d", psetid); 1728efd4c9b6SSteve Lawrence } 1729efd4c9b6SSteve Lawrence 1730efd4c9b6SSteve Lawrence /* 1731efd4c9b6SSteve Lawrence * Just treat legacy pset as a simple pool pset 1732efd4c9b6SSteve Lawrence */ 1733efd4c9b6SSteve Lawrence *online = num; 1734efd4c9b6SSteve Lawrence *size = num; 1735efd4c9b6SSteve Lawrence *min = num; 1736efd4c9b6SSteve Lawrence *max = num; 1737efd4c9b6SSteve Lawrence *importance = 1; 1738efd4c9b6SSteve Lawrence 1739efd4c9b6SSteve Lawrence return (0); 1740efd4c9b6SSteve Lawrence } 1741efd4c9b6SSteve Lawrence 1742efd4c9b6SSteve Lawrence /* Look up the pool pset using the pset id */ 1743efd4c9b6SSteve Lawrence res_list = NULL; 1744efd4c9b6SSteve Lawrence pool_value_set_int64(vals[1], psetid); 1745efd4c9b6SSteve Lawrence if (pool_value_set_name(vals[1], "pset.sys_id") 1746efd4c9b6SSteve Lawrence != PO_SUCCESS) 1747efd4c9b6SSteve Lawrence goto err; 1748efd4c9b6SSteve Lawrence 1749efd4c9b6SSteve Lawrence if (pool_value_set_name(vals[0], "type") != PO_SUCCESS) 1750efd4c9b6SSteve Lawrence goto err; 1751efd4c9b6SSteve Lawrence if (pool_value_set_string(vals[0], "pset") != PO_SUCCESS) 1752efd4c9b6SSteve Lawrence goto err; 1753efd4c9b6SSteve Lawrence if ((res_list = pool_query_resources(conf, &num, vals)) == NULL) 1754efd4c9b6SSteve Lawrence goto err; 1755efd4c9b6SSteve Lawrence if (num != 1) 1756efd4c9b6SSteve Lawrence goto err; 1757efd4c9b6SSteve Lawrence pset = res_list[0]; 1758efd4c9b6SSteve Lawrence free(res_list); 1759efd4c9b6SSteve Lawrence res_list = NULL; 1760efd4c9b6SSteve Lawrence if (pool_get_property(conf, pool_resource_to_elem(conf, pset), 1761efd4c9b6SSteve Lawrence "pset.name", vals[0]) != POC_STRING || 1762efd4c9b6SSteve Lawrence pool_value_get_string(vals[0], &string) != PO_SUCCESS) 1763efd4c9b6SSteve Lawrence goto err; 1764efd4c9b6SSteve Lawrence 1765efd4c9b6SSteve Lawrence (void) strlcpy(psetname, string, namelen); 1766efd4c9b6SSteve Lawrence if (strncmp(psetname, "SUNWtmp", strlen("SUNWtmp")) == 0) 1767efd4c9b6SSteve Lawrence *cputype = ZS_CPUTYPE_DEDICATED; 1768efd4c9b6SSteve Lawrence else if (psetid == ZS_PSET_DEFAULT) 1769efd4c9b6SSteve Lawrence *cputype = ZS_CPUTYPE_DEFAULT_PSET; 1770efd4c9b6SSteve Lawrence else 1771efd4c9b6SSteve Lawrence *cputype = ZS_CPUTYPE_POOL_PSET; 1772efd4c9b6SSteve Lawrence 1773efd4c9b6SSteve Lawrence /* Get size, min, max, and importance */ 1774efd4c9b6SSteve Lawrence if (pool_get_property(conf, pool_resource_to_elem(conf, 1775efd4c9b6SSteve Lawrence pset), "pset.size", vals[0]) == POC_UINT && 1776efd4c9b6SSteve Lawrence pool_value_get_uint64(vals[0], &uint64) == PO_SUCCESS) 1777efd4c9b6SSteve Lawrence *size = uint64; 1778efd4c9b6SSteve Lawrence else 1779efd4c9b6SSteve Lawrence *size = 0; 1780efd4c9b6SSteve Lawrence 1781efd4c9b6SSteve Lawrence /* Get size, min, max, and importance */ 1782efd4c9b6SSteve Lawrence if (pool_get_property(conf, pool_resource_to_elem(conf, 1783efd4c9b6SSteve Lawrence pset), "pset.min", vals[0]) == POC_UINT && 1784efd4c9b6SSteve Lawrence pool_value_get_uint64(vals[0], &uint64) == PO_SUCCESS) 1785efd4c9b6SSteve Lawrence *min = uint64; 1786efd4c9b6SSteve Lawrence else 1787efd4c9b6SSteve Lawrence *min = 0; 1788efd4c9b6SSteve Lawrence if (*min >= ZSD_PSET_UNLIMITED) 1789efd4c9b6SSteve Lawrence *min = ZS_LIMIT_NONE; 1790efd4c9b6SSteve Lawrence 1791efd4c9b6SSteve Lawrence if (pool_get_property(conf, pool_resource_to_elem(conf, 1792efd4c9b6SSteve Lawrence pset), "pset.max", vals[0]) == POC_UINT && 1793efd4c9b6SSteve Lawrence pool_value_get_uint64(vals[0], &uint64) == PO_SUCCESS) 1794efd4c9b6SSteve Lawrence *max = uint64; 1795efd4c9b6SSteve Lawrence else 1796efd4c9b6SSteve Lawrence *max = ZS_LIMIT_NONE; 1797efd4c9b6SSteve Lawrence 1798efd4c9b6SSteve Lawrence if (*max >= ZSD_PSET_UNLIMITED) 1799efd4c9b6SSteve Lawrence *max = ZS_LIMIT_NONE; 1800efd4c9b6SSteve Lawrence 1801efd4c9b6SSteve Lawrence if (pool_get_property(conf, pool_resource_to_elem(conf, 1802efd4c9b6SSteve Lawrence pset), "pset.importance", vals[0]) == POC_INT && 1803efd4c9b6SSteve Lawrence pool_value_get_int64(vals[0], &int64) == PO_SUCCESS) 1804efd4c9b6SSteve Lawrence *importance = int64; 1805efd4c9b6SSteve Lawrence else 1806efd4c9b6SSteve Lawrence *importance = (uint64_t)1; 1807efd4c9b6SSteve Lawrence 1808efd4c9b6SSteve Lawrence *online = 0; 1809efd4c9b6SSteve Lawrence if (*size == 0) 1810efd4c9b6SSteve Lawrence return (0); 1811efd4c9b6SSteve Lawrence 1812efd4c9b6SSteve Lawrence /* get cpus */ 1813efd4c9b6SSteve Lawrence cpus = pool_query_resource_components(conf, pset, &num, NULL); 1814efd4c9b6SSteve Lawrence if (cpus == NULL) 1815efd4c9b6SSteve Lawrence goto err; 1816efd4c9b6SSteve Lawrence 1817efd4c9b6SSteve Lawrence /* Make sure there is space for cpu id list */ 1818efd4c9b6SSteve Lawrence if (num > ctl->zsctl_cpu_ncache) { 1819efd4c9b6SSteve Lawrence if ((cache = (processorid_t *)realloc( 1820efd4c9b6SSteve Lawrence ctl->zsctl_cpu_cache, num * 1821efd4c9b6SSteve Lawrence sizeof (processorid_t))) != NULL) { 1822efd4c9b6SSteve Lawrence ctl->zsctl_cpu_ncache = num; 1823efd4c9b6SSteve Lawrence ctl->zsctl_cpu_cache = cache; 1824efd4c9b6SSteve Lawrence } else { 1825efd4c9b6SSteve Lawrence /* 1826efd4c9b6SSteve Lawrence * Could not allocate to get new cpu list. 1827efd4c9b6SSteve Lawrence */ 1828efd4c9b6SSteve Lawrence zsd_warn(gettext( 1829efd4c9b6SSteve Lawrence "Could not allocate for cpu list")); 1830efd4c9b6SSteve Lawrence goto err; 1831efd4c9b6SSteve Lawrence } 1832efd4c9b6SSteve Lawrence } 1833efd4c9b6SSteve Lawrence 1834efd4c9b6SSteve Lawrence /* count the online cpus */ 1835efd4c9b6SSteve Lawrence for (i = 0; i < num; i++) { 1836efd4c9b6SSteve Lawrence if (pool_get_property(conf, pool_component_to_elem( 1837efd4c9b6SSteve Lawrence conf, cpus[i]), "cpu.status", vals[0]) != POC_STRING || 1838efd4c9b6SSteve Lawrence pool_value_get_string(vals[0], &string) != PO_SUCCESS) 1839efd4c9b6SSteve Lawrence goto err; 1840efd4c9b6SSteve Lawrence 1841efd4c9b6SSteve Lawrence if (strcmp(string, "on-line") != 0 && 1842efd4c9b6SSteve Lawrence strcmp(string, "no-intr") != 0) 1843efd4c9b6SSteve Lawrence continue; 1844efd4c9b6SSteve Lawrence 1845efd4c9b6SSteve Lawrence if (pool_get_property(conf, pool_component_to_elem( 1846efd4c9b6SSteve Lawrence conf, cpus[i]), "cpu.sys_id", vals[0]) != POC_INT || 1847efd4c9b6SSteve Lawrence pool_value_get_int64(vals[0], &int64) != PO_SUCCESS) 1848efd4c9b6SSteve Lawrence goto err; 1849efd4c9b6SSteve Lawrence 1850efd4c9b6SSteve Lawrence (*online)++; 1851efd4c9b6SSteve Lawrence ctl->zsctl_cpu_cache[i] = (psetid_t)int64; 1852efd4c9b6SSteve Lawrence } 1853efd4c9b6SSteve Lawrence free(cpus); 1854efd4c9b6SSteve Lawrence return (0); 1855efd4c9b6SSteve Lawrence err: 1856efd4c9b6SSteve Lawrence if (res_list != NULL) 1857efd4c9b6SSteve Lawrence free(res_list); 1858efd4c9b6SSteve Lawrence if (cpus != NULL) 1859efd4c9b6SSteve Lawrence free(cpus); 1860efd4c9b6SSteve Lawrence 1861efd4c9b6SSteve Lawrence /* 1862efd4c9b6SSteve Lawrence * The pools operations should succeed since the conf is a consistent 1863efd4c9b6SSteve Lawrence * snapshot. Tell caller there is no need to retry. 1864efd4c9b6SSteve Lawrence */ 1865efd4c9b6SSteve Lawrence errno = EINVAL; 1866efd4c9b6SSteve Lawrence return (-1); 1867efd4c9b6SSteve Lawrence } 1868efd4c9b6SSteve Lawrence 1869efd4c9b6SSteve Lawrence /* 1870efd4c9b6SSteve Lawrence * Update the current list of processor sets. 1871efd4c9b6SSteve Lawrence * This also updates the list of online cpus, and each cpu's pset membership. 1872efd4c9b6SSteve Lawrence */ 1873efd4c9b6SSteve Lawrence static void 1874efd4c9b6SSteve Lawrence zsd_refresh_psets(zsd_ctl_t *ctl) 1875efd4c9b6SSteve Lawrence { 1876efd4c9b6SSteve Lawrence int i, j, ret, state; 1877efd4c9b6SSteve Lawrence uint_t old, num; 1878efd4c9b6SSteve Lawrence uint_t cputype; 1879efd4c9b6SSteve Lawrence int64_t sys_id, importance; 1880efd4c9b6SSteve Lawrence uint64_t online, size, min, max; 1881efd4c9b6SSteve Lawrence zsd_system_t *system; 1882efd4c9b6SSteve Lawrence zsd_pset_t *pset; 1883efd4c9b6SSteve Lawrence zsd_cpu_t *cpu; 1884efd4c9b6SSteve Lawrence psetid_t *cache; 1885efd4c9b6SSteve Lawrence char psetname[ZS_PSETNAME_MAX]; 1886efd4c9b6SSteve Lawrence processorid_t cpuid; 1887efd4c9b6SSteve Lawrence pool_value_t *pv_save = NULL; 1888efd4c9b6SSteve Lawrence pool_resource_t **res_list = NULL; 1889efd4c9b6SSteve Lawrence pool_resource_t *res; 1890efd4c9b6SSteve Lawrence pool_value_t **vals; 1891efd4c9b6SSteve Lawrence pool_conf_t *conf; 1892efd4c9b6SSteve Lawrence boolean_t roll_cpus = B_TRUE; 1893efd4c9b6SSteve Lawrence 1894efd4c9b6SSteve Lawrence /* Zero cpu counters to recount them */ 1895efd4c9b6SSteve Lawrence system = ctl->zsctl_system; 1896efd4c9b6SSteve Lawrence system->zss_ncpus = 0; 1897efd4c9b6SSteve Lawrence system->zss_ncpus_online = 0; 1898efd4c9b6SSteve Lawrence retry: 1899efd4c9b6SSteve Lawrence ret = pool_get_status(&state); 1900efd4c9b6SSteve Lawrence if (ret == 0 && state == POOL_ENABLED) { 1901efd4c9b6SSteve Lawrence 1902efd4c9b6SSteve Lawrence conf = ctl->zsctl_pool_conf; 1903efd4c9b6SSteve Lawrence vals = ctl->zsctl_pool_vals; 1904efd4c9b6SSteve Lawrence pv_save = vals[1]; 1905efd4c9b6SSteve Lawrence vals[1] = NULL; 1906efd4c9b6SSteve Lawrence 1907efd4c9b6SSteve Lawrence if (ctl->zsctl_pool_status == POOL_DISABLED) { 1908efd4c9b6SSteve Lawrence if (pool_conf_open(ctl->zsctl_pool_conf, 1909efd4c9b6SSteve Lawrence pool_dynamic_location(), PO_RDONLY) == 0) { 1910efd4c9b6SSteve Lawrence ctl->zsctl_pool_status = POOL_ENABLED; 1911efd4c9b6SSteve Lawrence ctl->zsctl_pool_changed = POU_PSET; 1912efd4c9b6SSteve Lawrence } 1913efd4c9b6SSteve Lawrence } else { 1914efd4c9b6SSteve Lawrence ctl->zsctl_pool_changed = 0; 1915efd4c9b6SSteve Lawrence ret = pool_conf_update(ctl->zsctl_pool_conf, 1916efd4c9b6SSteve Lawrence &(ctl->zsctl_pool_changed)); 1917efd4c9b6SSteve Lawrence if (ret < 0) { 1918efd4c9b6SSteve Lawrence /* Pools must have become disabled */ 1919efd4c9b6SSteve Lawrence (void) pool_conf_close(ctl->zsctl_pool_conf); 1920efd4c9b6SSteve Lawrence ctl->zsctl_pool_status = POOL_DISABLED; 1921efd4c9b6SSteve Lawrence if (pool_error() == POE_SYSTEM && errno == 1922efd4c9b6SSteve Lawrence ENOTACTIVE) 1923efd4c9b6SSteve Lawrence goto retry; 1924efd4c9b6SSteve Lawrence 1925efd4c9b6SSteve Lawrence zsd_warn(gettext( 1926efd4c9b6SSteve Lawrence "Unable to update pool configuration")); 1927efd4c9b6SSteve Lawrence /* Not able to get pool info. Don't update. */ 1928efd4c9b6SSteve Lawrence goto err; 1929efd4c9b6SSteve Lawrence } 1930efd4c9b6SSteve Lawrence } 1931efd4c9b6SSteve Lawrence /* Get the list of psets using libpool */ 1932efd4c9b6SSteve Lawrence if (pool_value_set_name(vals[0], "type") != PO_SUCCESS) 1933efd4c9b6SSteve Lawrence goto err; 1934efd4c9b6SSteve Lawrence 1935efd4c9b6SSteve Lawrence if (pool_value_set_string(vals[0], "pset") != PO_SUCCESS) 1936efd4c9b6SSteve Lawrence goto err; 1937efd4c9b6SSteve Lawrence if ((res_list = pool_query_resources(conf, &num, vals)) 1938efd4c9b6SSteve Lawrence == NULL) 1939efd4c9b6SSteve Lawrence goto err; 1940efd4c9b6SSteve Lawrence 1941efd4c9b6SSteve Lawrence if (num > ctl->zsctl_pset_ncache) { 1942efd4c9b6SSteve Lawrence if ((cache = (psetid_t *)realloc(ctl->zsctl_pset_cache, 1943efd4c9b6SSteve Lawrence (num) * sizeof (psetid_t))) == NULL) { 1944efd4c9b6SSteve Lawrence goto err; 1945efd4c9b6SSteve Lawrence } 1946efd4c9b6SSteve Lawrence ctl->zsctl_pset_ncache = num; 1947efd4c9b6SSteve Lawrence ctl->zsctl_pset_cache = cache; 1948efd4c9b6SSteve Lawrence } 1949efd4c9b6SSteve Lawrence /* Save the pset id of each pset */ 1950efd4c9b6SSteve Lawrence for (i = 0; i < num; i++) { 1951efd4c9b6SSteve Lawrence res = res_list[i]; 1952efd4c9b6SSteve Lawrence if (pool_get_property(conf, pool_resource_to_elem(conf, 1953efd4c9b6SSteve Lawrence res), "pset.sys_id", vals[0]) != POC_INT || 1954efd4c9b6SSteve Lawrence pool_value_get_int64(vals[0], &sys_id) 1955efd4c9b6SSteve Lawrence != PO_SUCCESS) 1956efd4c9b6SSteve Lawrence goto err; 1957efd4c9b6SSteve Lawrence ctl->zsctl_pset_cache[i] = (int)sys_id; 1958efd4c9b6SSteve Lawrence } 1959efd4c9b6SSteve Lawrence vals[1] = pv_save; 1960efd4c9b6SSteve Lawrence pv_save = NULL; 1961efd4c9b6SSteve Lawrence } else { 1962efd4c9b6SSteve Lawrence if (ctl->zsctl_pool_status == POOL_ENABLED) { 1963efd4c9b6SSteve Lawrence (void) pool_conf_close(ctl->zsctl_pool_conf); 1964efd4c9b6SSteve Lawrence ctl->zsctl_pool_status = POOL_DISABLED; 1965efd4c9b6SSteve Lawrence } 1966efd4c9b6SSteve Lawrence /* Get the pset list using legacy psets */ 1967efd4c9b6SSteve Lawrence for (;;) { 1968efd4c9b6SSteve Lawrence old = num = ctl->zsctl_pset_ncache; 1969efd4c9b6SSteve Lawrence (void) pset_list(ctl->zsctl_pset_cache, &num); 1970efd4c9b6SSteve Lawrence if ((num + 1) <= old) { 1971efd4c9b6SSteve Lawrence break; 1972efd4c9b6SSteve Lawrence } 1973efd4c9b6SSteve Lawrence if ((cache = (psetid_t *)realloc(ctl->zsctl_pset_cache, 1974efd4c9b6SSteve Lawrence (num + 1) * sizeof (psetid_t))) != NULL) { 1975efd4c9b6SSteve Lawrence ctl->zsctl_pset_ncache = num + 1; 1976efd4c9b6SSteve Lawrence ctl->zsctl_pset_cache = cache; 1977efd4c9b6SSteve Lawrence } else { 1978efd4c9b6SSteve Lawrence /* 1979efd4c9b6SSteve Lawrence * Could not allocate to get new pset list. 1980efd4c9b6SSteve Lawrence * Give up 1981efd4c9b6SSteve Lawrence */ 1982efd4c9b6SSteve Lawrence return; 1983efd4c9b6SSteve Lawrence } 1984efd4c9b6SSteve Lawrence } 1985efd4c9b6SSteve Lawrence /* Add the default pset to list */ 1986efd4c9b6SSteve Lawrence ctl->zsctl_pset_cache[num] = ctl->zsctl_pset_cache[0]; 1987efd4c9b6SSteve Lawrence ctl->zsctl_pset_cache[0] = ZS_PSET_DEFAULT; 1988efd4c9b6SSteve Lawrence num++; 1989efd4c9b6SSteve Lawrence } 1990efd4c9b6SSteve Lawrence psets_changed: 1991efd4c9b6SSteve Lawrence zsd_mark_cpus_start(ctl, roll_cpus); 1992efd4c9b6SSteve Lawrence zsd_mark_psets_start(ctl); 1993efd4c9b6SSteve Lawrence roll_cpus = B_FALSE; 1994efd4c9b6SSteve Lawrence 1995efd4c9b6SSteve Lawrence /* Refresh cpu membership of all psets */ 1996efd4c9b6SSteve Lawrence for (i = 0; i < num; i++) { 1997efd4c9b6SSteve Lawrence 1998efd4c9b6SSteve Lawrence /* Get pool pset information */ 1999efd4c9b6SSteve Lawrence sys_id = ctl->zsctl_pset_cache[i]; 2000efd4c9b6SSteve Lawrence if (zsd_get_pool_pset(ctl, sys_id, psetname, sizeof (psetname), 2001efd4c9b6SSteve Lawrence &cputype, &online, &size, &min, &max, &importance) 2002efd4c9b6SSteve Lawrence != 0) { 2003efd4c9b6SSteve Lawrence if (errno == EINTR) 2004efd4c9b6SSteve Lawrence goto psets_changed; 2005efd4c9b6SSteve Lawrence zsd_warn(gettext("Failed to get info for pset %d"), 2006efd4c9b6SSteve Lawrence sys_id); 2007efd4c9b6SSteve Lawrence continue; 2008efd4c9b6SSteve Lawrence } 2009efd4c9b6SSteve Lawrence 2010efd4c9b6SSteve Lawrence system->zss_ncpus += size; 2011efd4c9b6SSteve Lawrence system->zss_ncpus_online += online; 2012efd4c9b6SSteve Lawrence 2013efd4c9b6SSteve Lawrence pset = zsd_lookup_insert_pset(ctl, psetname, 2014efd4c9b6SSteve Lawrence ctl->zsctl_pset_cache[i]); 2015efd4c9b6SSteve Lawrence 2016efd4c9b6SSteve Lawrence /* update pset info */ 2017efd4c9b6SSteve Lawrence zsd_mark_pset_found(pset, cputype, online, size, min, 2018efd4c9b6SSteve Lawrence max, importance); 2019efd4c9b6SSteve Lawrence 2020efd4c9b6SSteve Lawrence /* update each cpu in pset */ 2021efd4c9b6SSteve Lawrence for (j = 0; j < pset->zsp_online; j++) { 2022efd4c9b6SSteve Lawrence cpuid = ctl->zsctl_cpu_cache[j]; 2023efd4c9b6SSteve Lawrence cpu = zsd_lookup_insert_cpu(ctl, cpuid); 2024efd4c9b6SSteve Lawrence zsd_mark_cpu_found(cpu, pset, sys_id); 2025efd4c9b6SSteve Lawrence } 2026efd4c9b6SSteve Lawrence } 2027efd4c9b6SSteve Lawrence err: 2028efd4c9b6SSteve Lawrence if (res_list != NULL) 2029efd4c9b6SSteve Lawrence free(res_list); 2030efd4c9b6SSteve Lawrence if (pv_save != NULL) 2031efd4c9b6SSteve Lawrence vals[1] = pv_save; 2032efd4c9b6SSteve Lawrence } 2033efd4c9b6SSteve Lawrence 2034efd4c9b6SSteve Lawrence 2035efd4c9b6SSteve Lawrence 2036efd4c9b6SSteve Lawrence /* 2037efd4c9b6SSteve Lawrence * Fetch the current pool and pset name for the given zone. 2038efd4c9b6SSteve Lawrence */ 2039efd4c9b6SSteve Lawrence static void 2040efd4c9b6SSteve Lawrence zsd_get_zone_pool_pset(zsd_ctl_t *ctl, zsd_zone_t *zone, 2041efd4c9b6SSteve Lawrence char *pool, int poollen, char *pset, int psetlen, uint_t *cputype) 2042efd4c9b6SSteve Lawrence { 2043efd4c9b6SSteve Lawrence poolid_t poolid; 2044efd4c9b6SSteve Lawrence pool_t **pools = NULL; 2045efd4c9b6SSteve Lawrence pool_resource_t **res_list = NULL; 2046efd4c9b6SSteve Lawrence char poolname[ZS_POOLNAME_MAX]; 2047efd4c9b6SSteve Lawrence char psetname[ZS_PSETNAME_MAX]; 2048efd4c9b6SSteve Lawrence pool_conf_t *conf = ctl->zsctl_pool_conf; 2049efd4c9b6SSteve Lawrence pool_value_t *pv_save = NULL; 2050efd4c9b6SSteve Lawrence pool_value_t **vals = ctl->zsctl_pool_vals; 2051efd4c9b6SSteve Lawrence const char *string; 2052efd4c9b6SSteve Lawrence int ret; 2053efd4c9b6SSteve Lawrence int64_t int64; 2054efd4c9b6SSteve Lawrence uint_t num; 2055efd4c9b6SSteve Lawrence 2056efd4c9b6SSteve Lawrence ret = zone_getattr(zone->zsz_id, ZONE_ATTR_POOLID, 2057efd4c9b6SSteve Lawrence &poolid, sizeof (poolid)); 2058efd4c9b6SSteve Lawrence if (ret < 0) 2059efd4c9b6SSteve Lawrence goto lookup_done; 2060efd4c9b6SSteve Lawrence 2061efd4c9b6SSteve Lawrence pv_save = vals[1]; 2062efd4c9b6SSteve Lawrence vals[1] = NULL; 2063efd4c9b6SSteve Lawrence pools = NULL; 2064efd4c9b6SSteve Lawrence res_list = NULL; 2065efd4c9b6SSteve Lawrence 2066efd4c9b6SSteve Lawrence /* Default values if lookup fails */ 2067efd4c9b6SSteve Lawrence (void) strlcpy(poolname, "pool_default", sizeof (poolname)); 2068efd4c9b6SSteve Lawrence (void) strlcpy(psetname, "pset_default", sizeof (poolname)); 2069efd4c9b6SSteve Lawrence *cputype = ZS_CPUTYPE_DEFAULT_PSET; 2070efd4c9b6SSteve Lawrence 2071efd4c9b6SSteve Lawrence /* no dedicated cpu if pools are disabled */ 2072efd4c9b6SSteve Lawrence if (ctl->zsctl_pool_status == POOL_DISABLED) 2073efd4c9b6SSteve Lawrence goto lookup_done; 2074efd4c9b6SSteve Lawrence 2075efd4c9b6SSteve Lawrence /* Get the pool name using the id */ 2076efd4c9b6SSteve Lawrence pool_value_set_int64(vals[0], poolid); 2077efd4c9b6SSteve Lawrence if (pool_value_set_name(vals[0], "pool.sys_id") != PO_SUCCESS) 2078efd4c9b6SSteve Lawrence goto lookup_done; 2079efd4c9b6SSteve Lawrence 2080efd4c9b6SSteve Lawrence if ((pools = pool_query_pools(conf, &num, vals)) == NULL) 2081efd4c9b6SSteve Lawrence goto lookup_done; 2082efd4c9b6SSteve Lawrence 2083efd4c9b6SSteve Lawrence if (num != 1) 2084efd4c9b6SSteve Lawrence goto lookup_done; 2085efd4c9b6SSteve Lawrence 2086efd4c9b6SSteve Lawrence if (pool_get_property(conf, pool_to_elem(conf, pools[0]), 2087efd4c9b6SSteve Lawrence "pool.name", vals[0]) != POC_STRING || 2088efd4c9b6SSteve Lawrence pool_value_get_string(vals[0], &string) != PO_SUCCESS) 2089efd4c9b6SSteve Lawrence goto lookup_done; 2090efd4c9b6SSteve Lawrence (void) strlcpy(poolname, (char *)string, sizeof (poolname)); 2091efd4c9b6SSteve Lawrence 2092efd4c9b6SSteve Lawrence /* Get the name of the pset for the pool */ 2093efd4c9b6SSteve Lawrence if (pool_value_set_name(vals[0], "type") != PO_SUCCESS) 2094efd4c9b6SSteve Lawrence goto lookup_done; 2095efd4c9b6SSteve Lawrence 2096efd4c9b6SSteve Lawrence if (pool_value_set_string(vals[0], "pset") != PO_SUCCESS) 2097efd4c9b6SSteve Lawrence goto lookup_done; 2098efd4c9b6SSteve Lawrence 2099efd4c9b6SSteve Lawrence if ((res_list = pool_query_pool_resources(conf, pools[0], &num, vals)) 2100efd4c9b6SSteve Lawrence == NULL) 2101efd4c9b6SSteve Lawrence goto lookup_done; 2102efd4c9b6SSteve Lawrence 2103efd4c9b6SSteve Lawrence if (num != 1) 2104efd4c9b6SSteve Lawrence goto lookup_done; 2105efd4c9b6SSteve Lawrence 2106efd4c9b6SSteve Lawrence if (pool_get_property(conf, pool_resource_to_elem(conf, 2107efd4c9b6SSteve Lawrence res_list[0]), "pset.sys_id", vals[0]) != POC_INT || 2108efd4c9b6SSteve Lawrence pool_value_get_int64(vals[0], &int64) != PO_SUCCESS) 2109efd4c9b6SSteve Lawrence goto lookup_done; 2110efd4c9b6SSteve Lawrence 2111efd4c9b6SSteve Lawrence if (int64 == ZS_PSET_DEFAULT) 2112efd4c9b6SSteve Lawrence *cputype = ZS_CPUTYPE_DEFAULT_PSET; 2113efd4c9b6SSteve Lawrence 2114efd4c9b6SSteve Lawrence if (pool_get_property(conf, pool_resource_to_elem(conf, 2115efd4c9b6SSteve Lawrence res_list[0]), "pset.name", vals[0]) != POC_STRING || 2116efd4c9b6SSteve Lawrence pool_value_get_string(vals[0], &string) != PO_SUCCESS) 2117efd4c9b6SSteve Lawrence goto lookup_done; 2118efd4c9b6SSteve Lawrence 2119efd4c9b6SSteve Lawrence (void) strlcpy(psetname, (char *)string, sizeof (psetname)); 2120efd4c9b6SSteve Lawrence 2121efd4c9b6SSteve Lawrence if (strncmp(psetname, "SUNWtmp_", strlen("SUNWtmp_")) == 0) 2122efd4c9b6SSteve Lawrence *cputype = ZS_CPUTYPE_DEDICATED; 2123efd4c9b6SSteve Lawrence if (strncmp(psetname, "SUNW_legacy_", strlen("SUNW_legacy_")) == 0) 2124efd4c9b6SSteve Lawrence *cputype = ZS_CPUTYPE_PSRSET_PSET; 2125efd4c9b6SSteve Lawrence else 2126efd4c9b6SSteve Lawrence *cputype = ZS_CPUTYPE_POOL_PSET; 2127efd4c9b6SSteve Lawrence 2128efd4c9b6SSteve Lawrence lookup_done: 2129efd4c9b6SSteve Lawrence 2130efd4c9b6SSteve Lawrence if (pv_save != NULL) 2131efd4c9b6SSteve Lawrence vals[1] = pv_save; 2132efd4c9b6SSteve Lawrence 2133efd4c9b6SSteve Lawrence if (res_list) 2134efd4c9b6SSteve Lawrence free(res_list); 2135efd4c9b6SSteve Lawrence if (pools) 2136efd4c9b6SSteve Lawrence free(pools); 2137efd4c9b6SSteve Lawrence 2138efd4c9b6SSteve Lawrence (void) strlcpy(pool, poolname, poollen); 2139efd4c9b6SSteve Lawrence (void) strlcpy(pset, psetname, psetlen); 2140efd4c9b6SSteve Lawrence } 2141efd4c9b6SSteve Lawrence 2142efd4c9b6SSteve Lawrence /* Convert scheduler names to ZS_* scheduler flags */ 2143efd4c9b6SSteve Lawrence static uint_t 2144efd4c9b6SSteve Lawrence zsd_schedname2int(char *clname, int pri) 2145efd4c9b6SSteve Lawrence { 2146efd4c9b6SSteve Lawrence uint_t sched = 0; 2147efd4c9b6SSteve Lawrence 2148efd4c9b6SSteve Lawrence if (strcmp(clname, "TS") == 0) { 2149efd4c9b6SSteve Lawrence sched = ZS_SCHED_TS; 2150efd4c9b6SSteve Lawrence } else if (strcmp(clname, "IA") == 0) { 2151efd4c9b6SSteve Lawrence sched = ZS_SCHED_IA; 2152efd4c9b6SSteve Lawrence } else if (strcmp(clname, "FX") == 0) { 2153efd4c9b6SSteve Lawrence if (pri > 59) { 2154efd4c9b6SSteve Lawrence sched = ZS_SCHED_FX_60; 2155efd4c9b6SSteve Lawrence } else { 2156efd4c9b6SSteve Lawrence sched = ZS_SCHED_FX; 2157efd4c9b6SSteve Lawrence } 2158efd4c9b6SSteve Lawrence } else if (strcmp(clname, "RT") == 0) { 2159efd4c9b6SSteve Lawrence sched = ZS_SCHED_RT; 2160efd4c9b6SSteve Lawrence 2161efd4c9b6SSteve Lawrence } else if (strcmp(clname, "FSS") == 0) { 2162efd4c9b6SSteve Lawrence sched = ZS_SCHED_FSS; 2163efd4c9b6SSteve Lawrence } 2164efd4c9b6SSteve Lawrence return (sched); 2165efd4c9b6SSteve Lawrence } 2166efd4c9b6SSteve Lawrence 2167efd4c9b6SSteve Lawrence static uint64_t 2168efd4c9b6SSteve Lawrence zsd_get_zone_rctl_limit(char *name) 2169efd4c9b6SSteve Lawrence { 2170efd4c9b6SSteve Lawrence rctlblk_t *rblk; 2171efd4c9b6SSteve Lawrence 2172efd4c9b6SSteve Lawrence rblk = (rctlblk_t *)alloca(rctlblk_size()); 2173efd4c9b6SSteve Lawrence if (getrctl(name, NULL, rblk, RCTL_FIRST) 2174efd4c9b6SSteve Lawrence != 0) { 2175efd4c9b6SSteve Lawrence return (ZS_LIMIT_NONE); 2176efd4c9b6SSteve Lawrence } 2177efd4c9b6SSteve Lawrence return (rctlblk_get_value(rblk)); 2178efd4c9b6SSteve Lawrence } 2179efd4c9b6SSteve Lawrence 2180efd4c9b6SSteve Lawrence static uint64_t 2181efd4c9b6SSteve Lawrence zsd_get_zone_rctl_usage(char *name) 2182efd4c9b6SSteve Lawrence { 2183efd4c9b6SSteve Lawrence rctlblk_t *rblk; 2184efd4c9b6SSteve Lawrence 2185efd4c9b6SSteve Lawrence rblk = (rctlblk_t *)alloca(rctlblk_size()); 2186efd4c9b6SSteve Lawrence if (getrctl(name, NULL, rblk, RCTL_USAGE) 2187efd4c9b6SSteve Lawrence != 0) { 2188efd4c9b6SSteve Lawrence return (0); 2189efd4c9b6SSteve Lawrence } 2190efd4c9b6SSteve Lawrence return (rctlblk_get_value(rblk)); 2191efd4c9b6SSteve Lawrence } 2192efd4c9b6SSteve Lawrence 2193efd4c9b6SSteve Lawrence #define ZSD_NUM_RCTL_VALS 19 2194efd4c9b6SSteve Lawrence 2195efd4c9b6SSteve Lawrence /* 2196efd4c9b6SSteve Lawrence * Fetch the limit information for a zone. This uses zone_enter() as the 2197efd4c9b6SSteve Lawrence * getrctl(2) system call only returns rctl information for the zone of 2198efd4c9b6SSteve Lawrence * the caller. 2199efd4c9b6SSteve Lawrence */ 2200efd4c9b6SSteve Lawrence static int 2201efd4c9b6SSteve Lawrence zsd_get_zone_caps(zsd_ctl_t *ctl, zsd_zone_t *zone, uint64_t *cpu_shares, 2202efd4c9b6SSteve Lawrence uint64_t *cpu_cap, uint64_t *ram_cap, uint64_t *locked_cap, 2203efd4c9b6SSteve Lawrence uint64_t *vm_cap, uint64_t *processes_cap, uint64_t *processes, 2204efd4c9b6SSteve Lawrence uint64_t *lwps_cap, uint64_t *lwps, uint64_t *shm_cap, uint64_t *shm, 2205efd4c9b6SSteve Lawrence uint64_t *shmids_cap, uint64_t *shmids, uint64_t *semids_cap, 2206efd4c9b6SSteve Lawrence uint64_t *semids, uint64_t *msgids_cap, uint64_t *msgids, 2207efd4c9b6SSteve Lawrence uint64_t *lofi_cap, uint64_t *lofi, uint_t *sched) 2208efd4c9b6SSteve Lawrence { 2209efd4c9b6SSteve Lawrence int p[2], pid, tmpl_fd, ret; 2210efd4c9b6SSteve Lawrence ctid_t ct; 2211efd4c9b6SSteve Lawrence char class[PC_CLNMSZ]; 2212efd4c9b6SSteve Lawrence uint64_t vals[ZSD_NUM_RCTL_VALS]; 2213efd4c9b6SSteve Lawrence zsd_system_t *sys = ctl->zsctl_system; 2214efd4c9b6SSteve Lawrence int i = 0; 2215efd4c9b6SSteve Lawrence int res = 0; 2216efd4c9b6SSteve Lawrence 2217efd4c9b6SSteve Lawrence /* Treat all caps as no cap on error */ 2218efd4c9b6SSteve Lawrence *cpu_shares = ZS_LIMIT_NONE; 2219efd4c9b6SSteve Lawrence *cpu_cap = ZS_LIMIT_NONE; 2220efd4c9b6SSteve Lawrence *ram_cap = ZS_LIMIT_NONE; 2221efd4c9b6SSteve Lawrence *locked_cap = ZS_LIMIT_NONE; 2222efd4c9b6SSteve Lawrence *vm_cap = ZS_LIMIT_NONE; 2223efd4c9b6SSteve Lawrence 2224efd4c9b6SSteve Lawrence *processes_cap = ZS_LIMIT_NONE; 2225efd4c9b6SSteve Lawrence *lwps_cap = ZS_LIMIT_NONE; 2226efd4c9b6SSteve Lawrence *shm_cap = ZS_LIMIT_NONE; 2227efd4c9b6SSteve Lawrence *shmids_cap = ZS_LIMIT_NONE; 2228efd4c9b6SSteve Lawrence *semids_cap = ZS_LIMIT_NONE; 2229efd4c9b6SSteve Lawrence *msgids_cap = ZS_LIMIT_NONE; 2230efd4c9b6SSteve Lawrence *lofi_cap = ZS_LIMIT_NONE; 2231efd4c9b6SSteve Lawrence 2232efd4c9b6SSteve Lawrence *processes = 0; 2233efd4c9b6SSteve Lawrence *lwps = 0; 2234efd4c9b6SSteve Lawrence *shm = 0; 2235efd4c9b6SSteve Lawrence *shmids = 0; 2236efd4c9b6SSteve Lawrence *semids = 0; 2237efd4c9b6SSteve Lawrence *msgids = 0; 2238efd4c9b6SSteve Lawrence *lofi = 0; 2239efd4c9b6SSteve Lawrence 2240efd4c9b6SSteve Lawrence /* Get the ram cap first since it is a zone attr */ 2241efd4c9b6SSteve Lawrence ret = zone_getattr(zone->zsz_id, ZONE_ATTR_PHYS_MCAP, 2242efd4c9b6SSteve Lawrence ram_cap, sizeof (*ram_cap)); 2243efd4c9b6SSteve Lawrence if (ret < 0 || *ram_cap == 0) 2244efd4c9b6SSteve Lawrence *ram_cap = ZS_LIMIT_NONE; 2245efd4c9b6SSteve Lawrence 2246efd4c9b6SSteve Lawrence /* Get the zone's default scheduling class */ 2247efd4c9b6SSteve Lawrence ret = zone_getattr(zone->zsz_id, ZONE_ATTR_SCHED_CLASS, 2248efd4c9b6SSteve Lawrence class, sizeof (class)); 2249efd4c9b6SSteve Lawrence if (ret < 0) 2250efd4c9b6SSteve Lawrence return (-1); 2251efd4c9b6SSteve Lawrence 2252efd4c9b6SSteve Lawrence *sched = zsd_schedname2int(class, 0); 2253efd4c9b6SSteve Lawrence 2254efd4c9b6SSteve Lawrence /* rctl caps must be fetched from within the zone */ 2255efd4c9b6SSteve Lawrence if (pipe(p) != 0) 2256efd4c9b6SSteve Lawrence return (-1); 2257efd4c9b6SSteve Lawrence 2258efd4c9b6SSteve Lawrence if ((tmpl_fd = init_template()) == -1) { 2259efd4c9b6SSteve Lawrence (void) close(p[0]); 2260efd4c9b6SSteve Lawrence (void) close(p[1]); 2261efd4c9b6SSteve Lawrence return (-1); 2262efd4c9b6SSteve Lawrence } 2263efd4c9b6SSteve Lawrence pid = forkx(0); 2264efd4c9b6SSteve Lawrence if (pid < 0) { 2265efd4c9b6SSteve Lawrence (void) ct_tmpl_clear(tmpl_fd); 2266efd4c9b6SSteve Lawrence (void) close(p[0]); 2267efd4c9b6SSteve Lawrence (void) close(p[1]); 2268efd4c9b6SSteve Lawrence return (-1); 2269efd4c9b6SSteve Lawrence } 2270efd4c9b6SSteve Lawrence if (pid == 0) { 2271efd4c9b6SSteve Lawrence 2272efd4c9b6SSteve Lawrence (void) ct_tmpl_clear(tmpl_fd); 2273efd4c9b6SSteve Lawrence (void) close(tmpl_fd); 2274efd4c9b6SSteve Lawrence (void) close(p[0]); 2275efd4c9b6SSteve Lawrence if (zone->zsz_id != getzoneid()) { 2276efd4c9b6SSteve Lawrence if (zone_enter(zone->zsz_id) < 0) { 2277efd4c9b6SSteve Lawrence (void) close(p[1]); 2278efd4c9b6SSteve Lawrence _exit(0); 2279efd4c9b6SSteve Lawrence } 2280efd4c9b6SSteve Lawrence } 2281efd4c9b6SSteve Lawrence 2282efd4c9b6SSteve Lawrence /* Get caps for zone, and write them to zonestatd parent. */ 2283efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_limit("zone.cpu-shares"); 2284efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_limit("zone.cpu-cap"); 2285efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_limit("zone.max-locked-memory"); 2286efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_limit("zone.max-swap"); 2287efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_limit("zone.max-processes"); 2288efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_usage("zone.max-processes"); 2289efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_limit("zone.max-lwps"); 2290efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_usage("zone.max-lwps"); 2291efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_limit("zone.max-shm-memory"); 2292efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_usage("zone.max-shm-memory"); 2293efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_limit("zone.max-shm-ids"); 2294efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_usage("zone.max-shm-ids"); 2295efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_limit("zone.max-sem-ids"); 2296efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_usage("zone.max-sem-ids"); 2297efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_limit("zone.max-msg-ids"); 2298efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_usage("zone.max-msg-ids"); 2299efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_limit("zone.max-lofi"); 2300efd4c9b6SSteve Lawrence vals[i++] = zsd_get_zone_rctl_usage("zone.max-lofi"); 2301efd4c9b6SSteve Lawrence 2302efd4c9b6SSteve Lawrence if (write(p[1], vals, ZSD_NUM_RCTL_VALS * sizeof (uint64_t)) != 2303efd4c9b6SSteve Lawrence ZSD_NUM_RCTL_VALS * sizeof (uint64_t)) { 2304efd4c9b6SSteve Lawrence (void) close(p[1]); 2305efd4c9b6SSteve Lawrence _exit(1); 2306efd4c9b6SSteve Lawrence } 2307efd4c9b6SSteve Lawrence 2308efd4c9b6SSteve Lawrence (void) close(p[1]); 2309efd4c9b6SSteve Lawrence _exit(0); 2310efd4c9b6SSteve Lawrence } 2311efd4c9b6SSteve Lawrence if (contract_latest(&ct) == -1) 2312efd4c9b6SSteve Lawrence ct = -1; 2313efd4c9b6SSteve Lawrence 2314efd4c9b6SSteve Lawrence (void) ct_tmpl_clear(tmpl_fd); 2315efd4c9b6SSteve Lawrence (void) close(tmpl_fd); 2316efd4c9b6SSteve Lawrence (void) close(p[1]); 2317efd4c9b6SSteve Lawrence while (waitpid(pid, NULL, 0) != pid) 2318efd4c9b6SSteve Lawrence ; 2319efd4c9b6SSteve Lawrence 2320efd4c9b6SSteve Lawrence /* Read cap from child in zone */ 2321efd4c9b6SSteve Lawrence if (read(p[0], vals, ZSD_NUM_RCTL_VALS * sizeof (uint64_t)) != 2322efd4c9b6SSteve Lawrence ZSD_NUM_RCTL_VALS * sizeof (uint64_t)) { 2323efd4c9b6SSteve Lawrence res = -1; 2324efd4c9b6SSteve Lawrence goto cleanup; 2325efd4c9b6SSteve Lawrence } 2326efd4c9b6SSteve Lawrence i = 0; 2327efd4c9b6SSteve Lawrence *cpu_shares = vals[i++]; 2328efd4c9b6SSteve Lawrence *cpu_cap = vals[i++]; 2329efd4c9b6SSteve Lawrence *locked_cap = vals[i++]; 2330efd4c9b6SSteve Lawrence *vm_cap = vals[i++]; 2331efd4c9b6SSteve Lawrence *processes_cap = vals[i++]; 2332efd4c9b6SSteve Lawrence *processes = vals[i++]; 2333efd4c9b6SSteve Lawrence *lwps_cap = vals[i++]; 2334efd4c9b6SSteve Lawrence *lwps = vals[i++]; 2335efd4c9b6SSteve Lawrence *shm_cap = vals[i++]; 2336efd4c9b6SSteve Lawrence *shm = vals[i++]; 2337efd4c9b6SSteve Lawrence *shmids_cap = vals[i++]; 2338efd4c9b6SSteve Lawrence *shmids = vals[i++]; 2339efd4c9b6SSteve Lawrence *semids_cap = vals[i++]; 2340efd4c9b6SSteve Lawrence *semids = vals[i++]; 2341efd4c9b6SSteve Lawrence *msgids_cap = vals[i++]; 2342efd4c9b6SSteve Lawrence *msgids = vals[i++]; 2343efd4c9b6SSteve Lawrence *lofi_cap = vals[i++]; 2344efd4c9b6SSteve Lawrence *lofi = vals[i++]; 2345efd4c9b6SSteve Lawrence 2346efd4c9b6SSteve Lawrence /* Interpret maximum values as no cap */ 2347efd4c9b6SSteve Lawrence if (*cpu_cap == UINT32_MAX || *cpu_cap == 0) 2348efd4c9b6SSteve Lawrence *cpu_cap = ZS_LIMIT_NONE; 2349efd4c9b6SSteve Lawrence if (*processes_cap == sys->zss_processes_max) 2350efd4c9b6SSteve Lawrence *processes_cap = ZS_LIMIT_NONE; 2351efd4c9b6SSteve Lawrence if (*lwps_cap == sys->zss_lwps_max) 2352efd4c9b6SSteve Lawrence *lwps_cap = ZS_LIMIT_NONE; 2353efd4c9b6SSteve Lawrence if (*shm_cap == sys->zss_shm_max) 2354efd4c9b6SSteve Lawrence *shm_cap = ZS_LIMIT_NONE; 2355efd4c9b6SSteve Lawrence if (*shmids_cap == sys->zss_shmids_max) 2356efd4c9b6SSteve Lawrence *shmids_cap = ZS_LIMIT_NONE; 2357efd4c9b6SSteve Lawrence if (*semids_cap == sys->zss_semids_max) 2358efd4c9b6SSteve Lawrence *semids_cap = ZS_LIMIT_NONE; 2359efd4c9b6SSteve Lawrence if (*msgids_cap == sys->zss_msgids_max) 2360efd4c9b6SSteve Lawrence *msgids_cap = ZS_LIMIT_NONE; 2361efd4c9b6SSteve Lawrence if (*lofi_cap == sys->zss_lofi_max) 2362efd4c9b6SSteve Lawrence *lofi_cap = ZS_LIMIT_NONE; 2363efd4c9b6SSteve Lawrence 2364efd4c9b6SSteve Lawrence 2365efd4c9b6SSteve Lawrence cleanup: 2366efd4c9b6SSteve Lawrence (void) close(p[0]); 2367efd4c9b6SSteve Lawrence (void) ct_tmpl_clear(tmpl_fd); 2368efd4c9b6SSteve Lawrence (void) close(tmpl_fd); 2369efd4c9b6SSteve Lawrence (void) contract_abandon_id(ct); 2370efd4c9b6SSteve Lawrence 2371efd4c9b6SSteve Lawrence return (res); 2372efd4c9b6SSteve Lawrence } 2373efd4c9b6SSteve Lawrence 2374efd4c9b6SSteve Lawrence /* Update the current list of running zones */ 2375efd4c9b6SSteve Lawrence static void 2376efd4c9b6SSteve Lawrence zsd_refresh_zones(zsd_ctl_t *ctl) 2377efd4c9b6SSteve Lawrence { 2378efd4c9b6SSteve Lawrence zsd_zone_t *zone; 2379efd4c9b6SSteve Lawrence uint_t old, num; 2380efd4c9b6SSteve Lawrence ushort_t flags; 2381efd4c9b6SSteve Lawrence int i, ret; 2382efd4c9b6SSteve Lawrence zoneid_t *cache; 2383efd4c9b6SSteve Lawrence uint64_t cpu_shares; 2384efd4c9b6SSteve Lawrence uint64_t cpu_cap; 2385efd4c9b6SSteve Lawrence uint64_t ram_cap; 2386efd4c9b6SSteve Lawrence uint64_t locked_cap; 2387efd4c9b6SSteve Lawrence uint64_t vm_cap; 2388efd4c9b6SSteve Lawrence uint64_t processes_cap; 2389efd4c9b6SSteve Lawrence uint64_t processes; 2390efd4c9b6SSteve Lawrence uint64_t lwps_cap; 2391efd4c9b6SSteve Lawrence uint64_t lwps; 2392efd4c9b6SSteve Lawrence uint64_t shm_cap; 2393efd4c9b6SSteve Lawrence uint64_t shm; 2394efd4c9b6SSteve Lawrence uint64_t shmids_cap; 2395efd4c9b6SSteve Lawrence uint64_t shmids; 2396efd4c9b6SSteve Lawrence uint64_t semids_cap; 2397efd4c9b6SSteve Lawrence uint64_t semids; 2398efd4c9b6SSteve Lawrence uint64_t msgids_cap; 2399efd4c9b6SSteve Lawrence uint64_t msgids; 2400efd4c9b6SSteve Lawrence uint64_t lofi_cap; 2401efd4c9b6SSteve Lawrence uint64_t lofi; 2402efd4c9b6SSteve Lawrence 2403efd4c9b6SSteve Lawrence char zonename[ZS_ZONENAME_MAX]; 2404efd4c9b6SSteve Lawrence char poolname[ZS_POOLNAME_MAX]; 2405efd4c9b6SSteve Lawrence char psetname[ZS_PSETNAME_MAX]; 2406efd4c9b6SSteve Lawrence uint_t sched; 2407efd4c9b6SSteve Lawrence uint_t cputype; 2408efd4c9b6SSteve Lawrence uint_t iptype; 2409efd4c9b6SSteve Lawrence 2410efd4c9b6SSteve Lawrence /* Get the current list of running zones */ 2411efd4c9b6SSteve Lawrence for (;;) { 2412efd4c9b6SSteve Lawrence old = num = ctl->zsctl_zone_ncache; 2413efd4c9b6SSteve Lawrence (void) zone_list(ctl->zsctl_zone_cache, &num); 2414efd4c9b6SSteve Lawrence if (num <= old) 2415efd4c9b6SSteve Lawrence break; 2416efd4c9b6SSteve Lawrence if ((cache = (zoneid_t *)realloc(ctl->zsctl_zone_cache, 2417efd4c9b6SSteve Lawrence (num) * sizeof (zoneid_t))) != NULL) { 2418efd4c9b6SSteve Lawrence ctl->zsctl_zone_ncache = num; 2419efd4c9b6SSteve Lawrence ctl->zsctl_zone_cache = cache; 2420efd4c9b6SSteve Lawrence } else { 2421efd4c9b6SSteve Lawrence /* Could not allocate to get new zone list. Give up */ 2422efd4c9b6SSteve Lawrence return; 2423efd4c9b6SSteve Lawrence } 2424efd4c9b6SSteve Lawrence } 2425efd4c9b6SSteve Lawrence 2426efd4c9b6SSteve Lawrence zsd_mark_zones_start(ctl); 2427efd4c9b6SSteve Lawrence 2428efd4c9b6SSteve Lawrence for (i = 0; i < num; i++) { 2429efd4c9b6SSteve Lawrence 2430efd4c9b6SSteve Lawrence ret = getzonenamebyid(ctl->zsctl_zone_cache[i], 2431efd4c9b6SSteve Lawrence zonename, sizeof (zonename)); 2432efd4c9b6SSteve Lawrence if (ret < 0) 2433efd4c9b6SSteve Lawrence continue; 2434efd4c9b6SSteve Lawrence 2435efd4c9b6SSteve Lawrence zone = zsd_lookup_insert_zone(ctl, zonename, 2436efd4c9b6SSteve Lawrence ctl->zsctl_zone_cache[i]); 2437efd4c9b6SSteve Lawrence 2438efd4c9b6SSteve Lawrence ret = zone_getattr(ctl->zsctl_zone_cache[i], ZONE_ATTR_FLAGS, 2439efd4c9b6SSteve Lawrence &flags, sizeof (flags)); 2440efd4c9b6SSteve Lawrence if (ret < 0) 2441efd4c9b6SSteve Lawrence continue; 2442efd4c9b6SSteve Lawrence 2443efd4c9b6SSteve Lawrence if (flags & ZF_NET_EXCL) 2444efd4c9b6SSteve Lawrence iptype = ZS_IPTYPE_EXCLUSIVE; 2445efd4c9b6SSteve Lawrence else 2446efd4c9b6SSteve Lawrence iptype = ZS_IPTYPE_SHARED; 2447efd4c9b6SSteve Lawrence 2448efd4c9b6SSteve Lawrence zsd_get_zone_pool_pset(ctl, zone, poolname, sizeof (poolname), 2449efd4c9b6SSteve Lawrence psetname, sizeof (psetname), &cputype); 2450efd4c9b6SSteve Lawrence 2451efd4c9b6SSteve Lawrence if (zsd_get_zone_caps(ctl, zone, &cpu_shares, &cpu_cap, 2452efd4c9b6SSteve Lawrence &ram_cap, &locked_cap, &vm_cap, &processes_cap, &processes, 2453efd4c9b6SSteve Lawrence &lwps_cap, &lwps, &shm_cap, &shm, &shmids_cap, &shmids, 2454efd4c9b6SSteve Lawrence &semids_cap, &semids, &msgids_cap, &msgids, &lofi_cap, 2455efd4c9b6SSteve Lawrence &lofi, &sched) != 0) 2456efd4c9b6SSteve Lawrence continue; 2457efd4c9b6SSteve Lawrence 2458efd4c9b6SSteve Lawrence zsd_mark_zone_found(ctl, zone, cpu_shares, cpu_cap, ram_cap, 2459efd4c9b6SSteve Lawrence locked_cap, vm_cap, processes_cap, processes, lwps_cap, 2460efd4c9b6SSteve Lawrence lwps, shm_cap, shm, shmids_cap, shmids, semids_cap, 2461efd4c9b6SSteve Lawrence semids, msgids_cap, msgids, lofi_cap, lofi, poolname, 2462efd4c9b6SSteve Lawrence psetname, sched, cputype, iptype); 2463efd4c9b6SSteve Lawrence } 2464efd4c9b6SSteve Lawrence } 2465efd4c9b6SSteve Lawrence 2466efd4c9b6SSteve Lawrence /* Fetch the details of a process from its psinfo_t */ 2467efd4c9b6SSteve Lawrence static void 2468efd4c9b6SSteve Lawrence zsd_get_proc_info(zsd_ctl_t *ctl, psinfo_t *psinfo, psetid_t *psetid, 2469efd4c9b6SSteve Lawrence psetid_t *prev_psetid, zoneid_t *zoneid, zoneid_t *prev_zoneid, 2470efd4c9b6SSteve Lawrence timestruc_t *delta, uint_t *sched) 2471efd4c9b6SSteve Lawrence { 2472efd4c9b6SSteve Lawrence timestruc_t d; 2473efd4c9b6SSteve Lawrence zsd_proc_t *proc; 2474efd4c9b6SSteve Lawrence 2475efd4c9b6SSteve Lawrence /* Get cached data for proc */ 2476efd4c9b6SSteve Lawrence proc = &(ctl->zsctl_proc_array[psinfo->pr_pid]); 2477efd4c9b6SSteve Lawrence *psetid = psinfo->pr_lwp.pr_bindpset; 2478efd4c9b6SSteve Lawrence 2479efd4c9b6SSteve Lawrence if (proc->zspr_psetid == ZS_PSET_ERROR) 2480efd4c9b6SSteve Lawrence *prev_psetid = *psetid; 2481efd4c9b6SSteve Lawrence else 2482efd4c9b6SSteve Lawrence *prev_psetid = proc->zspr_psetid; 2483efd4c9b6SSteve Lawrence 2484efd4c9b6SSteve Lawrence *zoneid = psinfo->pr_zoneid; 2485efd4c9b6SSteve Lawrence if (proc->zspr_zoneid == -1) 2486efd4c9b6SSteve Lawrence *prev_zoneid = *zoneid; 2487efd4c9b6SSteve Lawrence else 2488efd4c9b6SSteve Lawrence *prev_zoneid = proc->zspr_zoneid; 2489efd4c9b6SSteve Lawrence 2490efd4c9b6SSteve Lawrence TIMESTRUC_DELTA(d, psinfo->pr_time, proc->zspr_usage); 2491efd4c9b6SSteve Lawrence *delta = d; 2492efd4c9b6SSteve Lawrence 2493efd4c9b6SSteve Lawrence *sched = zsd_schedname2int(psinfo->pr_lwp.pr_clname, 2494efd4c9b6SSteve Lawrence psinfo->pr_lwp.pr_pri); 2495efd4c9b6SSteve Lawrence 2496efd4c9b6SSteve Lawrence /* Update cached data for proc */ 2497efd4c9b6SSteve Lawrence proc->zspr_psetid = psinfo->pr_lwp.pr_bindpset; 2498efd4c9b6SSteve Lawrence proc->zspr_zoneid = psinfo->pr_zoneid; 2499efd4c9b6SSteve Lawrence proc->zspr_sched = *sched; 2500efd4c9b6SSteve Lawrence proc->zspr_usage.tv_sec = psinfo->pr_time.tv_sec; 2501efd4c9b6SSteve Lawrence proc->zspr_usage.tv_nsec = psinfo->pr_time.tv_nsec; 2502efd4c9b6SSteve Lawrence proc->zspr_ppid = psinfo->pr_ppid; 2503efd4c9b6SSteve Lawrence } 2504efd4c9b6SSteve Lawrence 2505efd4c9b6SSteve Lawrence /* 2506efd4c9b6SSteve Lawrence * Reset the known cpu usage of a process. This is done after a process 2507efd4c9b6SSteve Lawrence * exits so that if the pid is recycled, data from its previous life is 2508efd4c9b6SSteve Lawrence * not reused 2509efd4c9b6SSteve Lawrence */ 2510efd4c9b6SSteve Lawrence static void 2511efd4c9b6SSteve Lawrence zsd_flush_proc_info(zsd_proc_t *proc) 2512efd4c9b6SSteve Lawrence { 2513efd4c9b6SSteve Lawrence proc->zspr_usage.tv_sec = 0; 2514efd4c9b6SSteve Lawrence proc->zspr_usage.tv_nsec = 0; 2515efd4c9b6SSteve Lawrence } 2516efd4c9b6SSteve Lawrence 2517efd4c9b6SSteve Lawrence /* 2518efd4c9b6SSteve Lawrence * Open the current extended accounting file. On initialization, open the 2519efd4c9b6SSteve Lawrence * file as the current file to be used. Otherwise, open the file as the 2520efd4c9b6SSteve Lawrence * next file to use of the current file reaches EOF. 2521efd4c9b6SSteve Lawrence */ 2522efd4c9b6SSteve Lawrence static int 2523efd4c9b6SSteve Lawrence zsd_open_exacct(zsd_ctl_t *ctl, boolean_t init) 2524efd4c9b6SSteve Lawrence { 2525efd4c9b6SSteve Lawrence int ret, oret, state, trys = 0, flags; 2526efd4c9b6SSteve Lawrence int *fd, *open; 2527efd4c9b6SSteve Lawrence ea_file_t *eaf; 2528efd4c9b6SSteve Lawrence struct stat64 *stat; 2529efd4c9b6SSteve Lawrence char path[MAXPATHLEN]; 2530efd4c9b6SSteve Lawrence 2531efd4c9b6SSteve Lawrence /* 2532efd4c9b6SSteve Lawrence * The accounting file is first opened at the tail. Following 2533efd4c9b6SSteve Lawrence * opens to new accounting files are opened at the head. 2534efd4c9b6SSteve Lawrence */ 2535efd4c9b6SSteve Lawrence if (init == B_TRUE) { 2536efd4c9b6SSteve Lawrence flags = EO_NO_VALID_HDR | EO_TAIL; 2537efd4c9b6SSteve Lawrence fd = &ctl->zsctl_proc_fd; 2538efd4c9b6SSteve Lawrence eaf = &ctl->zsctl_proc_eaf; 2539efd4c9b6SSteve Lawrence stat = &ctl->zsctl_proc_stat; 2540efd4c9b6SSteve Lawrence open = &ctl->zsctl_proc_open; 2541efd4c9b6SSteve Lawrence } else { 2542efd4c9b6SSteve Lawrence flags = EO_NO_VALID_HDR | EO_HEAD; 2543efd4c9b6SSteve Lawrence fd = &ctl->zsctl_proc_fd_next; 2544efd4c9b6SSteve Lawrence eaf = &ctl->zsctl_proc_eaf_next; 2545efd4c9b6SSteve Lawrence stat = &ctl->zsctl_proc_stat_next; 2546efd4c9b6SSteve Lawrence open = &ctl->zsctl_proc_open_next; 2547efd4c9b6SSteve Lawrence } 2548efd4c9b6SSteve Lawrence 2549efd4c9b6SSteve Lawrence *fd = -1; 2550efd4c9b6SSteve Lawrence *open = 0; 2551efd4c9b6SSteve Lawrence retry: 2552efd4c9b6SSteve Lawrence /* open accounting files for cpu consumption */ 2553efd4c9b6SSteve Lawrence ret = acctctl(AC_STATE_GET | AC_PROC, &state, sizeof (state)); 2554efd4c9b6SSteve Lawrence if (ret != 0) { 2555efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to get process accounting state")); 2556efd4c9b6SSteve Lawrence goto err; 2557efd4c9b6SSteve Lawrence } 2558efd4c9b6SSteve Lawrence if (state != AC_ON) { 2559efd4c9b6SSteve Lawrence if (trys > 0) { 2560efd4c9b6SSteve Lawrence zsd_warn(gettext( 2561efd4c9b6SSteve Lawrence "Unable to enable process accounting")); 2562efd4c9b6SSteve Lawrence goto err; 2563efd4c9b6SSteve Lawrence } 2564efd4c9b6SSteve Lawrence (void) zsd_enable_cpu_stats(); 2565efd4c9b6SSteve Lawrence trys++; 2566efd4c9b6SSteve Lawrence goto retry; 2567efd4c9b6SSteve Lawrence } 2568efd4c9b6SSteve Lawrence 2569efd4c9b6SSteve Lawrence ret = acctctl(AC_FILE_GET | AC_PROC, path, sizeof (path)); 2570efd4c9b6SSteve Lawrence if (ret != 0) { 2571efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to get process accounting file")); 2572efd4c9b6SSteve Lawrence goto err; 2573efd4c9b6SSteve Lawrence } 2574efd4c9b6SSteve Lawrence 2575efd4c9b6SSteve Lawrence if ((*fd = open64(path, O_RDONLY, 0)) >= 0 && 2576efd4c9b6SSteve Lawrence (oret = ea_fdopen(eaf, *fd, NULL, flags, O_RDONLY)) == 0) 2577efd4c9b6SSteve Lawrence ret = fstat64(*fd, stat); 2578efd4c9b6SSteve Lawrence 2579efd4c9b6SSteve Lawrence if (*fd < 0 || oret < 0 || ret < 0) { 2580efd4c9b6SSteve Lawrence struct timespec ts; 2581efd4c9b6SSteve Lawrence 2582efd4c9b6SSteve Lawrence /* 2583efd4c9b6SSteve Lawrence * It is possible the accounting file is momentarily unavailable 2584efd4c9b6SSteve Lawrence * because it is being rolled. Try for up to half a second. 2585efd4c9b6SSteve Lawrence * 2586efd4c9b6SSteve Lawrence * If failure to open accounting file persists, give up. 2587efd4c9b6SSteve Lawrence */ 2588efd4c9b6SSteve Lawrence if (oret == 0) 2589efd4c9b6SSteve Lawrence (void) ea_close(eaf); 2590efd4c9b6SSteve Lawrence else if (*fd >= 0) 2591efd4c9b6SSteve Lawrence (void) close(*fd); 2592efd4c9b6SSteve Lawrence if (trys > 500) { 2593efd4c9b6SSteve Lawrence zsd_warn(gettext( 2594efd4c9b6SSteve Lawrence "Unable to open process accounting file")); 2595efd4c9b6SSteve Lawrence goto err; 2596efd4c9b6SSteve Lawrence } 2597efd4c9b6SSteve Lawrence /* wait one millisecond */ 2598efd4c9b6SSteve Lawrence ts.tv_sec = 0; 2599efd4c9b6SSteve Lawrence ts.tv_nsec = NANOSEC / 1000; 2600efd4c9b6SSteve Lawrence (void) nanosleep(&ts, NULL); 2601efd4c9b6SSteve Lawrence goto retry; 2602efd4c9b6SSteve Lawrence } 2603efd4c9b6SSteve Lawrence *open = 1; 2604efd4c9b6SSteve Lawrence return (0); 2605efd4c9b6SSteve Lawrence err: 2606efd4c9b6SSteve Lawrence if (*fd >= 0) 2607efd4c9b6SSteve Lawrence (void) close(*fd); 2608efd4c9b6SSteve Lawrence *open = 0; 2609efd4c9b6SSteve Lawrence *fd = -1; 2610efd4c9b6SSteve Lawrence return (-1); 2611efd4c9b6SSteve Lawrence } 2612efd4c9b6SSteve Lawrence 2613efd4c9b6SSteve Lawrence /* 2614efd4c9b6SSteve Lawrence * Walk /proc and charge each process to its zone and processor set. 2615efd4c9b6SSteve Lawrence * Then read exacct data for exited processes, and charge them as well. 2616efd4c9b6SSteve Lawrence */ 2617efd4c9b6SSteve Lawrence static void 2618efd4c9b6SSteve Lawrence zsd_refresh_procs(zsd_ctl_t *ctl, boolean_t init) 2619efd4c9b6SSteve Lawrence { 2620efd4c9b6SSteve Lawrence DIR *dir; 2621efd4c9b6SSteve Lawrence struct dirent *dent; 2622efd4c9b6SSteve Lawrence psinfo_t psinfo; 2623efd4c9b6SSteve Lawrence int fd, ret; 2624efd4c9b6SSteve Lawrence zsd_proc_t *proc, *pproc, *tmp, *next; 2625efd4c9b6SSteve Lawrence list_t pplist, plist; 2626efd4c9b6SSteve Lawrence zsd_zone_t *zone, *prev_zone; 2627efd4c9b6SSteve Lawrence zsd_pset_t *pset, *prev_pset; 2628efd4c9b6SSteve Lawrence psetid_t psetid, prev_psetid; 2629efd4c9b6SSteve Lawrence zoneid_t zoneid, prev_zoneid; 2630efd4c9b6SSteve Lawrence zsd_pset_usage_t *usage, *prev_usage; 2631efd4c9b6SSteve Lawrence char path[MAXPATHLEN]; 2632efd4c9b6SSteve Lawrence 2633efd4c9b6SSteve Lawrence ea_object_t object; 2634efd4c9b6SSteve Lawrence ea_object_t pobject; 2635efd4c9b6SSteve Lawrence boolean_t hrtime_expired = B_FALSE; 2636efd4c9b6SSteve Lawrence struct timeval interval_end; 2637efd4c9b6SSteve Lawrence 2638efd4c9b6SSteve Lawrence timestruc_t delta, d1, d2; 2639efd4c9b6SSteve Lawrence uint_t sched = 0; 2640efd4c9b6SSteve Lawrence 2641efd4c9b6SSteve Lawrence /* 2642efd4c9b6SSteve Lawrence * Get the current accounting file. The current accounting file 2643efd4c9b6SSteve Lawrence * may be different than the file in use, as the accounting file 2644efd4c9b6SSteve Lawrence * may have been rolled, or manually changed by an admin. 2645efd4c9b6SSteve Lawrence */ 2646efd4c9b6SSteve Lawrence ret = zsd_open_exacct(ctl, init); 2647efd4c9b6SSteve Lawrence if (ret != 0) { 2648efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to track process accounting")); 2649efd4c9b6SSteve Lawrence return; 2650efd4c9b6SSteve Lawrence } 2651efd4c9b6SSteve Lawrence 2652efd4c9b6SSteve Lawrence /* 2653efd4c9b6SSteve Lawrence * Mark the current time as the interval end time. Don't track 2654efd4c9b6SSteve Lawrence * processes that exit after this time. 2655efd4c9b6SSteve Lawrence */ 2656efd4c9b6SSteve Lawrence (void) gettimeofday(&interval_end, NULL); 2657efd4c9b6SSteve Lawrence 2658efd4c9b6SSteve Lawrence dir = opendir("/proc"); 2659efd4c9b6SSteve Lawrence if (dir == NULL) { 2660efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to open /proc")); 2661efd4c9b6SSteve Lawrence return; 2662efd4c9b6SSteve Lawrence } 2663efd4c9b6SSteve Lawrence 2664efd4c9b6SSteve Lawrence dent = ctl->zsctl_procfs_dent; 2665efd4c9b6SSteve Lawrence 2666efd4c9b6SSteve Lawrence (void) memset(dent, 0, ctl->zsctl_procfs_dent_size); 2667efd4c9b6SSteve Lawrence 2668efd4c9b6SSteve Lawrence /* Walk all processes and compute each zone's usage on each pset. */ 2669efd4c9b6SSteve Lawrence while (readdir_r(dir, dent) != 0) { 2670efd4c9b6SSteve Lawrence 2671efd4c9b6SSteve Lawrence if (strcmp(dent->d_name, ".") == 0 || 2672efd4c9b6SSteve Lawrence strcmp(dent->d_name, "..") == 0) 2673efd4c9b6SSteve Lawrence continue; 2674efd4c9b6SSteve Lawrence 2675efd4c9b6SSteve Lawrence (void) snprintf(path, sizeof (path), "/proc/%s/psinfo", 2676efd4c9b6SSteve Lawrence dent->d_name); 2677efd4c9b6SSteve Lawrence 2678efd4c9b6SSteve Lawrence fd = open(path, O_RDONLY); 2679efd4c9b6SSteve Lawrence if (fd < 0) 2680efd4c9b6SSteve Lawrence continue; 2681efd4c9b6SSteve Lawrence 2682efd4c9b6SSteve Lawrence if (read(fd, &psinfo, sizeof (psinfo)) != sizeof (psinfo)) { 2683efd4c9b6SSteve Lawrence (void) close(fd); 2684efd4c9b6SSteve Lawrence continue; 2685efd4c9b6SSteve Lawrence } 2686efd4c9b6SSteve Lawrence (void) close(fd); 2687efd4c9b6SSteve Lawrence 2688efd4c9b6SSteve Lawrence zsd_get_proc_info(ctl, &psinfo, &psetid, &prev_psetid, 2689efd4c9b6SSteve Lawrence &zoneid, &prev_zoneid, &delta, &sched); 2690efd4c9b6SSteve Lawrence 2691efd4c9b6SSteve Lawrence d1.tv_sec = delta.tv_sec / 2; 2692efd4c9b6SSteve Lawrence d1.tv_nsec = delta.tv_nsec / 2; 2693efd4c9b6SSteve Lawrence d2.tv_sec = (delta.tv_sec / 2) + (delta.tv_sec % 2); 2694efd4c9b6SSteve Lawrence d2.tv_nsec = (delta.tv_nsec / 2) + (delta.tv_nsec % 2); 2695efd4c9b6SSteve Lawrence 2696efd4c9b6SSteve Lawrence /* Get the zone and pset this process is running in */ 2697efd4c9b6SSteve Lawrence zone = zsd_lookup_zone_byid(ctl, zoneid); 2698efd4c9b6SSteve Lawrence if (zone == NULL) 2699efd4c9b6SSteve Lawrence continue; 2700efd4c9b6SSteve Lawrence pset = zsd_lookup_pset_byid(ctl, psetid); 2701efd4c9b6SSteve Lawrence if (pset == NULL) 2702efd4c9b6SSteve Lawrence continue; 2703efd4c9b6SSteve Lawrence usage = zsd_lookup_insert_usage(ctl, pset, zone); 2704efd4c9b6SSteve Lawrence if (usage == NULL) 2705efd4c9b6SSteve Lawrence continue; 2706efd4c9b6SSteve Lawrence 2707efd4c9b6SSteve Lawrence /* 2708efd4c9b6SSteve Lawrence * Get the usage of the previous zone and pset if they were 2709efd4c9b6SSteve Lawrence * different. 2710efd4c9b6SSteve Lawrence */ 2711efd4c9b6SSteve Lawrence if (zoneid != prev_zoneid) 2712efd4c9b6SSteve Lawrence prev_zone = zsd_lookup_zone_byid(ctl, prev_zoneid); 2713efd4c9b6SSteve Lawrence else 2714efd4c9b6SSteve Lawrence prev_zone = NULL; 2715efd4c9b6SSteve Lawrence 2716efd4c9b6SSteve Lawrence if (psetid != prev_psetid) 2717efd4c9b6SSteve Lawrence prev_pset = zsd_lookup_pset_byid(ctl, prev_psetid); 2718efd4c9b6SSteve Lawrence else 2719efd4c9b6SSteve Lawrence prev_pset = NULL; 2720efd4c9b6SSteve Lawrence 2721efd4c9b6SSteve Lawrence prev_usage = NULL; 2722efd4c9b6SSteve Lawrence if (prev_zone != NULL || prev_pset != NULL) { 2723efd4c9b6SSteve Lawrence if (prev_zone == NULL) 2724efd4c9b6SSteve Lawrence prev_zone = zone; 2725efd4c9b6SSteve Lawrence if (prev_pset == NULL) 2726efd4c9b6SSteve Lawrence prev_pset = pset; 2727efd4c9b6SSteve Lawrence 2728efd4c9b6SSteve Lawrence prev_usage = zsd_lookup_insert_usage(ctl, prev_pset, 2729efd4c9b6SSteve Lawrence prev_zone); 2730efd4c9b6SSteve Lawrence } 2731efd4c9b6SSteve Lawrence 2732efd4c9b6SSteve Lawrence /* Update the usage with the processes info */ 2733efd4c9b6SSteve Lawrence if (prev_usage == NULL) { 2734efd4c9b6SSteve Lawrence zsd_mark_pset_usage_found(usage, sched); 2735efd4c9b6SSteve Lawrence } else { 2736efd4c9b6SSteve Lawrence zsd_mark_pset_usage_found(usage, sched); 2737efd4c9b6SSteve Lawrence zsd_mark_pset_usage_found(prev_usage, sched); 2738efd4c9b6SSteve Lawrence } 2739efd4c9b6SSteve Lawrence 2740efd4c9b6SSteve Lawrence /* 2741efd4c9b6SSteve Lawrence * First time around is just to get a starting point. All 2742efd4c9b6SSteve Lawrence * usages will be zero. 2743efd4c9b6SSteve Lawrence */ 2744efd4c9b6SSteve Lawrence if (init == B_TRUE) 2745efd4c9b6SSteve Lawrence continue; 2746efd4c9b6SSteve Lawrence 2747efd4c9b6SSteve Lawrence if (prev_usage == NULL) { 2748efd4c9b6SSteve Lawrence zsd_add_usage(ctl, usage, &delta); 2749efd4c9b6SSteve Lawrence } else { 2750efd4c9b6SSteve Lawrence zsd_add_usage(ctl, usage, &d1); 2751efd4c9b6SSteve Lawrence zsd_add_usage(ctl, prev_usage, &d2); 2752efd4c9b6SSteve Lawrence } 2753efd4c9b6SSteve Lawrence } 2754efd4c9b6SSteve Lawrence (void) closedir(dir); 2755efd4c9b6SSteve Lawrence 2756efd4c9b6SSteve Lawrence /* 2757efd4c9b6SSteve Lawrence * No need to collect exited proc data on initialization. Just 2758efd4c9b6SSteve Lawrence * caching the usage of the known processes to get a zero starting 2759efd4c9b6SSteve Lawrence * point. 2760efd4c9b6SSteve Lawrence */ 2761efd4c9b6SSteve Lawrence if (init == B_TRUE) 2762efd4c9b6SSteve Lawrence return; 2763efd4c9b6SSteve Lawrence 2764efd4c9b6SSteve Lawrence /* 2765efd4c9b6SSteve Lawrence * Add accounting records to account for processes which have 2766efd4c9b6SSteve Lawrence * exited. 2767efd4c9b6SSteve Lawrence */ 2768efd4c9b6SSteve Lawrence list_create(&plist, sizeof (zsd_proc_t), 2769efd4c9b6SSteve Lawrence offsetof(zsd_proc_t, zspr_next)); 2770efd4c9b6SSteve Lawrence list_create(&pplist, sizeof (zsd_proc_t), 2771efd4c9b6SSteve Lawrence offsetof(zsd_proc_t, zspr_next)); 2772efd4c9b6SSteve Lawrence 2773efd4c9b6SSteve Lawrence for (;;) { 2774efd4c9b6SSteve Lawrence pid_t pid; 2775efd4c9b6SSteve Lawrence pid_t ppid; 2776efd4c9b6SSteve Lawrence timestruc_t user, sys, proc_usage; 2777efd4c9b6SSteve Lawrence timestruc_t finish; 2778efd4c9b6SSteve Lawrence int numfound = 0; 2779efd4c9b6SSteve Lawrence 2780efd4c9b6SSteve Lawrence bzero(&object, sizeof (object)); 2781efd4c9b6SSteve Lawrence proc = NULL; 2782efd4c9b6SSteve Lawrence zone = NULL; 2783efd4c9b6SSteve Lawrence pset = NULL; 2784efd4c9b6SSteve Lawrence usage = NULL; 2785efd4c9b6SSteve Lawrence ret = ea_get_object(&ctl->zsctl_proc_eaf, &object); 2786efd4c9b6SSteve Lawrence if (ret == EO_ERROR) { 2787efd4c9b6SSteve Lawrence if (ea_error() == EXR_EOF) { 2788efd4c9b6SSteve Lawrence 2789efd4c9b6SSteve Lawrence struct stat64 *stat; 2790efd4c9b6SSteve Lawrence struct stat64 *stat_next; 2791efd4c9b6SSteve Lawrence 2792efd4c9b6SSteve Lawrence /* 2793efd4c9b6SSteve Lawrence * See if the next accounting file is the 2794efd4c9b6SSteve Lawrence * same as the current accounting file. 2795efd4c9b6SSteve Lawrence */ 2796efd4c9b6SSteve Lawrence stat = &(ctl->zsctl_proc_stat); 2797efd4c9b6SSteve Lawrence stat_next = &(ctl->zsctl_proc_stat_next); 2798efd4c9b6SSteve Lawrence if (stat->st_ino == stat_next->st_ino && 2799efd4c9b6SSteve Lawrence stat->st_dev == stat_next->st_dev) { 2800efd4c9b6SSteve Lawrence /* 2801efd4c9b6SSteve Lawrence * End of current accounting file is 2802efd4c9b6SSteve Lawrence * reached, so finished. Clear EOF 2803efd4c9b6SSteve Lawrence * bit for next time around. 2804efd4c9b6SSteve Lawrence */ 2805efd4c9b6SSteve Lawrence ea_clear(&ctl->zsctl_proc_eaf); 2806efd4c9b6SSteve Lawrence break; 2807efd4c9b6SSteve Lawrence } else { 2808efd4c9b6SSteve Lawrence /* 2809efd4c9b6SSteve Lawrence * Accounting file has changed. Move 2810efd4c9b6SSteve Lawrence * to current accounting file. 2811efd4c9b6SSteve Lawrence */ 2812efd4c9b6SSteve Lawrence (void) ea_close(&ctl->zsctl_proc_eaf); 2813efd4c9b6SSteve Lawrence 2814efd4c9b6SSteve Lawrence ctl->zsctl_proc_fd = 2815efd4c9b6SSteve Lawrence ctl->zsctl_proc_fd_next; 2816efd4c9b6SSteve Lawrence ctl->zsctl_proc_eaf = 2817efd4c9b6SSteve Lawrence ctl->zsctl_proc_eaf_next; 2818efd4c9b6SSteve Lawrence ctl->zsctl_proc_stat = 2819efd4c9b6SSteve Lawrence ctl->zsctl_proc_stat_next; 2820efd4c9b6SSteve Lawrence 2821efd4c9b6SSteve Lawrence ctl->zsctl_proc_fd_next = -1; 2822efd4c9b6SSteve Lawrence ctl->zsctl_proc_open_next = 0; 2823efd4c9b6SSteve Lawrence continue; 2824efd4c9b6SSteve Lawrence } 2825efd4c9b6SSteve Lawrence } else { 2826efd4c9b6SSteve Lawrence /* 2827efd4c9b6SSteve Lawrence * Other accounting error. Give up on 2828efd4c9b6SSteve Lawrence * accounting. 2829efd4c9b6SSteve Lawrence */ 2830efd4c9b6SSteve Lawrence goto ea_err; 2831efd4c9b6SSteve Lawrence } 2832efd4c9b6SSteve Lawrence } 2833efd4c9b6SSteve Lawrence /* Skip if not a process group */ 2834efd4c9b6SSteve Lawrence if ((object.eo_catalog & EXT_TYPE_MASK) != EXT_GROUP || 2835efd4c9b6SSteve Lawrence (object.eo_catalog & EXD_DATA_MASK) != EXD_GROUP_PROC) { 2836efd4c9b6SSteve Lawrence (void) ea_free_item(&object, EUP_ALLOC); 2837efd4c9b6SSteve Lawrence continue; 2838efd4c9b6SSteve Lawrence } 2839efd4c9b6SSteve Lawrence 2840efd4c9b6SSteve Lawrence /* The process group entry should be complete */ 2841efd4c9b6SSteve Lawrence while (numfound < 9) { 2842efd4c9b6SSteve Lawrence bzero(&pobject, sizeof (pobject)); 2843efd4c9b6SSteve Lawrence ret = ea_get_object(&ctl->zsctl_proc_eaf, 2844efd4c9b6SSteve Lawrence &pobject); 2845efd4c9b6SSteve Lawrence if (ret < 0) { 2846efd4c9b6SSteve Lawrence (void) ea_free_item(&object, EUP_ALLOC); 2847efd4c9b6SSteve Lawrence zsd_warn( 2848efd4c9b6SSteve Lawrence "unable to get process accounting data"); 2849efd4c9b6SSteve Lawrence goto ea_err; 2850efd4c9b6SSteve Lawrence } 2851efd4c9b6SSteve Lawrence /* Next entries should be process data */ 2852efd4c9b6SSteve Lawrence if ((pobject.eo_catalog & EXT_TYPE_MASK) == 2853efd4c9b6SSteve Lawrence EXT_GROUP) { 2854efd4c9b6SSteve Lawrence (void) ea_free_item(&object, EUP_ALLOC); 2855efd4c9b6SSteve Lawrence (void) ea_free_item(&pobject, EUP_ALLOC); 2856efd4c9b6SSteve Lawrence zsd_warn( 2857efd4c9b6SSteve Lawrence "process data of wrong type"); 2858efd4c9b6SSteve Lawrence goto ea_err; 2859efd4c9b6SSteve Lawrence } 2860efd4c9b6SSteve Lawrence switch (pobject.eo_catalog & EXD_DATA_MASK) { 2861efd4c9b6SSteve Lawrence case EXD_PROC_PID: 2862efd4c9b6SSteve Lawrence pid = pobject.eo_item.ei_uint32; 2863efd4c9b6SSteve Lawrence proc = &(ctl->zsctl_proc_array[pid]); 2864efd4c9b6SSteve Lawrence /* 2865efd4c9b6SSteve Lawrence * This process should not be currently in 2866efd4c9b6SSteve Lawrence * the list of processes to process. 2867efd4c9b6SSteve Lawrence */ 2868efd4c9b6SSteve Lawrence assert(!list_link_active(&proc->zspr_next)); 2869efd4c9b6SSteve Lawrence numfound++; 2870efd4c9b6SSteve Lawrence break; 2871efd4c9b6SSteve Lawrence case EXD_PROC_ANCPID: 2872efd4c9b6SSteve Lawrence ppid = pobject.eo_item.ei_uint32; 2873efd4c9b6SSteve Lawrence pproc = &(ctl->zsctl_proc_array[ppid]); 2874efd4c9b6SSteve Lawrence numfound++; 2875efd4c9b6SSteve Lawrence break; 2876efd4c9b6SSteve Lawrence case EXD_PROC_ZONENAME: 2877efd4c9b6SSteve Lawrence zone = zsd_lookup_zone(ctl, 2878efd4c9b6SSteve Lawrence pobject.eo_item.ei_string, -1); 2879efd4c9b6SSteve Lawrence numfound++; 2880efd4c9b6SSteve Lawrence break; 2881efd4c9b6SSteve Lawrence case EXD_PROC_CPU_USER_SEC: 2882efd4c9b6SSteve Lawrence user.tv_sec = 2883efd4c9b6SSteve Lawrence pobject.eo_item.ei_uint64; 2884efd4c9b6SSteve Lawrence numfound++; 2885efd4c9b6SSteve Lawrence break; 2886efd4c9b6SSteve Lawrence case EXD_PROC_CPU_USER_NSEC: 2887efd4c9b6SSteve Lawrence user.tv_nsec = 2888efd4c9b6SSteve Lawrence pobject.eo_item.ei_uint64; 2889efd4c9b6SSteve Lawrence numfound++; 2890efd4c9b6SSteve Lawrence break; 2891efd4c9b6SSteve Lawrence case EXD_PROC_CPU_SYS_SEC: 2892efd4c9b6SSteve Lawrence sys.tv_sec = 2893efd4c9b6SSteve Lawrence pobject.eo_item.ei_uint64; 2894efd4c9b6SSteve Lawrence numfound++; 2895efd4c9b6SSteve Lawrence break; 2896efd4c9b6SSteve Lawrence case EXD_PROC_CPU_SYS_NSEC: 2897efd4c9b6SSteve Lawrence sys.tv_nsec = 2898efd4c9b6SSteve Lawrence pobject.eo_item.ei_uint64; 2899efd4c9b6SSteve Lawrence numfound++; 2900efd4c9b6SSteve Lawrence break; 2901efd4c9b6SSteve Lawrence case EXD_PROC_FINISH_SEC: 2902efd4c9b6SSteve Lawrence finish.tv_sec = 2903efd4c9b6SSteve Lawrence pobject.eo_item.ei_uint64; 2904efd4c9b6SSteve Lawrence numfound++; 2905efd4c9b6SSteve Lawrence break; 2906efd4c9b6SSteve Lawrence case EXD_PROC_FINISH_NSEC: 2907efd4c9b6SSteve Lawrence finish.tv_nsec = 2908efd4c9b6SSteve Lawrence pobject.eo_item.ei_uint64; 2909efd4c9b6SSteve Lawrence numfound++; 2910efd4c9b6SSteve Lawrence break; 2911efd4c9b6SSteve Lawrence } 2912efd4c9b6SSteve Lawrence (void) ea_free_item(&pobject, EUP_ALLOC); 2913efd4c9b6SSteve Lawrence } 2914efd4c9b6SSteve Lawrence (void) ea_free_item(&object, EUP_ALLOC); 2915efd4c9b6SSteve Lawrence if (numfound != 9) { 2916efd4c9b6SSteve Lawrence zsd_warn(gettext( 2917efd4c9b6SSteve Lawrence "Malformed process accounting entry found")); 2918efd4c9b6SSteve Lawrence goto proc_done; 2919efd4c9b6SSteve Lawrence } 2920efd4c9b6SSteve Lawrence 2921efd4c9b6SSteve Lawrence if (finish.tv_sec > interval_end.tv_sec || 2922efd4c9b6SSteve Lawrence (finish.tv_sec == interval_end.tv_sec && 2923efd4c9b6SSteve Lawrence finish.tv_nsec > (interval_end.tv_usec * 1000))) 2924efd4c9b6SSteve Lawrence hrtime_expired = B_TRUE; 2925efd4c9b6SSteve Lawrence 2926efd4c9b6SSteve Lawrence /* 2927efd4c9b6SSteve Lawrence * Try to identify the zone and pset to which this 2928efd4c9b6SSteve Lawrence * exited process belongs. 2929efd4c9b6SSteve Lawrence */ 2930efd4c9b6SSteve Lawrence if (zone == NULL) 2931efd4c9b6SSteve Lawrence goto proc_done; 2932efd4c9b6SSteve Lawrence 2933efd4c9b6SSteve Lawrence /* Save proc info */ 2934efd4c9b6SSteve Lawrence proc->zspr_ppid = ppid; 2935efd4c9b6SSteve Lawrence proc->zspr_zoneid = zone->zsz_id; 2936efd4c9b6SSteve Lawrence 2937efd4c9b6SSteve Lawrence prev_psetid = ZS_PSET_ERROR; 2938efd4c9b6SSteve Lawrence sched = 0; 2939efd4c9b6SSteve Lawrence 2940efd4c9b6SSteve Lawrence /* 2941efd4c9b6SSteve Lawrence * The following tries to deduce the processes pset. 2942efd4c9b6SSteve Lawrence * 2943efd4c9b6SSteve Lawrence * First choose pset and sched using cached value from the 2944efd4c9b6SSteve Lawrence * most recent time the process has been seen. 2945efd4c9b6SSteve Lawrence * 2946efd4c9b6SSteve Lawrence * pset and sched can change across zone_enter, so make sure 2947efd4c9b6SSteve Lawrence * most recent sighting of this process was in the same 2948efd4c9b6SSteve Lawrence * zone before using most recent known value. 2949efd4c9b6SSteve Lawrence * 2950efd4c9b6SSteve Lawrence * If there is no known value, use value of processes 2951efd4c9b6SSteve Lawrence * parent. If parent is unknown, walk parents until a known 2952efd4c9b6SSteve Lawrence * parent is found. 2953efd4c9b6SSteve Lawrence * 2954efd4c9b6SSteve Lawrence * If no parent in the zone is found, use the zone's default 2955efd4c9b6SSteve Lawrence * pset and scheduling class. 2956efd4c9b6SSteve Lawrence */ 2957efd4c9b6SSteve Lawrence if (proc->zspr_psetid != ZS_PSET_ERROR) { 2958efd4c9b6SSteve Lawrence prev_psetid = proc->zspr_psetid; 2959efd4c9b6SSteve Lawrence pset = zsd_lookup_pset_byid(ctl, prev_psetid); 2960efd4c9b6SSteve Lawrence sched = proc->zspr_sched; 2961efd4c9b6SSteve Lawrence } else if (pproc->zspr_zoneid == zone->zsz_id && 2962efd4c9b6SSteve Lawrence pproc->zspr_psetid != ZS_PSET_ERROR) { 2963efd4c9b6SSteve Lawrence prev_psetid = pproc->zspr_psetid; 2964efd4c9b6SSteve Lawrence pset = zsd_lookup_pset_byid(ctl, prev_psetid); 2965efd4c9b6SSteve Lawrence sched = pproc->zspr_sched; 2966efd4c9b6SSteve Lawrence } 2967efd4c9b6SSteve Lawrence 2968efd4c9b6SSteve Lawrence if (pset == NULL) { 2969efd4c9b6SSteve Lawrence /* 2970efd4c9b6SSteve Lawrence * Process or processes parent has never been seen. 2971efd4c9b6SSteve Lawrence * Save to deduce a known parent later. 2972efd4c9b6SSteve Lawrence */ 2973efd4c9b6SSteve Lawrence proc_usage = sys; 2974efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(proc_usage, user); 2975efd4c9b6SSteve Lawrence TIMESTRUC_DELTA(delta, proc_usage, 2976efd4c9b6SSteve Lawrence proc->zspr_usage); 2977efd4c9b6SSteve Lawrence proc->zspr_usage = delta; 2978efd4c9b6SSteve Lawrence list_insert_tail(&plist, proc); 2979efd4c9b6SSteve Lawrence continue; 2980efd4c9b6SSteve Lawrence } 2981efd4c9b6SSteve Lawrence 2982efd4c9b6SSteve Lawrence /* Add the zone's usage to the pset */ 2983efd4c9b6SSteve Lawrence usage = zsd_lookup_insert_usage(ctl, pset, zone); 2984efd4c9b6SSteve Lawrence if (usage == NULL) 2985efd4c9b6SSteve Lawrence goto proc_done; 2986efd4c9b6SSteve Lawrence 2987efd4c9b6SSteve Lawrence zsd_mark_pset_usage_found(usage, sched); 2988efd4c9b6SSteve Lawrence 2989efd4c9b6SSteve Lawrence /* compute the usage to add for the exited proc */ 2990efd4c9b6SSteve Lawrence proc_usage = sys; 2991efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(proc_usage, user); 2992efd4c9b6SSteve Lawrence TIMESTRUC_DELTA(delta, proc_usage, 2993efd4c9b6SSteve Lawrence proc->zspr_usage); 2994efd4c9b6SSteve Lawrence 2995efd4c9b6SSteve Lawrence zsd_add_usage(ctl, usage, &delta); 2996efd4c9b6SSteve Lawrence proc_done: 2997efd4c9b6SSteve Lawrence zsd_flush_proc_info(proc); 2998efd4c9b6SSteve Lawrence 2999efd4c9b6SSteve Lawrence if (hrtime_expired == B_TRUE) 3000efd4c9b6SSteve Lawrence break; 3001efd4c9b6SSteve Lawrence } 3002efd4c9b6SSteve Lawrence /* 3003efd4c9b6SSteve Lawrence * close next accounting file. 3004efd4c9b6SSteve Lawrence */ 3005efd4c9b6SSteve Lawrence if (ctl->zsctl_proc_open_next) { 3006efd4c9b6SSteve Lawrence (void) ea_close( 3007efd4c9b6SSteve Lawrence &ctl->zsctl_proc_eaf_next); 3008efd4c9b6SSteve Lawrence ctl->zsctl_proc_open_next = 0; 3009efd4c9b6SSteve Lawrence ctl->zsctl_proc_fd_next = -1; 3010efd4c9b6SSteve Lawrence } 3011efd4c9b6SSteve Lawrence 3012efd4c9b6SSteve Lawrence /* For the remaining processes, use pset and sched of a known parent */ 3013efd4c9b6SSteve Lawrence proc = list_head(&plist); 3014efd4c9b6SSteve Lawrence while (proc != NULL) { 3015efd4c9b6SSteve Lawrence next = proc; 3016efd4c9b6SSteve Lawrence for (;;) { 3017efd4c9b6SSteve Lawrence if (next->zspr_ppid == 0 || next->zspr_ppid == -1) { 3018efd4c9b6SSteve Lawrence /* 3019efd4c9b6SSteve Lawrence * Kernel process, or parent is unknown, skip 3020efd4c9b6SSteve Lawrence * process, remove from process list. 3021efd4c9b6SSteve Lawrence */ 3022efd4c9b6SSteve Lawrence tmp = proc; 3023efd4c9b6SSteve Lawrence proc = list_next(&plist, proc); 3024efd4c9b6SSteve Lawrence list_link_init(&tmp->zspr_next); 3025efd4c9b6SSteve Lawrence break; 3026efd4c9b6SSteve Lawrence } 3027efd4c9b6SSteve Lawrence pproc = &(ctl->zsctl_proc_array[next->zspr_ppid]); 3028efd4c9b6SSteve Lawrence if (pproc->zspr_zoneid != proc->zspr_zoneid) { 3029efd4c9b6SSteve Lawrence /* 3030efd4c9b6SSteve Lawrence * Parent in different zone. Save process and 3031efd4c9b6SSteve Lawrence * use zone's default pset and sched below 3032efd4c9b6SSteve Lawrence */ 3033efd4c9b6SSteve Lawrence tmp = proc; 3034efd4c9b6SSteve Lawrence proc = list_next(&plist, proc); 3035efd4c9b6SSteve Lawrence list_remove(&plist, tmp); 3036efd4c9b6SSteve Lawrence list_insert_tail(&pplist, tmp); 3037efd4c9b6SSteve Lawrence break; 3038efd4c9b6SSteve Lawrence } 3039efd4c9b6SSteve Lawrence /* Parent has unknown pset, Search parent's parent */ 3040efd4c9b6SSteve Lawrence if (pproc->zspr_psetid == ZS_PSET_ERROR) { 3041efd4c9b6SSteve Lawrence next = pproc; 3042efd4c9b6SSteve Lawrence continue; 3043efd4c9b6SSteve Lawrence } 3044efd4c9b6SSteve Lawrence /* Found parent with known pset. Use its info */ 3045efd4c9b6SSteve Lawrence proc->zspr_psetid = pproc->zspr_psetid; 3046efd4c9b6SSteve Lawrence proc->zspr_sched = pproc->zspr_sched; 3047efd4c9b6SSteve Lawrence next->zspr_psetid = pproc->zspr_psetid; 3048efd4c9b6SSteve Lawrence next->zspr_sched = pproc->zspr_sched; 3049efd4c9b6SSteve Lawrence zone = zsd_lookup_zone_byid(ctl, 3050efd4c9b6SSteve Lawrence proc->zspr_zoneid); 3051efd4c9b6SSteve Lawrence if (zone == NULL) { 3052efd4c9b6SSteve Lawrence tmp = proc; 3053efd4c9b6SSteve Lawrence proc = list_next(&plist, proc); 3054efd4c9b6SSteve Lawrence list_remove(&plist, tmp); 3055efd4c9b6SSteve Lawrence list_link_init(&tmp->zspr_next); 3056efd4c9b6SSteve Lawrence break; 3057efd4c9b6SSteve Lawrence } 3058efd4c9b6SSteve Lawrence pset = zsd_lookup_pset_byid(ctl, 3059efd4c9b6SSteve Lawrence proc->zspr_psetid); 3060efd4c9b6SSteve Lawrence if (pset == NULL) { 3061efd4c9b6SSteve Lawrence tmp = proc; 3062efd4c9b6SSteve Lawrence proc = list_next(&plist, proc); 3063efd4c9b6SSteve Lawrence list_remove(&plist, tmp); 3064efd4c9b6SSteve Lawrence list_link_init(&tmp->zspr_next); 3065efd4c9b6SSteve Lawrence break; 3066efd4c9b6SSteve Lawrence } 3067efd4c9b6SSteve Lawrence /* Add the zone's usage to the pset */ 3068efd4c9b6SSteve Lawrence usage = zsd_lookup_insert_usage(ctl, pset, zone); 3069efd4c9b6SSteve Lawrence if (usage == NULL) { 3070efd4c9b6SSteve Lawrence tmp = proc; 3071efd4c9b6SSteve Lawrence proc = list_next(&plist, proc); 3072efd4c9b6SSteve Lawrence list_remove(&plist, tmp); 3073efd4c9b6SSteve Lawrence list_link_init(&tmp->zspr_next); 3074efd4c9b6SSteve Lawrence break; 3075efd4c9b6SSteve Lawrence } 3076efd4c9b6SSteve Lawrence zsd_mark_pset_usage_found(usage, proc->zspr_sched); 3077efd4c9b6SSteve Lawrence zsd_add_usage(ctl, usage, &proc->zspr_usage); 3078efd4c9b6SSteve Lawrence zsd_flush_proc_info(proc); 3079efd4c9b6SSteve Lawrence tmp = proc; 3080efd4c9b6SSteve Lawrence proc = list_next(&plist, proc); 3081efd4c9b6SSteve Lawrence list_remove(&plist, tmp); 3082efd4c9b6SSteve Lawrence list_link_init(&tmp->zspr_next); 3083efd4c9b6SSteve Lawrence break; 3084efd4c9b6SSteve Lawrence } 3085efd4c9b6SSteve Lawrence } 3086efd4c9b6SSteve Lawrence /* 3087efd4c9b6SSteve Lawrence * Process has never been seen. Using zone info to 3088efd4c9b6SSteve Lawrence * determine pset and scheduling class. 3089efd4c9b6SSteve Lawrence */ 3090efd4c9b6SSteve Lawrence proc = list_head(&pplist); 3091efd4c9b6SSteve Lawrence while (proc != NULL) { 3092efd4c9b6SSteve Lawrence 3093efd4c9b6SSteve Lawrence zone = zsd_lookup_zone_byid(ctl, proc->zspr_zoneid); 3094efd4c9b6SSteve Lawrence if (zone == NULL) 3095efd4c9b6SSteve Lawrence goto next; 3096efd4c9b6SSteve Lawrence if (zone->zsz_psetid != ZS_PSET_ERROR && 3097efd4c9b6SSteve Lawrence zone->zsz_psetid != ZS_PSET_MULTI) { 3098efd4c9b6SSteve Lawrence prev_psetid = zone->zsz_psetid; 3099efd4c9b6SSteve Lawrence pset = zsd_lookup_pset_byid(ctl, prev_psetid); 3100efd4c9b6SSteve Lawrence } else { 3101efd4c9b6SSteve Lawrence pset = zsd_lookup_pset(ctl, zone->zsz_pset, -1); 3102efd4c9b6SSteve Lawrence if (pset != NULL) 3103efd4c9b6SSteve Lawrence prev_psetid = pset->zsp_id; 3104efd4c9b6SSteve Lawrence } 3105efd4c9b6SSteve Lawrence if (pset == NULL) 3106efd4c9b6SSteve Lawrence goto next; 3107efd4c9b6SSteve Lawrence 3108efd4c9b6SSteve Lawrence sched = zone->zsz_scheds; 3109efd4c9b6SSteve Lawrence /* 3110efd4c9b6SSteve Lawrence * Ignore FX high scheduling class if it is not the 3111efd4c9b6SSteve Lawrence * only scheduling class in the zone. 3112efd4c9b6SSteve Lawrence */ 3113efd4c9b6SSteve Lawrence if (sched != ZS_SCHED_FX_60) 3114efd4c9b6SSteve Lawrence sched &= (~ZS_SCHED_FX_60); 3115efd4c9b6SSteve Lawrence /* 3116efd4c9b6SSteve Lawrence * If more than one scheduling class has been found 3117efd4c9b6SSteve Lawrence * in the zone, use zone's default scheduling class for 3118efd4c9b6SSteve Lawrence * this process. 3119efd4c9b6SSteve Lawrence */ 3120efd4c9b6SSteve Lawrence if ((sched & (sched - 1)) != 0) 3121efd4c9b6SSteve Lawrence sched = zone->zsz_default_sched; 3122efd4c9b6SSteve Lawrence 3123efd4c9b6SSteve Lawrence /* Add the zone's usage to the pset */ 3124efd4c9b6SSteve Lawrence usage = zsd_lookup_insert_usage(ctl, pset, zone); 3125efd4c9b6SSteve Lawrence if (usage == NULL) 3126efd4c9b6SSteve Lawrence goto next; 3127efd4c9b6SSteve Lawrence 3128efd4c9b6SSteve Lawrence zsd_mark_pset_usage_found(usage, sched); 3129efd4c9b6SSteve Lawrence zsd_add_usage(ctl, usage, &proc->zspr_usage); 3130efd4c9b6SSteve Lawrence next: 3131efd4c9b6SSteve Lawrence tmp = proc; 3132efd4c9b6SSteve Lawrence proc = list_next(&pplist, proc); 3133efd4c9b6SSteve Lawrence zsd_flush_proc_info(tmp); 3134efd4c9b6SSteve Lawrence list_link_init(&tmp->zspr_next); 3135efd4c9b6SSteve Lawrence } 3136efd4c9b6SSteve Lawrence return; 3137efd4c9b6SSteve Lawrence ea_err: 3138efd4c9b6SSteve Lawrence /* 3139efd4c9b6SSteve Lawrence * Close the next accounting file if we have not transitioned to it 3140efd4c9b6SSteve Lawrence * yet. 3141efd4c9b6SSteve Lawrence */ 3142efd4c9b6SSteve Lawrence if (ctl->zsctl_proc_open_next) { 3143efd4c9b6SSteve Lawrence (void) ea_close(&ctl->zsctl_proc_eaf_next); 3144efd4c9b6SSteve Lawrence ctl->zsctl_proc_open_next = 0; 3145efd4c9b6SSteve Lawrence ctl->zsctl_proc_fd_next = -1; 3146efd4c9b6SSteve Lawrence } 3147efd4c9b6SSteve Lawrence } 3148efd4c9b6SSteve Lawrence 3149efd4c9b6SSteve Lawrence /* 3150efd4c9b6SSteve Lawrence * getvmusage(2) uses size_t's in the passwd data structure, which differ 3151efd4c9b6SSteve Lawrence * in size for 32bit and 64 bit kernels. Since this is a contracted interface, 3152efd4c9b6SSteve Lawrence * and zonestatd does not necessarily match the kernel's bitness, marshal 3153efd4c9b6SSteve Lawrence * results appropriately. 3154efd4c9b6SSteve Lawrence */ 3155efd4c9b6SSteve Lawrence static int 3156efd4c9b6SSteve Lawrence zsd_getvmusage(zsd_ctl_t *ctl, uint_t flags, time_t age, zsd_vmusage64_t *buf, 3157efd4c9b6SSteve Lawrence uint64_t *nres) 3158efd4c9b6SSteve Lawrence { 3159efd4c9b6SSteve Lawrence zsd_vmusage32_t *vmu32; 3160efd4c9b6SSteve Lawrence zsd_vmusage64_t *vmu64; 3161efd4c9b6SSteve Lawrence uint32_t nres32; 3162efd4c9b6SSteve Lawrence int i; 3163efd4c9b6SSteve Lawrence int ret; 3164efd4c9b6SSteve Lawrence 3165efd4c9b6SSteve Lawrence if (ctl->zsctl_kern_bits == 32) { 3166efd4c9b6SSteve Lawrence nres32 = *nres; 3167efd4c9b6SSteve Lawrence ret = syscall(SYS_rusagesys, _RUSAGESYS_GETVMUSAGE, 3168efd4c9b6SSteve Lawrence flags, age, (uintptr_t)buf, (uintptr_t)&nres32); 3169efd4c9b6SSteve Lawrence *nres = nres32; 3170efd4c9b6SSteve Lawrence if (ret == 0 && buf != NULL) { 3171efd4c9b6SSteve Lawrence /* 3172efd4c9b6SSteve Lawrence * An array of vmusage32_t's has been returned. 3173efd4c9b6SSteve Lawrence * Convert it to an array of vmusage64_t's. 3174efd4c9b6SSteve Lawrence */ 3175efd4c9b6SSteve Lawrence vmu32 = (zsd_vmusage32_t *)buf; 3176efd4c9b6SSteve Lawrence vmu64 = (zsd_vmusage64_t *)buf; 3177efd4c9b6SSteve Lawrence for (i = nres32 - 1; i >= 0; i--) { 3178efd4c9b6SSteve Lawrence 3179efd4c9b6SSteve Lawrence vmu64[i].vmu_zoneid = vmu32[i].vmu_zoneid; 3180efd4c9b6SSteve Lawrence vmu64[i].vmu_type = vmu32[i].vmu_type; 3181efd4c9b6SSteve Lawrence vmu64[i].vmu_type = vmu32[i].vmu_type; 3182efd4c9b6SSteve Lawrence vmu64[i].vmu_rss_all = vmu32[i].vmu_rss_all; 3183efd4c9b6SSteve Lawrence vmu64[i].vmu_rss_private = 3184efd4c9b6SSteve Lawrence vmu32[i].vmu_rss_private; 3185efd4c9b6SSteve Lawrence vmu64[i].vmu_rss_shared = 3186efd4c9b6SSteve Lawrence vmu32[i].vmu_rss_shared; 3187efd4c9b6SSteve Lawrence vmu64[i].vmu_swap_all = vmu32[i].vmu_swap_all; 3188efd4c9b6SSteve Lawrence vmu64[i].vmu_swap_private = 3189efd4c9b6SSteve Lawrence vmu32[i].vmu_swap_private; 3190efd4c9b6SSteve Lawrence vmu64[i].vmu_swap_shared = 3191efd4c9b6SSteve Lawrence vmu32[i].vmu_swap_shared; 3192efd4c9b6SSteve Lawrence } 3193efd4c9b6SSteve Lawrence } 3194efd4c9b6SSteve Lawrence return (ret); 3195efd4c9b6SSteve Lawrence } else { 3196efd4c9b6SSteve Lawrence /* 3197efd4c9b6SSteve Lawrence * kernel is 64 bit, so use 64 bit structures as zonestat 3198efd4c9b6SSteve Lawrence * expects. 3199efd4c9b6SSteve Lawrence */ 3200efd4c9b6SSteve Lawrence return (syscall(SYS_rusagesys, _RUSAGESYS_GETVMUSAGE, 3201efd4c9b6SSteve Lawrence flags, age, (uintptr_t)buf, (uintptr_t)nres)); 3202efd4c9b6SSteve Lawrence 3203efd4c9b6SSteve Lawrence } 3204efd4c9b6SSteve Lawrence } 3205efd4c9b6SSteve Lawrence 3206efd4c9b6SSteve Lawrence /* 3207efd4c9b6SSteve Lawrence * Update the current physical, virtual, and locked memory usage of the 3208efd4c9b6SSteve Lawrence * running zones. 3209efd4c9b6SSteve Lawrence */ 3210efd4c9b6SSteve Lawrence static void 3211efd4c9b6SSteve Lawrence zsd_refresh_memory(zsd_ctl_t *ctl, boolean_t init) 3212efd4c9b6SSteve Lawrence { 3213efd4c9b6SSteve Lawrence 3214efd4c9b6SSteve Lawrence uint64_t phys_total; 3215efd4c9b6SSteve Lawrence uint64_t phys_used; 3216efd4c9b6SSteve Lawrence uint64_t phys_zones; 3217efd4c9b6SSteve Lawrence uint64_t phys_zones_overcount; 3218efd4c9b6SSteve Lawrence uint64_t phys_zones_extra; 3219efd4c9b6SSteve Lawrence uint64_t phys_zones_credit; 3220efd4c9b6SSteve Lawrence 3221efd4c9b6SSteve Lawrence uint64_t vm_free; 3222efd4c9b6SSteve Lawrence uint64_t vm_used; 3223efd4c9b6SSteve Lawrence 3224efd4c9b6SSteve Lawrence uint64_t disk_swap_total; 3225efd4c9b6SSteve Lawrence uint64_t disk_swap_used; /* disk swap with contents */ 3226efd4c9b6SSteve Lawrence 3227efd4c9b6SSteve Lawrence uint64_t physmem; 3228efd4c9b6SSteve Lawrence uint64_t pp_kernel; 3229efd4c9b6SSteve Lawrence uint64_t arc_size = 0; 3230efd4c9b6SSteve Lawrence struct anoninfo ani; 3231efd4c9b6SSteve Lawrence 3232efd4c9b6SSteve Lawrence int num_swap_devices; 3233efd4c9b6SSteve Lawrence struct swaptable *swt; 3234efd4c9b6SSteve Lawrence struct swapent *swent; 3235efd4c9b6SSteve Lawrence size_t swt_size; 3236efd4c9b6SSteve Lawrence char *path; 3237efd4c9b6SSteve Lawrence 3238efd4c9b6SSteve Lawrence zsd_vmusage64_t *vmusage; 3239efd4c9b6SSteve Lawrence uint64_t num_vmusage; 3240efd4c9b6SSteve Lawrence 3241efd4c9b6SSteve Lawrence int i, ret; 3242efd4c9b6SSteve Lawrence 3243efd4c9b6SSteve Lawrence zsd_system_t *sys; 3244efd4c9b6SSteve Lawrence zsd_zone_t *zone; 3245efd4c9b6SSteve Lawrence int vmu_nzones; 3246efd4c9b6SSteve Lawrence 3247efd4c9b6SSteve Lawrence kstat_t *kstat; 3248efd4c9b6SSteve Lawrence char kstat_name[KSTAT_STRLEN]; 3249efd4c9b6SSteve Lawrence kstat_named_t *knp; 3250efd4c9b6SSteve Lawrence kid_t kid; 3251efd4c9b6SSteve Lawrence 3252efd4c9b6SSteve Lawrence if (init) 3253efd4c9b6SSteve Lawrence return; 3254efd4c9b6SSteve Lawrence 3255efd4c9b6SSteve Lawrence sys = ctl->zsctl_system; 3256efd4c9b6SSteve Lawrence 3257efd4c9b6SSteve Lawrence /* interrogate swap devices to find the amount of disk swap */ 3258efd4c9b6SSteve Lawrence disk_swap_again: 3259efd4c9b6SSteve Lawrence num_swap_devices = swapctl(SC_GETNSWP, NULL); 3260efd4c9b6SSteve Lawrence 3261efd4c9b6SSteve Lawrence if (num_swap_devices == 0) { 3262efd4c9b6SSteve Lawrence sys->zss_swap_total = disk_swap_total = 0; 3263efd4c9b6SSteve Lawrence sys->zss_swap_used = disk_swap_used = 0; 3264efd4c9b6SSteve Lawrence /* No disk swap */ 3265efd4c9b6SSteve Lawrence goto disk_swap_done; 3266efd4c9b6SSteve Lawrence } 3267efd4c9b6SSteve Lawrence /* see if swap table needs to be larger */ 3268efd4c9b6SSteve Lawrence if (num_swap_devices > ctl->zsctl_swap_cache_num) { 3269efd4c9b6SSteve Lawrence swt_size = sizeof (int) + 3270efd4c9b6SSteve Lawrence (num_swap_devices * sizeof (struct swapent)) + 3271efd4c9b6SSteve Lawrence (num_swap_devices * MAXPATHLEN); 3272efd4c9b6SSteve Lawrence if (ctl->zsctl_swap_cache != NULL) 3273efd4c9b6SSteve Lawrence free(ctl->zsctl_swap_cache); 3274efd4c9b6SSteve Lawrence 3275efd4c9b6SSteve Lawrence swt = (struct swaptable *)malloc(swt_size); 3276efd4c9b6SSteve Lawrence if (swt == NULL) { 3277efd4c9b6SSteve Lawrence /* 3278efd4c9b6SSteve Lawrence * Could not allocate to get list of swap devices. 3279efd4c9b6SSteve Lawrence * Just use data from the most recent read, which will 3280efd4c9b6SSteve Lawrence * be zero if this is the first read. 3281efd4c9b6SSteve Lawrence */ 3282efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to allocate to determine " 3283efd4c9b6SSteve Lawrence "virtual memory")); 3284efd4c9b6SSteve Lawrence disk_swap_total = sys->zss_swap_total; 3285efd4c9b6SSteve Lawrence disk_swap_used = sys->zss_swap_used; 3286efd4c9b6SSteve Lawrence goto disk_swap_done; 3287efd4c9b6SSteve Lawrence } 3288efd4c9b6SSteve Lawrence swent = swt->swt_ent; 3289efd4c9b6SSteve Lawrence path = (char *)swt + (sizeof (int) + 3290efd4c9b6SSteve Lawrence num_swap_devices * sizeof (swapent_t)); 3291efd4c9b6SSteve Lawrence for (i = 0; i < num_swap_devices; i++, swent++) { 3292efd4c9b6SSteve Lawrence swent->ste_path = path; 3293efd4c9b6SSteve Lawrence path += MAXPATHLEN; 3294efd4c9b6SSteve Lawrence } 3295efd4c9b6SSteve Lawrence swt->swt_n = num_swap_devices; 3296efd4c9b6SSteve Lawrence ctl->zsctl_swap_cache = swt; 3297efd4c9b6SSteve Lawrence ctl->zsctl_swap_cache_size = swt_size; 3298efd4c9b6SSteve Lawrence ctl->zsctl_swap_cache_num = num_swap_devices; 3299efd4c9b6SSteve Lawrence } 3300efd4c9b6SSteve Lawrence num_swap_devices = swapctl(SC_LIST, ctl->zsctl_swap_cache); 3301efd4c9b6SSteve Lawrence if (num_swap_devices < 0) { 3302efd4c9b6SSteve Lawrence /* More swap devices have arrived */ 3303efd4c9b6SSteve Lawrence if (errno == ENOMEM) 3304efd4c9b6SSteve Lawrence goto disk_swap_again; 3305efd4c9b6SSteve Lawrence 3306efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to determine disk swap devices")); 3307efd4c9b6SSteve Lawrence /* Unexpected error. Use existing data */ 3308efd4c9b6SSteve Lawrence disk_swap_total = sys->zss_swap_total; 3309efd4c9b6SSteve Lawrence disk_swap_used = sys->zss_swap_used; 3310efd4c9b6SSteve Lawrence goto disk_swap_done; 3311efd4c9b6SSteve Lawrence } 3312efd4c9b6SSteve Lawrence 3313efd4c9b6SSteve Lawrence /* add up the disk swap */ 3314efd4c9b6SSteve Lawrence disk_swap_total = 0; 3315efd4c9b6SSteve Lawrence disk_swap_used = 0; 3316efd4c9b6SSteve Lawrence swent = ctl->zsctl_swap_cache->swt_ent; 3317efd4c9b6SSteve Lawrence for (i = 0; i < num_swap_devices; i++, swent++) { 3318efd4c9b6SSteve Lawrence disk_swap_total += swent->ste_pages; 3319efd4c9b6SSteve Lawrence disk_swap_used += (swent->ste_pages - swent->ste_free); 3320efd4c9b6SSteve Lawrence } 3321efd4c9b6SSteve Lawrence disk_swap_total *= ctl->zsctl_pagesize; 3322efd4c9b6SSteve Lawrence disk_swap_used *= ctl->zsctl_pagesize; 3323efd4c9b6SSteve Lawrence 3324efd4c9b6SSteve Lawrence sys->zss_swap_total = disk_swap_total; 3325efd4c9b6SSteve Lawrence sys->zss_swap_used = disk_swap_used; 3326efd4c9b6SSteve Lawrence 3327efd4c9b6SSteve Lawrence disk_swap_done: 3328efd4c9b6SSteve Lawrence 3329efd4c9b6SSteve Lawrence /* get system pages kstat */ 3330efd4c9b6SSteve Lawrence kid = -1; 3331efd4c9b6SSteve Lawrence kstat = kstat_lookup(ctl->zsctl_kstat_ctl, "unix", 0, "system_pages"); 3332efd4c9b6SSteve Lawrence if (kstat == NULL) 3333efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to lookup system pages kstat")); 3334efd4c9b6SSteve Lawrence else 3335efd4c9b6SSteve Lawrence kid = kstat_read(ctl->zsctl_kstat_ctl, kstat, NULL); 3336efd4c9b6SSteve Lawrence 3337efd4c9b6SSteve Lawrence if (kid == -1) { 3338efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to read system pages kstat")); 3339efd4c9b6SSteve Lawrence return; 3340efd4c9b6SSteve Lawrence } else { 3341efd4c9b6SSteve Lawrence knp = kstat_data_lookup(kstat, "physmem"); 3342efd4c9b6SSteve Lawrence if (knp == NULL) { 3343efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to read physmem")); 3344efd4c9b6SSteve Lawrence } else { 3345efd4c9b6SSteve Lawrence if (knp->data_type == KSTAT_DATA_UINT64) 3346efd4c9b6SSteve Lawrence physmem = knp->value.ui64; 3347efd4c9b6SSteve Lawrence else if (knp->data_type == KSTAT_DATA_UINT32) 3348efd4c9b6SSteve Lawrence physmem = knp->value.ui32; 3349efd4c9b6SSteve Lawrence else 3350efd4c9b6SSteve Lawrence return; 3351efd4c9b6SSteve Lawrence } 3352efd4c9b6SSteve Lawrence knp = kstat_data_lookup(kstat, "pp_kernel"); 3353efd4c9b6SSteve Lawrence if (knp == NULL) { 3354efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to read pp_kernel")); 3355efd4c9b6SSteve Lawrence } else { 3356efd4c9b6SSteve Lawrence if (knp->data_type == KSTAT_DATA_UINT64) 3357efd4c9b6SSteve Lawrence pp_kernel = knp->value.ui64; 3358efd4c9b6SSteve Lawrence else if (knp->data_type == KSTAT_DATA_UINT32) 3359efd4c9b6SSteve Lawrence pp_kernel = knp->value.ui32; 3360efd4c9b6SSteve Lawrence else 3361efd4c9b6SSteve Lawrence return; 3362efd4c9b6SSteve Lawrence } 3363efd4c9b6SSteve Lawrence } 3364efd4c9b6SSteve Lawrence physmem *= ctl->zsctl_pagesize; 3365efd4c9b6SSteve Lawrence pp_kernel *= ctl->zsctl_pagesize; 3366efd4c9b6SSteve Lawrence 3367efd4c9b6SSteve Lawrence /* get the zfs arc size if available */ 3368efd4c9b6SSteve Lawrence arc_size = 0; 3369efd4c9b6SSteve Lawrence kid = -1; 3370efd4c9b6SSteve Lawrence kstat = kstat_lookup(ctl->zsctl_kstat_ctl, "zfs", 0, "arcstats"); 3371efd4c9b6SSteve Lawrence if (kstat != NULL) 3372efd4c9b6SSteve Lawrence kid = kstat_read(ctl->zsctl_kstat_ctl, kstat, NULL); 3373efd4c9b6SSteve Lawrence if (kid != -1) { 3374efd4c9b6SSteve Lawrence knp = kstat_data_lookup(kstat, "size"); 3375efd4c9b6SSteve Lawrence if (knp != NULL) 3376efd4c9b6SSteve Lawrence if (knp->data_type == KSTAT_DATA_UINT64) 3377efd4c9b6SSteve Lawrence arc_size = knp->value.ui64; 3378efd4c9b6SSteve Lawrence } 3379efd4c9b6SSteve Lawrence 3380efd4c9b6SSteve Lawrence /* Try to get swap information */ 3381efd4c9b6SSteve Lawrence if (swapctl(SC_AINFO, &ani) < 0) { 3382efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to get swap info")); 3383efd4c9b6SSteve Lawrence return; 3384efd4c9b6SSteve Lawrence } 3385efd4c9b6SSteve Lawrence 3386efd4c9b6SSteve Lawrence vmusage_again: 3387efd4c9b6SSteve Lawrence /* getvmusage to get physical memory usage */ 3388efd4c9b6SSteve Lawrence vmusage = ctl->zsctl_vmusage_cache; 3389efd4c9b6SSteve Lawrence num_vmusage = ctl->zsctl_vmusage_cache_num; 3390efd4c9b6SSteve Lawrence 3391efd4c9b6SSteve Lawrence ret = zsd_getvmusage(ctl, VMUSAGE_SYSTEM | VMUSAGE_ALL_ZONES, 0, 3392efd4c9b6SSteve Lawrence vmusage, &num_vmusage); 3393efd4c9b6SSteve Lawrence 3394efd4c9b6SSteve Lawrence if (ret != 0) { 3395efd4c9b6SSteve Lawrence /* Unexpected error. Use existing data */ 3396efd4c9b6SSteve Lawrence if (errno != EOVERFLOW) { 3397efd4c9b6SSteve Lawrence zsd_warn(gettext( 3398efd4c9b6SSteve Lawrence "Unable to read physical memory usage")); 3399efd4c9b6SSteve Lawrence phys_zones = sys->zss_ram_zones; 3400efd4c9b6SSteve Lawrence goto vmusage_done; 3401efd4c9b6SSteve Lawrence } 3402efd4c9b6SSteve Lawrence } 3403efd4c9b6SSteve Lawrence /* vmusage results cache too small */ 3404efd4c9b6SSteve Lawrence if (num_vmusage > ctl->zsctl_vmusage_cache_num) { 3405efd4c9b6SSteve Lawrence 3406efd4c9b6SSteve Lawrence size_t size = sizeof (zsd_vmusage64_t) * num_vmusage; 3407efd4c9b6SSteve Lawrence 3408efd4c9b6SSteve Lawrence if (ctl->zsctl_vmusage_cache != NULL) 3409efd4c9b6SSteve Lawrence free(ctl->zsctl_vmusage_cache); 3410efd4c9b6SSteve Lawrence vmusage = (zsd_vmusage64_t *)malloc(size); 3411efd4c9b6SSteve Lawrence if (vmusage == NULL) { 3412efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to alloc to determine " 3413efd4c9b6SSteve Lawrence "physical memory usage")); 3414efd4c9b6SSteve Lawrence phys_zones = sys->zss_ram_zones; 3415efd4c9b6SSteve Lawrence goto vmusage_done; 3416efd4c9b6SSteve Lawrence } 3417efd4c9b6SSteve Lawrence ctl->zsctl_vmusage_cache = vmusage; 3418efd4c9b6SSteve Lawrence ctl->zsctl_vmusage_cache_num = num_vmusage; 3419efd4c9b6SSteve Lawrence goto vmusage_again; 3420efd4c9b6SSteve Lawrence } 3421efd4c9b6SSteve Lawrence 3422efd4c9b6SSteve Lawrence phys_zones_overcount = 0; 3423efd4c9b6SSteve Lawrence vmu_nzones = 0; 3424efd4c9b6SSteve Lawrence for (i = 0; i < num_vmusage; i++) { 3425efd4c9b6SSteve Lawrence switch (vmusage[i].vmu_type) { 3426efd4c9b6SSteve Lawrence case VMUSAGE_SYSTEM: 3427efd4c9b6SSteve Lawrence /* total pages backing user process mappings */ 3428efd4c9b6SSteve Lawrence phys_zones = sys->zss_ram_zones = 3429efd4c9b6SSteve Lawrence vmusage[i].vmu_rss_all; 3430efd4c9b6SSteve Lawrence break; 3431efd4c9b6SSteve Lawrence case VMUSAGE_ZONE: 3432efd4c9b6SSteve Lawrence vmu_nzones++; 3433efd4c9b6SSteve Lawrence phys_zones_overcount += vmusage[i].vmu_rss_all; 3434efd4c9b6SSteve Lawrence zone = zsd_lookup_zone_byid(ctl, vmusage[i].vmu_id); 3435efd4c9b6SSteve Lawrence if (zone != NULL) 3436efd4c9b6SSteve Lawrence zone->zsz_usage_ram = vmusage[i].vmu_rss_all; 3437efd4c9b6SSteve Lawrence break; 3438efd4c9b6SSteve Lawrence default: 3439efd4c9b6SSteve Lawrence break; 3440efd4c9b6SSteve Lawrence } 3441efd4c9b6SSteve Lawrence } 3442efd4c9b6SSteve Lawrence /* 3443efd4c9b6SSteve Lawrence * Figure how much memory was double counted due to text sharing 3444efd4c9b6SSteve Lawrence * between zones. Credit this back so that the sum of the zones 3445efd4c9b6SSteve Lawrence * equals the total zone ram usage; 3446efd4c9b6SSteve Lawrence */ 3447efd4c9b6SSteve Lawrence phys_zones_extra = phys_zones_overcount - phys_zones; 3448efd4c9b6SSteve Lawrence phys_zones_credit = phys_zones_extra / vmu_nzones; 3449efd4c9b6SSteve Lawrence 3450efd4c9b6SSteve Lawrence vmusage_done: 3451efd4c9b6SSteve Lawrence 3452efd4c9b6SSteve Lawrence /* walk the zones to get swap and locked kstats. Fetch ram cap. */ 3453efd4c9b6SSteve Lawrence sys->zss_locked_zones = 0; 3454efd4c9b6SSteve Lawrence sys->zss_vm_zones = 0; 3455efd4c9b6SSteve Lawrence for (zone = list_head(&ctl->zsctl_zones); zone != NULL; 3456efd4c9b6SSteve Lawrence zone = list_next(&ctl->zsctl_zones, zone)) { 3457efd4c9b6SSteve Lawrence 3458efd4c9b6SSteve Lawrence /* If zone halted during interval, show memory usage as none */ 3459efd4c9b6SSteve Lawrence if (zone->zsz_active == B_FALSE || 3460efd4c9b6SSteve Lawrence zone->zsz_deleted == B_TRUE) { 3461efd4c9b6SSteve Lawrence zone->zsz_usage_ram = 0; 3462efd4c9b6SSteve Lawrence zone->zsz_usage_vm = 0; 3463efd4c9b6SSteve Lawrence zone->zsz_usage_locked = 0; 3464efd4c9b6SSteve Lawrence continue; 3465efd4c9b6SSteve Lawrence } 3466efd4c9b6SSteve Lawrence 3467efd4c9b6SSteve Lawrence if (phys_zones_credit > 0) { 3468efd4c9b6SSteve Lawrence if (zone->zsz_usage_ram > phys_zones_credit) { 3469efd4c9b6SSteve Lawrence zone->zsz_usage_ram -= phys_zones_credit; 3470efd4c9b6SSteve Lawrence } 3471efd4c9b6SSteve Lawrence } 3472efd4c9b6SSteve Lawrence /* 3473efd4c9b6SSteve Lawrence * Get zone's swap usage. Since zone could have halted, 3474efd4c9b6SSteve Lawrence * treats as zero if cannot read 3475efd4c9b6SSteve Lawrence */ 3476efd4c9b6SSteve Lawrence zone->zsz_usage_vm = 0; 3477efd4c9b6SSteve Lawrence (void) snprintf(kstat_name, sizeof (kstat_name), 3478efd4c9b6SSteve Lawrence "swapresv_zone_%d", zone->zsz_id); 3479efd4c9b6SSteve Lawrence kid = -1; 3480efd4c9b6SSteve Lawrence kstat = kstat_lookup(ctl->zsctl_kstat_ctl, "caps", 3481efd4c9b6SSteve Lawrence zone->zsz_id, kstat_name); 3482efd4c9b6SSteve Lawrence if (kstat != NULL) 3483efd4c9b6SSteve Lawrence kid = kstat_read(ctl->zsctl_kstat_ctl, kstat, NULL); 3484efd4c9b6SSteve Lawrence if (kid != -1) { 3485efd4c9b6SSteve Lawrence knp = kstat_data_lookup(kstat, "usage"); 3486efd4c9b6SSteve Lawrence if (knp != NULL && 3487efd4c9b6SSteve Lawrence knp->data_type == KSTAT_DATA_UINT64) { 3488efd4c9b6SSteve Lawrence zone->zsz_usage_vm = knp->value.ui64; 3489efd4c9b6SSteve Lawrence sys->zss_vm_zones += knp->value.ui64; 3490efd4c9b6SSteve Lawrence } 3491efd4c9b6SSteve Lawrence } 3492efd4c9b6SSteve Lawrence /* 3493efd4c9b6SSteve Lawrence * Get zone's locked usage. Since zone could have halted, 3494efd4c9b6SSteve Lawrence * treats as zero if cannot read 3495efd4c9b6SSteve Lawrence */ 3496efd4c9b6SSteve Lawrence zone->zsz_usage_locked = 0; 3497efd4c9b6SSteve Lawrence (void) snprintf(kstat_name, sizeof (kstat_name), 3498efd4c9b6SSteve Lawrence "lockedmem_zone_%d", zone->zsz_id); 3499efd4c9b6SSteve Lawrence kid = -1; 3500efd4c9b6SSteve Lawrence kstat = kstat_lookup(ctl->zsctl_kstat_ctl, "caps", 3501efd4c9b6SSteve Lawrence zone->zsz_id, kstat_name); 3502efd4c9b6SSteve Lawrence if (kstat != NULL) 3503efd4c9b6SSteve Lawrence kid = kstat_read(ctl->zsctl_kstat_ctl, kstat, NULL); 3504efd4c9b6SSteve Lawrence if (kid != -1) { 3505efd4c9b6SSteve Lawrence knp = kstat_data_lookup(kstat, "usage"); 3506efd4c9b6SSteve Lawrence if (knp != NULL && 3507efd4c9b6SSteve Lawrence knp->data_type == KSTAT_DATA_UINT64) { 3508efd4c9b6SSteve Lawrence zone->zsz_usage_locked = knp->value.ui64; 3509efd4c9b6SSteve Lawrence /* 3510efd4c9b6SSteve Lawrence * Since locked memory accounting for zones 3511efd4c9b6SSteve Lawrence * can double count ddi locked memory, cap each 3512efd4c9b6SSteve Lawrence * zone's locked usage at its ram usage. 3513efd4c9b6SSteve Lawrence */ 3514efd4c9b6SSteve Lawrence if (zone->zsz_usage_locked > 3515efd4c9b6SSteve Lawrence zone->zsz_usage_ram) 3516efd4c9b6SSteve Lawrence zone->zsz_usage_locked = 3517efd4c9b6SSteve Lawrence zone->zsz_usage_ram; 3518efd4c9b6SSteve Lawrence sys->zss_locked_zones += 3519efd4c9b6SSteve Lawrence zone->zsz_usage_locked; 3520efd4c9b6SSteve Lawrence } 3521efd4c9b6SSteve Lawrence } 3522efd4c9b6SSteve Lawrence } 3523efd4c9b6SSteve Lawrence 3524efd4c9b6SSteve Lawrence phys_total = 3525efd4c9b6SSteve Lawrence sysconf(_SC_PHYS_PAGES) * ctl->zsctl_pagesize; 3526efd4c9b6SSteve Lawrence 3527efd4c9b6SSteve Lawrence phys_used = (sysconf(_SC_PHYS_PAGES) - sysconf(_SC_AVPHYS_PAGES)) 3528efd4c9b6SSteve Lawrence * ctl->zsctl_pagesize; 3529efd4c9b6SSteve Lawrence 3530efd4c9b6SSteve Lawrence /* Compute remaining statistics */ 3531efd4c9b6SSteve Lawrence sys->zss_ram_total = phys_total; 3532efd4c9b6SSteve Lawrence sys->zss_ram_zones = phys_zones; 3533efd4c9b6SSteve Lawrence sys->zss_ram_kern = phys_used - phys_zones - arc_size; 3534efd4c9b6SSteve Lawrence 3535efd4c9b6SSteve Lawrence /* 3536efd4c9b6SSteve Lawrence * The total for kernel locked memory should include 3537efd4c9b6SSteve Lawrence * segkp locked pages, but oh well. The arc size is subtracted, 3538efd4c9b6SSteve Lawrence * as that physical memory is reclaimable. 3539efd4c9b6SSteve Lawrence */ 3540efd4c9b6SSteve Lawrence sys->zss_locked_kern = pp_kernel - arc_size; 3541efd4c9b6SSteve Lawrence /* Add memory used by kernel startup and obp to kernel locked */ 3542efd4c9b6SSteve Lawrence if ((phys_total - physmem) > 0) 3543efd4c9b6SSteve Lawrence sys->zss_locked_kern += phys_total - physmem; 3544efd4c9b6SSteve Lawrence 3545efd4c9b6SSteve Lawrence /* 3546efd4c9b6SSteve Lawrence * Add in the portion of (RAM+DISK) that is not available as swap, 3547efd4c9b6SSteve Lawrence * and consider it swap used by the kernel. 3548efd4c9b6SSteve Lawrence */ 3549efd4c9b6SSteve Lawrence sys->zss_vm_total = phys_total + disk_swap_total; 3550efd4c9b6SSteve Lawrence vm_free = (ani.ani_max - ani.ani_resv) * ctl->zsctl_pagesize; 3551efd4c9b6SSteve Lawrence vm_used = sys->zss_vm_total - vm_free; 3552efd4c9b6SSteve Lawrence sys->zss_vm_kern = vm_used - sys->zss_vm_zones - arc_size; 3553efd4c9b6SSteve Lawrence } 3554efd4c9b6SSteve Lawrence 3555efd4c9b6SSteve Lawrence /* 3556efd4c9b6SSteve Lawrence * Charge each cpu's usage to its processor sets. Also add the cpu's total 3557efd4c9b6SSteve Lawrence * time to each zone using the processor set. This tracks the maximum 3558efd4c9b6SSteve Lawrence * amount of cpu time that a zone could have used. 3559efd4c9b6SSteve Lawrence */ 3560efd4c9b6SSteve Lawrence static void 3561efd4c9b6SSteve Lawrence zsd_refresh_cpu_stats(zsd_ctl_t *ctl, boolean_t init) 3562efd4c9b6SSteve Lawrence { 3563efd4c9b6SSteve Lawrence zsd_system_t *sys; 3564efd4c9b6SSteve Lawrence zsd_zone_t *zone; 3565efd4c9b6SSteve Lawrence zsd_pset_usage_t *usage; 3566efd4c9b6SSteve Lawrence zsd_cpu_t *cpu; 3567efd4c9b6SSteve Lawrence zsd_cpu_t *cpu_next; 3568efd4c9b6SSteve Lawrence zsd_pset_t *pset; 3569efd4c9b6SSteve Lawrence timestruc_t ts; 3570efd4c9b6SSteve Lawrence uint64_t hrtime; 3571efd4c9b6SSteve Lawrence timestruc_t delta; 3572efd4c9b6SSteve Lawrence 3573efd4c9b6SSteve Lawrence /* Update the per-cpu kstat data */ 3574efd4c9b6SSteve Lawrence cpu_next = list_head(&ctl->zsctl_cpus); 3575efd4c9b6SSteve Lawrence while (cpu_next != NULL) { 3576efd4c9b6SSteve Lawrence cpu = cpu_next; 3577efd4c9b6SSteve Lawrence cpu_next = list_next(&ctl->zsctl_cpus, cpu); 3578efd4c9b6SSteve Lawrence zsd_update_cpu_stats(ctl, cpu); 3579efd4c9b6SSteve Lawrence } 3580efd4c9b6SSteve Lawrence /* Update the elapsed real time */ 3581efd4c9b6SSteve Lawrence hrtime = gethrtime(); 3582efd4c9b6SSteve Lawrence if (init) { 3583efd4c9b6SSteve Lawrence /* first time around, store hrtime for future comparision */ 3584efd4c9b6SSteve Lawrence ctl->zsctl_hrtime = hrtime; 3585efd4c9b6SSteve Lawrence ctl->zsctl_hrtime_prev = hrtime; 3586efd4c9b6SSteve Lawrence 3587efd4c9b6SSteve Lawrence } else { 3588efd4c9b6SSteve Lawrence /* Compute increase in hrtime since the most recent read */ 3589efd4c9b6SSteve Lawrence ctl->zsctl_hrtime_prev = ctl->zsctl_hrtime; 3590efd4c9b6SSteve Lawrence ctl->zsctl_hrtime = hrtime; 3591efd4c9b6SSteve Lawrence if ((hrtime = hrtime - ctl->zsctl_hrtime_prev) > 0) 3592efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(ctl->zsctl_hrtime_total, hrtime); 3593efd4c9b6SSteve Lawrence } 3594efd4c9b6SSteve Lawrence 3595efd4c9b6SSteve Lawrence /* On initialization, all psets have zero time */ 3596efd4c9b6SSteve Lawrence if (init) 3597efd4c9b6SSteve Lawrence return; 3598efd4c9b6SSteve Lawrence 3599efd4c9b6SSteve Lawrence for (pset = list_head(&ctl->zsctl_psets); pset != NULL; 3600efd4c9b6SSteve Lawrence pset = list_next(&ctl->zsctl_psets, pset)) { 3601efd4c9b6SSteve Lawrence 3602efd4c9b6SSteve Lawrence if (pset->zsp_active == B_FALSE) { 3603efd4c9b6SSteve Lawrence zsd_warn(gettext("Internal error,inactive pset found")); 3604efd4c9b6SSteve Lawrence continue; 3605efd4c9b6SSteve Lawrence } 3606efd4c9b6SSteve Lawrence 3607efd4c9b6SSteve Lawrence /* sum total used time for pset */ 3608efd4c9b6SSteve Lawrence ts.tv_sec = 0; 3609efd4c9b6SSteve Lawrence ts.tv_nsec = 0; 3610efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(ts, pset->zsp_intr); 3611efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(ts, pset->zsp_kern); 3612efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(ts, pset->zsp_user); 3613efd4c9b6SSteve Lawrence /* kernel time in pset is total time minus zone time */ 3614efd4c9b6SSteve Lawrence TIMESTRUC_DELTA(pset->zsp_usage_kern, ts, 3615efd4c9b6SSteve Lawrence pset->zsp_usage_zones); 3616efd4c9b6SSteve Lawrence if (pset->zsp_usage_kern.tv_sec < 0 || 3617efd4c9b6SSteve Lawrence pset->zsp_usage_kern.tv_nsec < 0) { 3618efd4c9b6SSteve Lawrence pset->zsp_usage_kern.tv_sec = 0; 3619efd4c9b6SSteve Lawrence pset->zsp_usage_kern.tv_nsec = 0; 3620efd4c9b6SSteve Lawrence } 3621efd4c9b6SSteve Lawrence /* Total pset elapsed time is used time plus idle time */ 3622efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(ts, pset->zsp_idle); 3623efd4c9b6SSteve Lawrence 3624efd4c9b6SSteve Lawrence TIMESTRUC_DELTA(delta, ts, pset->zsp_total_time); 3625efd4c9b6SSteve Lawrence 3626efd4c9b6SSteve Lawrence for (usage = list_head(&pset->zsp_usage_list); usage != NULL; 3627efd4c9b6SSteve Lawrence usage = list_next(&pset->zsp_usage_list, usage)) { 3628efd4c9b6SSteve Lawrence 3629efd4c9b6SSteve Lawrence zone = usage->zsu_zone; 3630efd4c9b6SSteve Lawrence if (usage->zsu_cpu_shares != ZS_LIMIT_NONE && 3631efd4c9b6SSteve Lawrence usage->zsu_cpu_shares != ZS_SHARES_UNLIMITED && 3632efd4c9b6SSteve Lawrence usage->zsu_cpu_shares != 0) { 3633efd4c9b6SSteve Lawrence /* 3634efd4c9b6SSteve Lawrence * Figure out how many nanoseconds of share time 3635efd4c9b6SSteve Lawrence * to give to the zone 3636efd4c9b6SSteve Lawrence */ 3637efd4c9b6SSteve Lawrence hrtime = delta.tv_sec; 3638efd4c9b6SSteve Lawrence hrtime *= NANOSEC; 3639efd4c9b6SSteve Lawrence hrtime += delta.tv_nsec; 3640efd4c9b6SSteve Lawrence hrtime *= usage->zsu_cpu_shares; 3641efd4c9b6SSteve Lawrence hrtime /= pset->zsp_cpu_shares; 3642efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(zone->zsz_share_time, 3643efd4c9b6SSteve Lawrence hrtime); 3644efd4c9b6SSteve Lawrence } 3645efd4c9b6SSteve Lawrence /* Add pset time to each zone using pset */ 3646efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(zone->zsz_pset_time, delta); 3647efd4c9b6SSteve Lawrence 3648efd4c9b6SSteve Lawrence zone->zsz_cpus_online += pset->zsp_online; 3649efd4c9b6SSteve Lawrence } 3650efd4c9b6SSteve Lawrence pset->zsp_total_time = ts; 3651efd4c9b6SSteve Lawrence } 3652efd4c9b6SSteve Lawrence 3653efd4c9b6SSteve Lawrence for (zone = list_head(&ctl->zsctl_zones); zone != NULL; 3654efd4c9b6SSteve Lawrence zone = list_next(&ctl->zsctl_zones, zone)) { 3655efd4c9b6SSteve Lawrence 3656efd4c9b6SSteve Lawrence /* update cpu cap tracking if the zone has a cpu cap */ 3657efd4c9b6SSteve Lawrence if (zone->zsz_cpu_cap != ZS_LIMIT_NONE) { 3658efd4c9b6SSteve Lawrence uint64_t elapsed; 3659efd4c9b6SSteve Lawrence 3660efd4c9b6SSteve Lawrence elapsed = ctl->zsctl_hrtime - ctl->zsctl_hrtime_prev; 3661efd4c9b6SSteve Lawrence elapsed *= zone->zsz_cpu_cap; 3662efd4c9b6SSteve Lawrence elapsed = elapsed / 100; 3663efd4c9b6SSteve Lawrence TIMESTRUC_ADD_NANOSEC(zone->zsz_cap_time, elapsed); 3664efd4c9b6SSteve Lawrence } 3665efd4c9b6SSteve Lawrence } 3666efd4c9b6SSteve Lawrence sys = ctl->zsctl_system; 3667efd4c9b6SSteve Lawrence ts.tv_sec = 0; 3668efd4c9b6SSteve Lawrence ts.tv_nsec = 0; 3669efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(ts, sys->zss_intr); 3670efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(ts, sys->zss_kern); 3671efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(ts, sys->zss_user); 3672efd4c9b6SSteve Lawrence 3673efd4c9b6SSteve Lawrence /* kernel time in pset is total time minus zone time */ 3674efd4c9b6SSteve Lawrence TIMESTRUC_DELTA(sys->zss_cpu_usage_kern, ts, 3675efd4c9b6SSteve Lawrence sys->zss_cpu_usage_zones); 3676efd4c9b6SSteve Lawrence if (sys->zss_cpu_usage_kern.tv_sec < 0 || 3677efd4c9b6SSteve Lawrence sys->zss_cpu_usage_kern.tv_nsec < 0) { 3678efd4c9b6SSteve Lawrence sys->zss_cpu_usage_kern.tv_sec = 0; 3679efd4c9b6SSteve Lawrence sys->zss_cpu_usage_kern.tv_nsec = 0; 3680efd4c9b6SSteve Lawrence } 3681efd4c9b6SSteve Lawrence /* Total pset elapsed time is used time plus idle time */ 3682efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(ts, sys->zss_idle); 3683efd4c9b6SSteve Lawrence sys->zss_cpu_total_time = ts; 3684efd4c9b6SSteve Lawrence } 3685efd4c9b6SSteve Lawrence 3686efd4c9b6SSteve Lawrence /* 3687efd4c9b6SSteve Lawrence * Saves current usage data to a cache that is read by libzonestat when 3688efd4c9b6SSteve Lawrence * calling zs_usage_read(). 3689efd4c9b6SSteve Lawrence * 3690efd4c9b6SSteve Lawrence * All pointers in the cached data structure are set to NULL. When 3691efd4c9b6SSteve Lawrence * libzonestat reads the cached data, it will set the pointers relative to 3692efd4c9b6SSteve Lawrence * its address space. 3693efd4c9b6SSteve Lawrence */ 3694efd4c9b6SSteve Lawrence static void 3695efd4c9b6SSteve Lawrence zsd_usage_cache_update(zsd_ctl_t *ctl) 3696efd4c9b6SSteve Lawrence { 3697efd4c9b6SSteve Lawrence zs_usage_cache_t *cache; 3698efd4c9b6SSteve Lawrence zs_usage_cache_t *old; 3699efd4c9b6SSteve Lawrence zs_usage_t *usage; 3700efd4c9b6SSteve Lawrence 3701efd4c9b6SSteve Lawrence zs_system_t *sys; 3702efd4c9b6SSteve Lawrence zsd_system_t *dsys; 3703efd4c9b6SSteve Lawrence zs_zone_t *zone = NULL; 3704efd4c9b6SSteve Lawrence zsd_zone_t *dzone; 3705efd4c9b6SSteve Lawrence zs_pset_t *pset = NULL; 3706efd4c9b6SSteve Lawrence zsd_pset_t *dpset; 3707efd4c9b6SSteve Lawrence zs_pset_zone_t *pusage; 3708efd4c9b6SSteve Lawrence zsd_pset_usage_t *dpusage; 3709efd4c9b6SSteve Lawrence 3710efd4c9b6SSteve Lawrence char *next; 3711efd4c9b6SSteve Lawrence uint_t size, i, j; 3712efd4c9b6SSteve Lawrence 3713efd4c9b6SSteve Lawrence size = 3714efd4c9b6SSteve Lawrence sizeof (zs_usage_cache_t) + 3715efd4c9b6SSteve Lawrence sizeof (zs_usage_t) + 3716efd4c9b6SSteve Lawrence sizeof (zs_system_t) + 3717efd4c9b6SSteve Lawrence sizeof (zs_zone_t) * ctl->zsctl_nzones + 3718efd4c9b6SSteve Lawrence sizeof (zs_pset_t) * ctl->zsctl_npsets + 3719efd4c9b6SSteve Lawrence sizeof (zs_pset_zone_t) * ctl->zsctl_npset_usages; 3720efd4c9b6SSteve Lawrence 3721efd4c9b6SSteve Lawrence cache = (zs_usage_cache_t *)malloc(size); 3722efd4c9b6SSteve Lawrence if (cache == NULL) { 3723efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to allocate usage cache\n")); 3724efd4c9b6SSteve Lawrence return; 3725efd4c9b6SSteve Lawrence } 3726efd4c9b6SSteve Lawrence 3727efd4c9b6SSteve Lawrence next = (char *)cache; 3728efd4c9b6SSteve Lawrence cache->zsuc_size = size - sizeof (zs_usage_cache_t); 3729efd4c9b6SSteve Lawrence next += sizeof (zs_usage_cache_t); 3730efd4c9b6SSteve Lawrence 3731efd4c9b6SSteve Lawrence /* LINTED */ 3732efd4c9b6SSteve Lawrence usage = cache->zsuc_usage = (zs_usage_t *)next; 3733efd4c9b6SSteve Lawrence next += sizeof (zs_usage_t); 3734efd4c9b6SSteve Lawrence usage->zsu_start = g_start; 3735efd4c9b6SSteve Lawrence usage->zsu_hrstart = g_hrstart; 3736efd4c9b6SSteve Lawrence usage->zsu_time = g_now; 3737efd4c9b6SSteve Lawrence usage->zsu_hrtime = g_hrnow; 3738efd4c9b6SSteve Lawrence usage->zsu_nzones = ctl->zsctl_nzones; 3739efd4c9b6SSteve Lawrence usage->zsu_npsets = ctl->zsctl_npsets; 3740efd4c9b6SSteve Lawrence usage->zsu_system = NULL; 3741efd4c9b6SSteve Lawrence 3742efd4c9b6SSteve Lawrence /* LINTED */ 3743efd4c9b6SSteve Lawrence sys = (zs_system_t *)next; 3744efd4c9b6SSteve Lawrence next += sizeof (zs_system_t); 3745efd4c9b6SSteve Lawrence dsys = ctl->zsctl_system; 3746efd4c9b6SSteve Lawrence sys->zss_ram_total = dsys->zss_ram_total; 3747efd4c9b6SSteve Lawrence sys->zss_ram_kern = dsys->zss_ram_kern; 3748efd4c9b6SSteve Lawrence sys->zss_ram_zones = dsys->zss_ram_zones; 3749efd4c9b6SSteve Lawrence sys->zss_locked_kern = dsys->zss_locked_kern; 3750efd4c9b6SSteve Lawrence sys->zss_locked_zones = dsys->zss_locked_zones; 3751efd4c9b6SSteve Lawrence sys->zss_vm_total = dsys->zss_vm_total; 3752efd4c9b6SSteve Lawrence sys->zss_vm_kern = dsys->zss_vm_kern; 3753efd4c9b6SSteve Lawrence sys->zss_vm_zones = dsys->zss_vm_zones; 3754efd4c9b6SSteve Lawrence sys->zss_swap_total = dsys->zss_swap_total; 3755efd4c9b6SSteve Lawrence sys->zss_swap_used = dsys->zss_swap_used; 3756efd4c9b6SSteve Lawrence sys->zss_ncpus = dsys->zss_ncpus; 3757efd4c9b6SSteve Lawrence sys->zss_ncpus_online = dsys->zss_ncpus_online; 3758efd4c9b6SSteve Lawrence 3759efd4c9b6SSteve Lawrence sys->zss_processes_max = dsys->zss_maxpid; 3760efd4c9b6SSteve Lawrence sys->zss_lwps_max = dsys->zss_lwps_max; 3761efd4c9b6SSteve Lawrence sys->zss_shm_max = dsys->zss_shm_max; 3762efd4c9b6SSteve Lawrence sys->zss_shmids_max = dsys->zss_shmids_max; 3763efd4c9b6SSteve Lawrence sys->zss_semids_max = dsys->zss_semids_max; 3764efd4c9b6SSteve Lawrence sys->zss_msgids_max = dsys->zss_msgids_max; 3765efd4c9b6SSteve Lawrence sys->zss_lofi_max = dsys->zss_lofi_max; 3766efd4c9b6SSteve Lawrence 3767efd4c9b6SSteve Lawrence sys->zss_processes = dsys->zss_processes; 3768efd4c9b6SSteve Lawrence sys->zss_lwps = dsys->zss_lwps; 3769efd4c9b6SSteve Lawrence sys->zss_shm = dsys->zss_shm; 3770efd4c9b6SSteve Lawrence sys->zss_shmids = dsys->zss_shmids; 3771efd4c9b6SSteve Lawrence sys->zss_semids = dsys->zss_semids; 3772efd4c9b6SSteve Lawrence sys->zss_msgids = dsys->zss_msgids; 3773efd4c9b6SSteve Lawrence sys->zss_lofi = dsys->zss_lofi; 3774efd4c9b6SSteve Lawrence 3775efd4c9b6SSteve Lawrence sys->zss_cpu_total_time = dsys->zss_cpu_total_time; 3776efd4c9b6SSteve Lawrence sys->zss_cpu_usage_zones = dsys->zss_cpu_usage_zones; 3777efd4c9b6SSteve Lawrence sys->zss_cpu_usage_kern = dsys->zss_cpu_usage_kern; 3778efd4c9b6SSteve Lawrence 3779efd4c9b6SSteve Lawrence for (i = 0, dzone = list_head(&ctl->zsctl_zones); 3780efd4c9b6SSteve Lawrence i < ctl->zsctl_nzones; 3781efd4c9b6SSteve Lawrence i++, dzone = list_next(&ctl->zsctl_zones, dzone)) { 3782efd4c9b6SSteve Lawrence /* LINTED */ 3783efd4c9b6SSteve Lawrence zone = (zs_zone_t *)next; 3784efd4c9b6SSteve Lawrence next += sizeof (zs_zone_t); 3785efd4c9b6SSteve Lawrence list_link_init(&zone->zsz_next); 3786efd4c9b6SSteve Lawrence zone->zsz_system = NULL; 3787efd4c9b6SSteve Lawrence 3788efd4c9b6SSteve Lawrence (void) strlcpy(zone->zsz_name, dzone->zsz_name, 3789efd4c9b6SSteve Lawrence sizeof (zone->zsz_name)); 3790efd4c9b6SSteve Lawrence (void) strlcpy(zone->zsz_pool, dzone->zsz_pool, 3791efd4c9b6SSteve Lawrence sizeof (zone->zsz_pool)); 3792efd4c9b6SSteve Lawrence (void) strlcpy(zone->zsz_pset, dzone->zsz_pset, 3793efd4c9b6SSteve Lawrence sizeof (zone->zsz_pset)); 3794efd4c9b6SSteve Lawrence zone->zsz_id = dzone->zsz_id; 3795efd4c9b6SSteve Lawrence zone->zsz_cputype = dzone->zsz_cputype; 3796efd4c9b6SSteve Lawrence zone->zsz_iptype = dzone->zsz_iptype; 3797efd4c9b6SSteve Lawrence zone->zsz_start = dzone->zsz_start; 3798efd4c9b6SSteve Lawrence zone->zsz_hrstart = dzone->zsz_hrstart; 3799efd4c9b6SSteve Lawrence zone->zsz_scheds = dzone->zsz_scheds; 3800efd4c9b6SSteve Lawrence zone->zsz_cpu_shares = dzone->zsz_cpu_shares; 3801efd4c9b6SSteve Lawrence zone->zsz_cpu_cap = dzone->zsz_cpu_cap; 3802efd4c9b6SSteve Lawrence zone->zsz_ram_cap = dzone->zsz_ram_cap; 3803efd4c9b6SSteve Lawrence zone->zsz_vm_cap = dzone->zsz_vm_cap; 3804efd4c9b6SSteve Lawrence zone->zsz_locked_cap = dzone->zsz_locked_cap; 3805efd4c9b6SSteve Lawrence zone->zsz_cpu_usage = dzone->zsz_cpu_usage; 3806efd4c9b6SSteve Lawrence zone->zsz_cpus_online = dzone->zsz_cpus_online; 3807efd4c9b6SSteve Lawrence zone->zsz_pset_time = dzone->zsz_pset_time; 3808efd4c9b6SSteve Lawrence zone->zsz_cap_time = dzone->zsz_cap_time; 3809efd4c9b6SSteve Lawrence zone->zsz_share_time = dzone->zsz_share_time; 3810efd4c9b6SSteve Lawrence zone->zsz_usage_ram = dzone->zsz_usage_ram; 3811efd4c9b6SSteve Lawrence zone->zsz_usage_locked = dzone->zsz_usage_locked; 3812efd4c9b6SSteve Lawrence zone->zsz_usage_vm = dzone->zsz_usage_vm; 3813efd4c9b6SSteve Lawrence 3814efd4c9b6SSteve Lawrence zone->zsz_processes_cap = dzone->zsz_processes_cap; 3815efd4c9b6SSteve Lawrence zone->zsz_lwps_cap = dzone->zsz_lwps_cap; 3816efd4c9b6SSteve Lawrence zone->zsz_shm_cap = dzone->zsz_shm_cap; 3817efd4c9b6SSteve Lawrence zone->zsz_shmids_cap = dzone->zsz_shmids_cap; 3818efd4c9b6SSteve Lawrence zone->zsz_semids_cap = dzone->zsz_semids_cap; 3819efd4c9b6SSteve Lawrence zone->zsz_msgids_cap = dzone->zsz_msgids_cap; 3820efd4c9b6SSteve Lawrence zone->zsz_lofi_cap = dzone->zsz_lofi_cap; 3821efd4c9b6SSteve Lawrence 3822efd4c9b6SSteve Lawrence zone->zsz_processes = dzone->zsz_processes; 3823efd4c9b6SSteve Lawrence zone->zsz_lwps = dzone->zsz_lwps; 3824efd4c9b6SSteve Lawrence zone->zsz_shm = dzone->zsz_shm; 3825efd4c9b6SSteve Lawrence zone->zsz_shmids = dzone->zsz_shmids; 3826efd4c9b6SSteve Lawrence zone->zsz_semids = dzone->zsz_semids; 3827efd4c9b6SSteve Lawrence zone->zsz_msgids = dzone->zsz_msgids; 3828efd4c9b6SSteve Lawrence zone->zsz_lofi = dzone->zsz_lofi; 3829efd4c9b6SSteve Lawrence } 3830efd4c9b6SSteve Lawrence 3831efd4c9b6SSteve Lawrence for (i = 0, dpset = list_head(&ctl->zsctl_psets); 3832efd4c9b6SSteve Lawrence i < ctl->zsctl_npsets; 3833efd4c9b6SSteve Lawrence i++, dpset = list_next(&ctl->zsctl_psets, dpset)) { 3834efd4c9b6SSteve Lawrence /* LINTED */ 3835efd4c9b6SSteve Lawrence pset = (zs_pset_t *)next; 3836efd4c9b6SSteve Lawrence next += sizeof (zs_pset_t); 3837efd4c9b6SSteve Lawrence list_link_init(&pset->zsp_next); 3838efd4c9b6SSteve Lawrence (void) strlcpy(pset->zsp_name, dpset->zsp_name, 3839efd4c9b6SSteve Lawrence sizeof (pset->zsp_name)); 3840efd4c9b6SSteve Lawrence pset->zsp_id = dpset->zsp_id; 3841efd4c9b6SSteve Lawrence pset->zsp_cputype = dpset->zsp_cputype; 3842efd4c9b6SSteve Lawrence pset->zsp_start = dpset->zsp_start; 3843efd4c9b6SSteve Lawrence pset->zsp_hrstart = dpset->zsp_hrstart; 3844efd4c9b6SSteve Lawrence pset->zsp_online = dpset->zsp_online; 3845efd4c9b6SSteve Lawrence pset->zsp_size = dpset->zsp_size; 3846efd4c9b6SSteve Lawrence pset->zsp_min = dpset->zsp_min; 3847efd4c9b6SSteve Lawrence pset->zsp_max = dpset->zsp_max; 3848efd4c9b6SSteve Lawrence pset->zsp_importance = dpset->zsp_importance; 3849efd4c9b6SSteve Lawrence pset->zsp_scheds = dpset->zsp_scheds; 3850efd4c9b6SSteve Lawrence pset->zsp_cpu_shares = dpset->zsp_cpu_shares; 3851efd4c9b6SSteve Lawrence pset->zsp_total_time = dpset->zsp_total_time; 3852efd4c9b6SSteve Lawrence pset->zsp_usage_kern = dpset->zsp_usage_kern; 3853efd4c9b6SSteve Lawrence pset->zsp_usage_zones = dpset->zsp_usage_zones; 3854efd4c9b6SSteve Lawrence pset->zsp_nusage = dpset->zsp_nusage; 3855efd4c9b6SSteve Lawrence /* Add pset usages for pset */ 3856efd4c9b6SSteve Lawrence for (j = 0, dpusage = list_head(&dpset->zsp_usage_list); 3857efd4c9b6SSteve Lawrence j < dpset->zsp_nusage; 3858efd4c9b6SSteve Lawrence j++, dpusage = list_next(&dpset->zsp_usage_list, dpusage)) { 3859efd4c9b6SSteve Lawrence /* LINTED */ 3860efd4c9b6SSteve Lawrence pusage = (zs_pset_zone_t *)next; 3861efd4c9b6SSteve Lawrence next += sizeof (zs_pset_zone_t); 3862efd4c9b6SSteve Lawrence /* pointers are computed by client */ 3863efd4c9b6SSteve Lawrence pusage->zspz_pset = NULL; 3864efd4c9b6SSteve Lawrence pusage->zspz_zone = NULL; 3865efd4c9b6SSteve Lawrence list_link_init(&pusage->zspz_next); 3866efd4c9b6SSteve Lawrence pusage->zspz_zoneid = dpusage->zsu_zone->zsz_id; 3867efd4c9b6SSteve Lawrence pusage->zspz_start = dpusage->zsu_start; 3868efd4c9b6SSteve Lawrence pusage->zspz_hrstart = dpusage->zsu_hrstart; 3869efd4c9b6SSteve Lawrence pusage->zspz_hrstart = dpusage->zsu_hrstart; 3870efd4c9b6SSteve Lawrence pusage->zspz_cpu_shares = dpusage->zsu_cpu_shares; 3871efd4c9b6SSteve Lawrence pusage->zspz_scheds = dpusage->zsu_scheds; 3872efd4c9b6SSteve Lawrence pusage->zspz_cpu_usage = dpusage->zsu_cpu_usage; 3873efd4c9b6SSteve Lawrence } 3874efd4c9b6SSteve Lawrence } 3875efd4c9b6SSteve Lawrence 3876efd4c9b6SSteve Lawrence /* Update the current cache pointer */ 3877efd4c9b6SSteve Lawrence (void) mutex_lock(&g_usage_cache_lock); 3878*8c4f1486SMarcel Telka old = g_usage_cache; 3879*8c4f1486SMarcel Telka cache->zsuc_ref = 1; 3880*8c4f1486SMarcel Telka cache->zsuc_gen = g_gen_next; 3881*8c4f1486SMarcel Telka usage->zsu_gen = g_gen_next; 3882*8c4f1486SMarcel Telka usage->zsu_size = size; 3883*8c4f1486SMarcel Telka g_usage_cache = cache; 3884*8c4f1486SMarcel Telka if (old != NULL) { 3885*8c4f1486SMarcel Telka old->zsuc_ref--; 3886*8c4f1486SMarcel Telka if (old->zsuc_ref == 0) 3887*8c4f1486SMarcel Telka free(old); 3888*8c4f1486SMarcel Telka } 3889*8c4f1486SMarcel Telka g_gen_next++; 3890efd4c9b6SSteve Lawrence /* Wake up any clients that are waiting for this calculation */ 3891efd4c9b6SSteve Lawrence if (g_usage_cache_kickers > 0) { 3892efd4c9b6SSteve Lawrence (void) cond_broadcast(&g_usage_cache_wait); 3893efd4c9b6SSteve Lawrence } 3894efd4c9b6SSteve Lawrence (void) mutex_unlock(&g_usage_cache_lock); 3895efd4c9b6SSteve Lawrence } 3896efd4c9b6SSteve Lawrence 3897efd4c9b6SSteve Lawrence static zs_usage_cache_t * 3898efd4c9b6SSteve Lawrence zsd_usage_cache_hold_locked() 3899efd4c9b6SSteve Lawrence { 3900efd4c9b6SSteve Lawrence zs_usage_cache_t *ret; 3901efd4c9b6SSteve Lawrence 3902efd4c9b6SSteve Lawrence ret = g_usage_cache; 3903efd4c9b6SSteve Lawrence ret->zsuc_ref++; 3904efd4c9b6SSteve Lawrence return (ret); 3905efd4c9b6SSteve Lawrence } 3906efd4c9b6SSteve Lawrence 3907efd4c9b6SSteve Lawrence void 3908efd4c9b6SSteve Lawrence zsd_usage_cache_rele(zs_usage_cache_t *cache) 3909efd4c9b6SSteve Lawrence { 3910efd4c9b6SSteve Lawrence (void) mutex_lock(&g_usage_cache_lock); 3911efd4c9b6SSteve Lawrence cache->zsuc_ref--; 3912efd4c9b6SSteve Lawrence if (cache->zsuc_ref == 0) 3913efd4c9b6SSteve Lawrence free(cache); 3914efd4c9b6SSteve Lawrence (void) mutex_unlock(&g_usage_cache_lock); 3915efd4c9b6SSteve Lawrence } 3916efd4c9b6SSteve Lawrence 3917efd4c9b6SSteve Lawrence /* Close the handles held by zsd_open() */ 3918efd4c9b6SSteve Lawrence void 3919efd4c9b6SSteve Lawrence zsd_close(zsd_ctl_t *ctl) 3920efd4c9b6SSteve Lawrence { 3921efd4c9b6SSteve Lawrence zsd_zone_t *zone; 3922efd4c9b6SSteve Lawrence zsd_pset_t *pset; 3923efd4c9b6SSteve Lawrence zsd_pset_usage_t *usage; 3924efd4c9b6SSteve Lawrence zsd_cpu_t *cpu; 3925efd4c9b6SSteve Lawrence int id; 3926efd4c9b6SSteve Lawrence 3927efd4c9b6SSteve Lawrence if (ctl->zsctl_kstat_ctl) { 3928efd4c9b6SSteve Lawrence (void) kstat_close(ctl->zsctl_kstat_ctl); 3929efd4c9b6SSteve Lawrence ctl->zsctl_kstat_ctl = NULL; 3930efd4c9b6SSteve Lawrence } 3931efd4c9b6SSteve Lawrence if (ctl->zsctl_proc_open) { 3932efd4c9b6SSteve Lawrence (void) ea_close(&ctl->zsctl_proc_eaf); 3933efd4c9b6SSteve Lawrence ctl->zsctl_proc_open = 0; 3934efd4c9b6SSteve Lawrence ctl->zsctl_proc_fd = -1; 3935efd4c9b6SSteve Lawrence } 3936efd4c9b6SSteve Lawrence if (ctl->zsctl_pool_conf) { 3937efd4c9b6SSteve Lawrence if (ctl->zsctl_pool_status == POOL_ENABLED) 3938efd4c9b6SSteve Lawrence (void) pool_conf_close(ctl->zsctl_pool_conf); 3939efd4c9b6SSteve Lawrence ctl->zsctl_pool_status = POOL_DISABLED; 3940efd4c9b6SSteve Lawrence } 3941efd4c9b6SSteve Lawrence 3942efd4c9b6SSteve Lawrence while ((zone = list_head(&ctl->zsctl_zones)) != NULL) { 3943efd4c9b6SSteve Lawrence list_remove(&ctl->zsctl_zones, zone); 3944efd4c9b6SSteve Lawrence free(zone); 3945efd4c9b6SSteve Lawrence ctl->zsctl_nzones--; 3946efd4c9b6SSteve Lawrence } 3947efd4c9b6SSteve Lawrence 3948efd4c9b6SSteve Lawrence while ((pset = list_head(&ctl->zsctl_psets)) != NULL) { 3949efd4c9b6SSteve Lawrence while ((usage = list_head(&pset->zsp_usage_list)) 3950efd4c9b6SSteve Lawrence != NULL) { 3951efd4c9b6SSteve Lawrence list_remove(&pset->zsp_usage_list, usage); 3952efd4c9b6SSteve Lawrence ctl->zsctl_npset_usages--; 3953efd4c9b6SSteve Lawrence free(usage); 3954efd4c9b6SSteve Lawrence } 3955efd4c9b6SSteve Lawrence list_remove(&ctl->zsctl_psets, pset); 3956efd4c9b6SSteve Lawrence free(pset); 3957efd4c9b6SSteve Lawrence ctl->zsctl_npsets--; 3958efd4c9b6SSteve Lawrence } 3959efd4c9b6SSteve Lawrence 3960efd4c9b6SSteve Lawrence /* Release all cpus being tracked */ 3961efd4c9b6SSteve Lawrence while (cpu = list_head(&ctl->zsctl_cpus)) { 3962efd4c9b6SSteve Lawrence list_remove(&ctl->zsctl_cpus, cpu); 3963efd4c9b6SSteve Lawrence id = cpu->zsc_id; 3964efd4c9b6SSteve Lawrence bzero(cpu, sizeof (zsd_cpu_t)); 3965efd4c9b6SSteve Lawrence cpu->zsc_id = id; 3966efd4c9b6SSteve Lawrence cpu->zsc_allocated = B_FALSE; 3967efd4c9b6SSteve Lawrence cpu->zsc_psetid = ZS_PSET_ERROR; 3968efd4c9b6SSteve Lawrence cpu->zsc_psetid_prev = ZS_PSET_ERROR; 3969efd4c9b6SSteve Lawrence } 3970efd4c9b6SSteve Lawrence 3971efd4c9b6SSteve Lawrence assert(ctl->zsctl_npset_usages == 0); 3972efd4c9b6SSteve Lawrence assert(ctl->zsctl_npsets == 0); 3973efd4c9b6SSteve Lawrence assert(ctl->zsctl_nzones == 0); 3974efd4c9b6SSteve Lawrence (void) zsd_disable_cpu_stats(); 3975efd4c9b6SSteve Lawrence } 3976efd4c9b6SSteve Lawrence 3977efd4c9b6SSteve Lawrence 3978efd4c9b6SSteve Lawrence /* 3979efd4c9b6SSteve Lawrence * Update the utilization data for all zones and processor sets. 3980efd4c9b6SSteve Lawrence */ 3981efd4c9b6SSteve Lawrence static int 3982efd4c9b6SSteve Lawrence zsd_read(zsd_ctl_t *ctl, boolean_t init, boolean_t do_memory) 3983efd4c9b6SSteve Lawrence { 3984efd4c9b6SSteve Lawrence (void) kstat_chain_update(ctl->zsctl_kstat_ctl); 3985efd4c9b6SSteve Lawrence (void) gettimeofday(&(ctl->zsctl_timeofday), NULL); 3986efd4c9b6SSteve Lawrence 3987efd4c9b6SSteve Lawrence zsd_refresh_system(ctl); 3988efd4c9b6SSteve Lawrence 3989efd4c9b6SSteve Lawrence /* 3990efd4c9b6SSteve Lawrence * Memory calculation is expensive. Only update it on sample 3991efd4c9b6SSteve Lawrence * intervals. 3992efd4c9b6SSteve Lawrence */ 3993efd4c9b6SSteve Lawrence if (do_memory == B_TRUE) 3994efd4c9b6SSteve Lawrence zsd_refresh_memory(ctl, init); 3995efd4c9b6SSteve Lawrence zsd_refresh_zones(ctl); 3996efd4c9b6SSteve Lawrence zsd_refresh_psets(ctl); 3997efd4c9b6SSteve Lawrence zsd_refresh_procs(ctl, init); 3998efd4c9b6SSteve Lawrence zsd_refresh_cpu_stats(ctl, init); 3999efd4c9b6SSteve Lawrence 4000efd4c9b6SSteve Lawrence /* 4001efd4c9b6SSteve Lawrence * Delete objects that no longer exist. 4002efd4c9b6SSteve Lawrence * Pset usages must be deleted first as they point to zone and 4003efd4c9b6SSteve Lawrence * pset objects. 4004efd4c9b6SSteve Lawrence */ 4005efd4c9b6SSteve Lawrence zsd_mark_pset_usages_end(ctl); 4006efd4c9b6SSteve Lawrence zsd_mark_psets_end(ctl); 4007efd4c9b6SSteve Lawrence zsd_mark_cpus_end(ctl); 4008efd4c9b6SSteve Lawrence zsd_mark_zones_end(ctl); 4009efd4c9b6SSteve Lawrence 4010efd4c9b6SSteve Lawrence /* 4011efd4c9b6SSteve Lawrence * Save results for clients. 4012efd4c9b6SSteve Lawrence */ 4013efd4c9b6SSteve Lawrence zsd_usage_cache_update(ctl); 4014efd4c9b6SSteve Lawrence 4015efd4c9b6SSteve Lawrence /* 4016efd4c9b6SSteve Lawrence * Roll process accounting file. 4017efd4c9b6SSteve Lawrence */ 4018efd4c9b6SSteve Lawrence (void) zsd_roll_exacct(); 4019efd4c9b6SSteve Lawrence return (0); 4020efd4c9b6SSteve Lawrence } 4021efd4c9b6SSteve Lawrence 4022efd4c9b6SSteve Lawrence /* 4023efd4c9b6SSteve Lawrence * Get the system rctl, which is the upper most limit 4024efd4c9b6SSteve Lawrence */ 4025efd4c9b6SSteve Lawrence static uint64_t 4026efd4c9b6SSteve Lawrence zsd_get_system_rctl(char *name) 4027efd4c9b6SSteve Lawrence { 4028efd4c9b6SSteve Lawrence rctlblk_t *rblk, *rblk_last; 4029efd4c9b6SSteve Lawrence 4030efd4c9b6SSteve Lawrence rblk = (rctlblk_t *)alloca(rctlblk_size()); 4031efd4c9b6SSteve Lawrence rblk_last = (rctlblk_t *)alloca(rctlblk_size()); 4032efd4c9b6SSteve Lawrence 4033efd4c9b6SSteve Lawrence if (getrctl(name, NULL, rblk_last, RCTL_FIRST) != 0) 4034efd4c9b6SSteve Lawrence return (ZS_LIMIT_NONE); 4035efd4c9b6SSteve Lawrence 4036efd4c9b6SSteve Lawrence while (getrctl(name, rblk_last, rblk, RCTL_NEXT) == 0) 4037efd4c9b6SSteve Lawrence (void) bcopy(rblk, rblk_last, rctlblk_size()); 4038efd4c9b6SSteve Lawrence 4039efd4c9b6SSteve Lawrence return (rctlblk_get_value(rblk_last)); 4040efd4c9b6SSteve Lawrence } 4041efd4c9b6SSteve Lawrence 4042efd4c9b6SSteve Lawrence /* 4043efd4c9b6SSteve Lawrence * Open any necessary subsystems for collecting utilization data, 4044efd4c9b6SSteve Lawrence * allocate and initialize data structures, and get initial utilization. 4045efd4c9b6SSteve Lawrence * 4046efd4c9b6SSteve Lawrence * Errors: 4047efd4c9b6SSteve Lawrence * ENOMEM out of memory 4048efd4c9b6SSteve Lawrence * EINVAL other error 4049efd4c9b6SSteve Lawrence */ 4050efd4c9b6SSteve Lawrence static zsd_ctl_t * 4051efd4c9b6SSteve Lawrence zsd_open(zsd_ctl_t *ctl) 4052efd4c9b6SSteve Lawrence { 4053efd4c9b6SSteve Lawrence zsd_system_t *system; 4054efd4c9b6SSteve Lawrence 4055efd4c9b6SSteve Lawrence char path[MAXPATHLEN]; 4056efd4c9b6SSteve Lawrence long pathmax; 4057efd4c9b6SSteve Lawrence struct statvfs svfs; 4058efd4c9b6SSteve Lawrence int ret; 4059efd4c9b6SSteve Lawrence int i; 4060efd4c9b6SSteve Lawrence size_t size; 4061efd4c9b6SSteve Lawrence int err; 4062efd4c9b6SSteve Lawrence 4063efd4c9b6SSteve Lawrence if (ctl == NULL && (ctl = (zsd_ctl_t *)calloc(1, 4064efd4c9b6SSteve Lawrence sizeof (zsd_ctl_t))) == NULL) { 4065efd4c9b6SSteve Lawrence zsd_warn(gettext("Out of Memory")); 4066efd4c9b6SSteve Lawrence errno = ENOMEM; 4067efd4c9b6SSteve Lawrence goto err; 4068efd4c9b6SSteve Lawrence } 4069efd4c9b6SSteve Lawrence ctl->zsctl_proc_fd = -1; 4070efd4c9b6SSteve Lawrence 4071efd4c9b6SSteve Lawrence /* open kstats */ 4072efd4c9b6SSteve Lawrence if (ctl->zsctl_kstat_ctl == NULL && 4073efd4c9b6SSteve Lawrence (ctl->zsctl_kstat_ctl = kstat_open()) == NULL) { 4074efd4c9b6SSteve Lawrence err = errno; 4075efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to open kstats")); 4076efd4c9b6SSteve Lawrence errno = err; 4077efd4c9b6SSteve Lawrence if (errno != ENOMEM) 4078efd4c9b6SSteve Lawrence errno = EAGAIN; 4079efd4c9b6SSteve Lawrence goto err; 4080efd4c9b6SSteve Lawrence } 4081efd4c9b6SSteve Lawrence 4082efd4c9b6SSteve Lawrence /* 4083efd4c9b6SSteve Lawrence * These are set when the accounting file is opened by 4084efd4c9b6SSteve Lawrence * zsd_update_procs() 4085efd4c9b6SSteve Lawrence */ 4086efd4c9b6SSteve Lawrence ctl->zsctl_proc_fd = -1; 4087efd4c9b6SSteve Lawrence ctl->zsctl_proc_fd_next = -1; 4088efd4c9b6SSteve Lawrence ctl->zsctl_proc_open = 0; 4089efd4c9b6SSteve Lawrence ctl->zsctl_proc_open_next = 0; 4090efd4c9b6SSteve Lawrence 4091efd4c9b6SSteve Lawrence check_exacct: 4092efd4c9b6SSteve Lawrence (void) zsd_enable_cpu_stats(); 4093efd4c9b6SSteve Lawrence 4094efd4c9b6SSteve Lawrence /* Create structures to track usage */ 4095efd4c9b6SSteve Lawrence if (ctl->zsctl_system == NULL && (ctl->zsctl_system = (zsd_system_t *) 4096efd4c9b6SSteve Lawrence calloc(1, sizeof (zsd_system_t))) == NULL) { 4097efd4c9b6SSteve Lawrence ret = -1; 4098efd4c9b6SSteve Lawrence zsd_warn(gettext("Out of Memory")); 4099efd4c9b6SSteve Lawrence errno = ENOMEM; 4100efd4c9b6SSteve Lawrence goto err; 4101efd4c9b6SSteve Lawrence } 4102efd4c9b6SSteve Lawrence system = ctl->zsctl_system; 4103efd4c9b6SSteve Lawrence /* get the kernel bitness to know structure layout for getvmusage */ 4104efd4c9b6SSteve Lawrence ret = sysinfo(SI_ARCHITECTURE_64, path, sizeof (path)); 4105efd4c9b6SSteve Lawrence if (ret < 0) 4106efd4c9b6SSteve Lawrence ctl->zsctl_kern_bits = 32; 4107efd4c9b6SSteve Lawrence else 4108efd4c9b6SSteve Lawrence ctl->zsctl_kern_bits = 64; 4109efd4c9b6SSteve Lawrence ctl->zsctl_pagesize = sysconf(_SC_PAGESIZE); 4110efd4c9b6SSteve Lawrence 4111efd4c9b6SSteve Lawrence size = sysconf(_SC_CPUID_MAX); 4112efd4c9b6SSteve Lawrence ctl->zsctl_maxcpuid = size; 4113efd4c9b6SSteve Lawrence if (ctl->zsctl_cpu_array == NULL && (ctl->zsctl_cpu_array = 4114efd4c9b6SSteve Lawrence (zsd_cpu_t *)calloc(size + 1, sizeof (zsd_cpu_t))) == NULL) { 4115efd4c9b6SSteve Lawrence zsd_warn(gettext("Out of Memory")); 4116efd4c9b6SSteve Lawrence errno = ENOMEM; 4117efd4c9b6SSteve Lawrence goto err; 4118efd4c9b6SSteve Lawrence } 4119efd4c9b6SSteve Lawrence for (i = 0; i <= ctl->zsctl_maxcpuid; i++) { 4120efd4c9b6SSteve Lawrence ctl->zsctl_cpu_array[i].zsc_id = i; 4121efd4c9b6SSteve Lawrence ctl->zsctl_cpu_array[i].zsc_allocated = B_FALSE; 4122efd4c9b6SSteve Lawrence ctl->zsctl_cpu_array[i].zsc_psetid = ZS_PSET_ERROR; 4123efd4c9b6SSteve Lawrence ctl->zsctl_cpu_array[i].zsc_psetid_prev = ZS_PSET_ERROR; 4124efd4c9b6SSteve Lawrence } 4125efd4c9b6SSteve Lawrence if (statvfs("/proc", &svfs) != 0 || 4126efd4c9b6SSteve Lawrence strcmp("/proc", svfs.f_fstr) != 0) { 4127efd4c9b6SSteve Lawrence zsd_warn(gettext("/proc not a procfs filesystem")); 4128efd4c9b6SSteve Lawrence errno = EINVAL; 4129efd4c9b6SSteve Lawrence goto err; 4130efd4c9b6SSteve Lawrence } 4131efd4c9b6SSteve Lawrence 4132efd4c9b6SSteve Lawrence size = sysconf(_SC_MAXPID) + 1; 4133efd4c9b6SSteve Lawrence ctl->zsctl_maxproc = size; 4134efd4c9b6SSteve Lawrence if (ctl->zsctl_proc_array == NULL && 4135efd4c9b6SSteve Lawrence (ctl->zsctl_proc_array = (zsd_proc_t *)calloc(size, 4136efd4c9b6SSteve Lawrence sizeof (zsd_proc_t))) == NULL) { 4137efd4c9b6SSteve Lawrence zsd_warn(gettext("Out of Memory")); 4138efd4c9b6SSteve Lawrence errno = ENOMEM; 4139efd4c9b6SSteve Lawrence goto err; 4140efd4c9b6SSteve Lawrence } 4141efd4c9b6SSteve Lawrence for (i = 0; i <= ctl->zsctl_maxproc; i++) { 4142efd4c9b6SSteve Lawrence list_link_init(&(ctl->zsctl_proc_array[i].zspr_next)); 4143efd4c9b6SSteve Lawrence ctl->zsctl_proc_array[i].zspr_psetid = ZS_PSET_ERROR; 4144efd4c9b6SSteve Lawrence ctl->zsctl_proc_array[i].zspr_zoneid = -1; 4145efd4c9b6SSteve Lawrence ctl->zsctl_proc_array[i].zspr_usage.tv_sec = 0; 4146efd4c9b6SSteve Lawrence ctl->zsctl_proc_array[i].zspr_usage.tv_nsec = 0; 4147efd4c9b6SSteve Lawrence ctl->zsctl_proc_array[i].zspr_ppid = -1; 4148efd4c9b6SSteve Lawrence } 4149efd4c9b6SSteve Lawrence 4150efd4c9b6SSteve Lawrence list_create(&ctl->zsctl_zones, sizeof (zsd_zone_t), 4151efd4c9b6SSteve Lawrence offsetof(zsd_zone_t, zsz_next)); 4152efd4c9b6SSteve Lawrence 4153efd4c9b6SSteve Lawrence list_create(&ctl->zsctl_psets, sizeof (zsd_pset_t), 4154efd4c9b6SSteve Lawrence offsetof(zsd_pset_t, zsp_next)); 4155efd4c9b6SSteve Lawrence 4156efd4c9b6SSteve Lawrence list_create(&ctl->zsctl_cpus, sizeof (zsd_cpu_t), 4157efd4c9b6SSteve Lawrence offsetof(zsd_cpu_t, zsc_next)); 4158efd4c9b6SSteve Lawrence 4159efd4c9b6SSteve Lawrence pathmax = pathconf("/proc", _PC_NAME_MAX); 4160efd4c9b6SSteve Lawrence if (pathmax < 0) { 4161efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to determine max path of /proc")); 4162efd4c9b6SSteve Lawrence errno = EINVAL; 4163efd4c9b6SSteve Lawrence goto err; 4164efd4c9b6SSteve Lawrence } 4165efd4c9b6SSteve Lawrence size = sizeof (struct dirent) + pathmax + 1; 4166efd4c9b6SSteve Lawrence 4167efd4c9b6SSteve Lawrence ctl->zsctl_procfs_dent_size = size; 4168efd4c9b6SSteve Lawrence if (ctl->zsctl_procfs_dent == NULL && 4169efd4c9b6SSteve Lawrence (ctl->zsctl_procfs_dent = (struct dirent *)calloc(1, size)) 4170efd4c9b6SSteve Lawrence == NULL) { 4171efd4c9b6SSteve Lawrence zsd_warn(gettext("Out of Memory")); 4172efd4c9b6SSteve Lawrence errno = ENOMEM; 4173efd4c9b6SSteve Lawrence goto err; 4174efd4c9b6SSteve Lawrence } 4175efd4c9b6SSteve Lawrence 4176efd4c9b6SSteve Lawrence if (ctl->zsctl_pool_conf == NULL && 4177efd4c9b6SSteve Lawrence (ctl->zsctl_pool_conf = pool_conf_alloc()) == NULL) { 4178efd4c9b6SSteve Lawrence zsd_warn(gettext("Out of Memory")); 4179efd4c9b6SSteve Lawrence errno = ENOMEM; 4180efd4c9b6SSteve Lawrence goto err; 4181efd4c9b6SSteve Lawrence } 4182efd4c9b6SSteve Lawrence ctl->zsctl_pool_status = POOL_DISABLED; 4183efd4c9b6SSteve Lawrence ctl->zsctl_pool_changed = 0; 4184efd4c9b6SSteve Lawrence 4185efd4c9b6SSteve Lawrence if (ctl->zsctl_pool_vals[0] == NULL && 4186efd4c9b6SSteve Lawrence (ctl->zsctl_pool_vals[0] = pool_value_alloc()) == NULL) { 4187efd4c9b6SSteve Lawrence zsd_warn(gettext("Out of Memory")); 4188efd4c9b6SSteve Lawrence errno = ENOMEM; 4189efd4c9b6SSteve Lawrence goto err; 4190efd4c9b6SSteve Lawrence } 4191efd4c9b6SSteve Lawrence if (ctl->zsctl_pool_vals[1] == NULL && 4192efd4c9b6SSteve Lawrence (ctl->zsctl_pool_vals[1] = pool_value_alloc()) == NULL) { 4193efd4c9b6SSteve Lawrence zsd_warn(gettext("Out of Memory")); 4194efd4c9b6SSteve Lawrence errno = ENOMEM; 4195efd4c9b6SSteve Lawrence goto err; 4196efd4c9b6SSteve Lawrence } 4197efd4c9b6SSteve Lawrence ctl->zsctl_pool_vals[2] = NULL; 4198efd4c9b6SSteve Lawrence 4199efd4c9b6SSteve Lawrence /* 4200efd4c9b6SSteve Lawrence * get system limits 4201efd4c9b6SSteve Lawrence */ 4202efd4c9b6SSteve Lawrence system->zss_maxpid = size = sysconf(_SC_MAXPID); 4203efd4c9b6SSteve Lawrence system->zss_processes_max = zsd_get_system_rctl("zone.max-processes"); 4204efd4c9b6SSteve Lawrence system->zss_lwps_max = zsd_get_system_rctl("zone.max-lwps"); 4205efd4c9b6SSteve Lawrence system->zss_shm_max = zsd_get_system_rctl("zone.max-shm-memory"); 4206efd4c9b6SSteve Lawrence system->zss_shmids_max = zsd_get_system_rctl("zone.max-shm-ids"); 4207efd4c9b6SSteve Lawrence system->zss_semids_max = zsd_get_system_rctl("zone.max-sem-ids"); 4208efd4c9b6SSteve Lawrence system->zss_msgids_max = zsd_get_system_rctl("zone.max-msg-ids"); 4209efd4c9b6SSteve Lawrence system->zss_lofi_max = zsd_get_system_rctl("zone.max-lofi"); 4210efd4c9b6SSteve Lawrence 4211efd4c9b6SSteve Lawrence g_gen_next = 1; 4212efd4c9b6SSteve Lawrence 4213efd4c9b6SSteve Lawrence if (zsd_read(ctl, B_TRUE, B_FALSE) != 0) 4214efd4c9b6SSteve Lawrence zsd_warn(gettext("Reading zone statistics failed")); 4215efd4c9b6SSteve Lawrence 4216efd4c9b6SSteve Lawrence return (ctl); 4217efd4c9b6SSteve Lawrence err: 4218efd4c9b6SSteve Lawrence if (ctl) 4219efd4c9b6SSteve Lawrence zsd_close(ctl); 4220efd4c9b6SSteve Lawrence 4221efd4c9b6SSteve Lawrence return (NULL); 4222efd4c9b6SSteve Lawrence } 4223efd4c9b6SSteve Lawrence 4224efd4c9b6SSteve Lawrence /* Copy utilization data to buffer, filtering data if non-global zone. */ 4225efd4c9b6SSteve Lawrence static void 4226efd4c9b6SSteve Lawrence zsd_usage_filter(zoneid_t zid, zs_usage_cache_t *cache, zs_usage_t *usage, 4227efd4c9b6SSteve Lawrence boolean_t is_gz) 4228efd4c9b6SSteve Lawrence { 4229efd4c9b6SSteve Lawrence zs_usage_t *cusage; 4230efd4c9b6SSteve Lawrence zs_system_t *sys, *csys; 4231efd4c9b6SSteve Lawrence zs_zone_t *zone, *czone; 4232efd4c9b6SSteve Lawrence zs_pset_t *pset, *cpset; 4233efd4c9b6SSteve Lawrence zs_pset_zone_t *pz, *cpz, *foundpz; 4234efd4c9b6SSteve Lawrence size_t size = 0, csize = 0; 4235efd4c9b6SSteve Lawrence char *start, *cstart; 4236efd4c9b6SSteve Lawrence int i, j; 4237efd4c9b6SSteve Lawrence timestruc_t delta; 4238efd4c9b6SSteve Lawrence 4239efd4c9b6SSteve Lawrence /* Privileged users in the global zone get everything */ 4240efd4c9b6SSteve Lawrence if (is_gz) { 4241efd4c9b6SSteve Lawrence cusage = cache->zsuc_usage; 4242efd4c9b6SSteve Lawrence (void) bcopy(cusage, usage, cusage->zsu_size); 4243efd4c9b6SSteve Lawrence return; 4244efd4c9b6SSteve Lawrence } 4245efd4c9b6SSteve Lawrence 4246efd4c9b6SSteve Lawrence /* Zones just get their own usage */ 4247efd4c9b6SSteve Lawrence cusage = cache->zsuc_usage; 4248efd4c9b6SSteve Lawrence 4249efd4c9b6SSteve Lawrence start = (char *)usage; 4250efd4c9b6SSteve Lawrence cstart = (char *)cusage; 4251efd4c9b6SSteve Lawrence size += sizeof (zs_usage_t); 4252efd4c9b6SSteve Lawrence csize += sizeof (zs_usage_t); 4253efd4c9b6SSteve Lawrence 4254efd4c9b6SSteve Lawrence usage->zsu_start = cusage->zsu_start; 4255efd4c9b6SSteve Lawrence usage->zsu_hrstart = cusage->zsu_hrstart; 4256efd4c9b6SSteve Lawrence usage->zsu_time = cusage->zsu_time; 4257efd4c9b6SSteve Lawrence usage->zsu_hrtime = cusage->zsu_hrtime; 4258efd4c9b6SSteve Lawrence usage->zsu_gen = cusage->zsu_gen; 4259efd4c9b6SSteve Lawrence usage->zsu_nzones = 1; 4260efd4c9b6SSteve Lawrence usage->zsu_npsets = 0; 4261efd4c9b6SSteve Lawrence 4262efd4c9b6SSteve Lawrence /* LINTED */ 4263efd4c9b6SSteve Lawrence sys = (zs_system_t *)(start + size); 4264efd4c9b6SSteve Lawrence /* LINTED */ 4265efd4c9b6SSteve Lawrence csys = (zs_system_t *)(cstart + csize); 4266efd4c9b6SSteve Lawrence size += sizeof (zs_system_t); 4267efd4c9b6SSteve Lawrence csize += sizeof (zs_system_t); 4268efd4c9b6SSteve Lawrence 4269efd4c9b6SSteve Lawrence /* Save system limits but not usage */ 4270efd4c9b6SSteve Lawrence *sys = *csys; 4271efd4c9b6SSteve Lawrence sys->zss_ncpus = 0; 4272efd4c9b6SSteve Lawrence sys->zss_ncpus_online = 0; 4273efd4c9b6SSteve Lawrence 4274efd4c9b6SSteve Lawrence /* LINTED */ 4275efd4c9b6SSteve Lawrence zone = (zs_zone_t *)(start + size); 4276efd4c9b6SSteve Lawrence /* LINTED */ 4277efd4c9b6SSteve Lawrence czone = (zs_zone_t *)(cstart + csize); 4278efd4c9b6SSteve Lawrence /* Find the matching zone */ 4279efd4c9b6SSteve Lawrence for (i = 0; i < cusage->zsu_nzones; i++) { 4280efd4c9b6SSteve Lawrence if (czone->zsz_id == zid) { 4281efd4c9b6SSteve Lawrence *zone = *czone; 4282efd4c9b6SSteve Lawrence size += sizeof (zs_zone_t); 4283efd4c9b6SSteve Lawrence } 4284efd4c9b6SSteve Lawrence csize += sizeof (zs_zone_t); 4285efd4c9b6SSteve Lawrence /* LINTED */ 4286efd4c9b6SSteve Lawrence czone = (zs_zone_t *)(cstart + csize); 4287efd4c9b6SSteve Lawrence } 4288efd4c9b6SSteve Lawrence sys->zss_ram_kern += (sys->zss_ram_zones - zone->zsz_usage_ram); 4289efd4c9b6SSteve Lawrence sys->zss_ram_zones = zone->zsz_usage_ram; 4290efd4c9b6SSteve Lawrence 4291efd4c9b6SSteve Lawrence sys->zss_vm_kern += (sys->zss_vm_zones - zone->zsz_usage_vm); 4292efd4c9b6SSteve Lawrence sys->zss_vm_zones = zone->zsz_usage_vm; 4293efd4c9b6SSteve Lawrence 4294efd4c9b6SSteve Lawrence sys->zss_locked_kern += (sys->zss_locked_zones - 4295efd4c9b6SSteve Lawrence zone->zsz_usage_locked); 4296efd4c9b6SSteve Lawrence sys->zss_locked_zones = zone->zsz_usage_locked; 4297efd4c9b6SSteve Lawrence 4298efd4c9b6SSteve Lawrence TIMESTRUC_DELTA(delta, sys->zss_cpu_usage_zones, zone->zsz_cpu_usage); 4299efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(sys->zss_cpu_usage_kern, delta); 4300efd4c9b6SSteve Lawrence sys->zss_cpu_usage_zones = zone->zsz_cpu_usage; 4301efd4c9b6SSteve Lawrence 4302efd4c9b6SSteve Lawrence /* LINTED */ 4303efd4c9b6SSteve Lawrence pset = (zs_pset_t *)(start + size); 4304efd4c9b6SSteve Lawrence /* LINTED */ 4305efd4c9b6SSteve Lawrence cpset = (zs_pset_t *)(cstart + csize); 4306efd4c9b6SSteve Lawrence for (i = 0; i < cusage->zsu_npsets; i++) { 4307efd4c9b6SSteve Lawrence csize += sizeof (zs_pset_t); 4308efd4c9b6SSteve Lawrence /* LINTED */ 4309efd4c9b6SSteve Lawrence cpz = (zs_pset_zone_t *)(csize + cstart); 4310efd4c9b6SSteve Lawrence foundpz = NULL; 4311efd4c9b6SSteve Lawrence for (j = 0; j < cpset->zsp_nusage; j++) { 4312efd4c9b6SSteve Lawrence if (cpz->zspz_zoneid == zid) 4313efd4c9b6SSteve Lawrence foundpz = cpz; 4314efd4c9b6SSteve Lawrence 4315efd4c9b6SSteve Lawrence csize += sizeof (zs_pset_zone_t); 4316efd4c9b6SSteve Lawrence /* LINTED */ 4317efd4c9b6SSteve Lawrence cpz = (zs_pset_zone_t *)(csize + cstart); 4318efd4c9b6SSteve Lawrence } 4319efd4c9b6SSteve Lawrence if (foundpz != NULL) { 4320efd4c9b6SSteve Lawrence size += sizeof (zs_pset_t); 4321efd4c9b6SSteve Lawrence /* LINTED */ 4322efd4c9b6SSteve Lawrence pz = (zs_pset_zone_t *)(start + size); 4323efd4c9b6SSteve Lawrence size += sizeof (zs_pset_zone_t); 4324efd4c9b6SSteve Lawrence 4325efd4c9b6SSteve Lawrence *pset = *cpset; 4326efd4c9b6SSteve Lawrence *pz = *foundpz; 4327efd4c9b6SSteve Lawrence 4328efd4c9b6SSteve Lawrence TIMESTRUC_DELTA(delta, pset->zsp_usage_zones, 4329efd4c9b6SSteve Lawrence pz->zspz_cpu_usage); 4330efd4c9b6SSteve Lawrence TIMESTRUC_ADD_TIMESTRUC(pset->zsp_usage_kern, delta); 4331efd4c9b6SSteve Lawrence pset->zsp_usage_zones = pz->zspz_cpu_usage; 4332efd4c9b6SSteve Lawrence pset->zsp_nusage = 1; 4333efd4c9b6SSteve Lawrence usage->zsu_npsets++; 4334efd4c9b6SSteve Lawrence sys->zss_ncpus += pset->zsp_size; 4335efd4c9b6SSteve Lawrence sys->zss_ncpus_online += pset->zsp_online; 4336efd4c9b6SSteve Lawrence } 4337efd4c9b6SSteve Lawrence /* LINTED */ 4338efd4c9b6SSteve Lawrence cpset = (zs_pset_t *)(cstart + csize); 4339efd4c9b6SSteve Lawrence } 4340efd4c9b6SSteve Lawrence usage->zsu_size = size; 4341efd4c9b6SSteve Lawrence } 4342efd4c9b6SSteve Lawrence 4343efd4c9b6SSteve Lawrence /* 4344efd4c9b6SSteve Lawrence * Respond to new connections from libzonestat.so. Also respond to zoneadmd, 4345efd4c9b6SSteve Lawrence * which reports new zones. 4346efd4c9b6SSteve Lawrence */ 4347efd4c9b6SSteve Lawrence /* ARGSUSED */ 4348efd4c9b6SSteve Lawrence static void 4349efd4c9b6SSteve Lawrence zsd_server(void *cookie, char *argp, size_t arg_size, 4350efd4c9b6SSteve Lawrence door_desc_t *dp, uint_t n_desc) 4351efd4c9b6SSteve Lawrence { 4352efd4c9b6SSteve Lawrence int *args, cmd; 4353efd4c9b6SSteve Lawrence door_desc_t door; 4354efd4c9b6SSteve Lawrence ucred_t *ucred; 4355efd4c9b6SSteve Lawrence const priv_set_t *eset; 4356efd4c9b6SSteve Lawrence 4357efd4c9b6SSteve Lawrence if (argp == DOOR_UNREF_DATA) { 4358efd4c9b6SSteve Lawrence (void) door_return(NULL, 0, NULL, 0); 4359efd4c9b6SSteve Lawrence thr_exit(NULL); 4360efd4c9b6SSteve Lawrence } 4361efd4c9b6SSteve Lawrence 4362efd4c9b6SSteve Lawrence if (arg_size != sizeof (cmd) * 2) { 4363efd4c9b6SSteve Lawrence (void) door_return(NULL, 0, NULL, 0); 4364efd4c9b6SSteve Lawrence thr_exit(NULL); 4365efd4c9b6SSteve Lawrence } 4366efd4c9b6SSteve Lawrence 4367efd4c9b6SSteve Lawrence /* LINTED */ 4368efd4c9b6SSteve Lawrence args = (int *)argp; 4369efd4c9b6SSteve Lawrence cmd = args[0]; 4370efd4c9b6SSteve Lawrence 4371efd4c9b6SSteve Lawrence /* If connection, return door to stat server */ 4372efd4c9b6SSteve Lawrence if (cmd == ZSD_CMD_CONNECT) { 4373efd4c9b6SSteve Lawrence 4374efd4c9b6SSteve Lawrence /* Verify client compilation version */ 4375efd4c9b6SSteve Lawrence if (args[1] != ZS_VERSION) { 4376efd4c9b6SSteve Lawrence args[1] = ZSD_STATUS_VERSION_MISMATCH; 4377efd4c9b6SSteve Lawrence (void) door_return(argp, sizeof (cmd) * 2, NULL, 0); 4378efd4c9b6SSteve Lawrence thr_exit(NULL); 4379efd4c9b6SSteve Lawrence } 4380efd4c9b6SSteve Lawrence ucred = alloca(ucred_size()); 4381efd4c9b6SSteve Lawrence /* Verify client permission */ 4382efd4c9b6SSteve Lawrence if (door_ucred(&ucred) != 0) { 4383efd4c9b6SSteve Lawrence args[1] = ZSD_STATUS_INTERNAL_ERROR; 4384efd4c9b6SSteve Lawrence (void) door_return(argp, sizeof (cmd) * 2, NULL, 0); 4385efd4c9b6SSteve Lawrence thr_exit(NULL); 4386efd4c9b6SSteve Lawrence } 4387efd4c9b6SSteve Lawrence 4388efd4c9b6SSteve Lawrence eset = ucred_getprivset(ucred, PRIV_EFFECTIVE); 4389efd4c9b6SSteve Lawrence if (eset == NULL) { 4390efd4c9b6SSteve Lawrence args[1] = ZSD_STATUS_INTERNAL_ERROR; 4391efd4c9b6SSteve Lawrence (void) door_return(argp, sizeof (cmd) * 2, NULL, 0); 4392efd4c9b6SSteve Lawrence thr_exit(NULL); 4393efd4c9b6SSteve Lawrence } 4394efd4c9b6SSteve Lawrence if (!priv_ismember(eset, PRIV_PROC_INFO)) { 4395efd4c9b6SSteve Lawrence args[1] = ZSD_STATUS_PERMISSION; 4396efd4c9b6SSteve Lawrence (void) door_return(argp, sizeof (cmd) * 2, NULL, 0); 4397efd4c9b6SSteve Lawrence thr_exit(NULL); 4398efd4c9b6SSteve Lawrence } 4399efd4c9b6SSteve Lawrence 4400efd4c9b6SSteve Lawrence /* Return stat server door */ 4401efd4c9b6SSteve Lawrence args[1] = ZSD_STATUS_OK; 4402efd4c9b6SSteve Lawrence door.d_attributes = DOOR_DESCRIPTOR; 4403efd4c9b6SSteve Lawrence door.d_data.d_desc.d_descriptor = g_stat_door; 4404efd4c9b6SSteve Lawrence (void) door_return(argp, sizeof (cmd) * 2, &door, 1); 4405efd4c9b6SSteve Lawrence thr_exit(NULL); 4406efd4c9b6SSteve Lawrence } 4407efd4c9b6SSteve Lawrence 4408efd4c9b6SSteve Lawrence /* Respond to zoneadmd informing zonestatd of a new zone */ 4409efd4c9b6SSteve Lawrence if (cmd == ZSD_CMD_NEW_ZONE) { 4410efd4c9b6SSteve Lawrence zsd_fattach_zone(args[1], g_server_door, B_FALSE); 4411efd4c9b6SSteve Lawrence (void) door_return(NULL, 0, NULL, 0); 4412efd4c9b6SSteve Lawrence thr_exit(NULL); 4413efd4c9b6SSteve Lawrence } 4414efd4c9b6SSteve Lawrence 4415efd4c9b6SSteve Lawrence args[1] = ZSD_STATUS_INTERNAL_ERROR; 4416efd4c9b6SSteve Lawrence (void) door_return(argp, sizeof (cmd) * 2, NULL, 0); 4417efd4c9b6SSteve Lawrence thr_exit(NULL); 4418efd4c9b6SSteve Lawrence } 4419efd4c9b6SSteve Lawrence 4420efd4c9b6SSteve Lawrence /* 4421efd4c9b6SSteve Lawrence * Respond to libzonestat.so clients with the current utlilzation data. 4422efd4c9b6SSteve Lawrence */ 4423efd4c9b6SSteve Lawrence /* ARGSUSED */ 4424efd4c9b6SSteve Lawrence static void 4425efd4c9b6SSteve Lawrence zsd_stat_server(void *cookie, char *argp, size_t arg_size, 4426efd4c9b6SSteve Lawrence door_desc_t *dp, uint_t n_desc) 4427efd4c9b6SSteve Lawrence { 4428efd4c9b6SSteve Lawrence uint64_t *args, cmd; 4429efd4c9b6SSteve Lawrence zs_usage_cache_t *cache; 4430efd4c9b6SSteve Lawrence int ret; 4431efd4c9b6SSteve Lawrence char *rvalp; 4432efd4c9b6SSteve Lawrence size_t rvals; 4433efd4c9b6SSteve Lawrence zs_usage_t *usage; 4434efd4c9b6SSteve Lawrence ucred_t *ucred; 4435efd4c9b6SSteve Lawrence zoneid_t zoneid; 4436efd4c9b6SSteve Lawrence const priv_set_t *eset; 4437efd4c9b6SSteve Lawrence boolean_t is_gz = B_FALSE; 4438efd4c9b6SSteve Lawrence 4439efd4c9b6SSteve Lawrence /* Tell stat thread there are no more clients */ 4440efd4c9b6SSteve Lawrence if (argp == DOOR_UNREF_DATA) { 4441efd4c9b6SSteve Lawrence (void) mutex_lock(&g_usage_cache_lock); 4442efd4c9b6SSteve Lawrence g_hasclient = B_FALSE; 4443efd4c9b6SSteve Lawrence (void) cond_signal(&g_usage_cache_kick); 4444efd4c9b6SSteve Lawrence (void) mutex_unlock(&g_usage_cache_lock); 4445efd4c9b6SSteve Lawrence (void) door_return(NULL, 0, NULL, 0); 4446efd4c9b6SSteve Lawrence thr_exit(NULL); 4447efd4c9b6SSteve Lawrence } 4448efd4c9b6SSteve Lawrence if (arg_size != sizeof (cmd) * 2) { 4449efd4c9b6SSteve Lawrence (void) door_return(NULL, 0, NULL, 0); 4450efd4c9b6SSteve Lawrence thr_exit(NULL); 4451efd4c9b6SSteve Lawrence } 4452efd4c9b6SSteve Lawrence /* LINTED */ 4453efd4c9b6SSteve Lawrence args = (uint64_t *)argp; 4454efd4c9b6SSteve Lawrence cmd = args[0]; 4455efd4c9b6SSteve Lawrence if (cmd != ZSD_CMD_READ) { 4456efd4c9b6SSteve Lawrence (void) door_return(NULL, 0, NULL, 0); 4457efd4c9b6SSteve Lawrence thr_exit(NULL); 4458efd4c9b6SSteve Lawrence } 4459efd4c9b6SSteve Lawrence ucred = alloca(ucred_size()); 4460efd4c9b6SSteve Lawrence if (door_ucred(&ucred) != 0) { 4461efd4c9b6SSteve Lawrence (void) door_return(NULL, 0, NULL, 0); 4462efd4c9b6SSteve Lawrence thr_exit(NULL); 4463efd4c9b6SSteve Lawrence } 4464efd4c9b6SSteve Lawrence zoneid = ucred_getzoneid(ucred); 4465efd4c9b6SSteve Lawrence 4466efd4c9b6SSteve Lawrence if (zoneid == GLOBAL_ZONEID) 4467efd4c9b6SSteve Lawrence is_gz = B_TRUE; 4468efd4c9b6SSteve Lawrence 4469efd4c9b6SSteve Lawrence eset = ucred_getprivset(ucred, PRIV_EFFECTIVE); 4470efd4c9b6SSteve Lawrence if (eset == NULL) { 4471efd4c9b6SSteve Lawrence (void) door_return(NULL, 0, NULL, 0); 4472efd4c9b6SSteve Lawrence thr_exit(NULL); 4473efd4c9b6SSteve Lawrence } 4474efd4c9b6SSteve Lawrence if (!priv_ismember(eset, PRIV_PROC_INFO)) { 4475efd4c9b6SSteve Lawrence (void) door_return(NULL, 0, NULL, 0); 4476efd4c9b6SSteve Lawrence thr_exit(NULL); 4477efd4c9b6SSteve Lawrence } 4478efd4c9b6SSteve Lawrence (void) mutex_lock(&g_usage_cache_lock); 4479efd4c9b6SSteve Lawrence g_hasclient = B_TRUE; 4480efd4c9b6SSteve Lawrence 4481efd4c9b6SSteve Lawrence /* 4482efd4c9b6SSteve Lawrence * Force a new cpu calculation for client. This will force a 4483efd4c9b6SSteve Lawrence * new memory calculation if the memory data is older than the 4484efd4c9b6SSteve Lawrence * sample period. 4485efd4c9b6SSteve Lawrence */ 4486efd4c9b6SSteve Lawrence g_usage_cache_kickers++; 4487efd4c9b6SSteve Lawrence (void) cond_signal(&g_usage_cache_kick); 4488efd4c9b6SSteve Lawrence ret = cond_wait(&g_usage_cache_wait, &g_usage_cache_lock); 4489efd4c9b6SSteve Lawrence g_usage_cache_kickers--; 4490efd4c9b6SSteve Lawrence if (ret != 0 && errno == EINTR) { 4491efd4c9b6SSteve Lawrence (void) mutex_unlock(&g_usage_cache_lock); 4492efd4c9b6SSteve Lawrence zsd_warn(gettext( 4493efd4c9b6SSteve Lawrence "Interrupted before writing usage size to client\n")); 4494efd4c9b6SSteve Lawrence (void) door_return(NULL, 0, NULL, 0); 4495efd4c9b6SSteve Lawrence thr_exit(NULL); 4496efd4c9b6SSteve Lawrence } 4497efd4c9b6SSteve Lawrence cache = zsd_usage_cache_hold_locked(); 4498efd4c9b6SSteve Lawrence if (cache == NULL) { 4499efd4c9b6SSteve Lawrence zsd_warn(gettext("Usage cache empty.\n")); 4500efd4c9b6SSteve Lawrence (void) door_return(NULL, 0, NULL, 0); 4501efd4c9b6SSteve Lawrence thr_exit(NULL); 4502efd4c9b6SSteve Lawrence } 4503efd4c9b6SSteve Lawrence (void) mutex_unlock(&g_usage_cache_lock); 4504efd4c9b6SSteve Lawrence 4505efd4c9b6SSteve Lawrence /* Copy current usage data to stack to send to client */ 4506efd4c9b6SSteve Lawrence usage = (zs_usage_t *)alloca(cache->zsuc_size); 4507efd4c9b6SSteve Lawrence 4508efd4c9b6SSteve Lawrence /* Filter out results if caller is non-global zone */ 4509efd4c9b6SSteve Lawrence zsd_usage_filter(zoneid, cache, usage, is_gz); 4510efd4c9b6SSteve Lawrence 4511efd4c9b6SSteve Lawrence rvalp = (void *)usage; 4512efd4c9b6SSteve Lawrence rvals = usage->zsu_size; 4513efd4c9b6SSteve Lawrence zsd_usage_cache_rele(cache); 4514efd4c9b6SSteve Lawrence 45151e88dc67SToomas Soome (void) door_return(rvalp, rvals, NULL, 0); 4516efd4c9b6SSteve Lawrence thr_exit(NULL); 4517efd4c9b6SSteve Lawrence } 4518efd4c9b6SSteve Lawrence 4519efd4c9b6SSteve Lawrence static volatile boolean_t g_quit; 4520efd4c9b6SSteve Lawrence 4521efd4c9b6SSteve Lawrence /* ARGSUSED */ 4522efd4c9b6SSteve Lawrence static void 4523efd4c9b6SSteve Lawrence zonestat_quithandler(int sig) 4524efd4c9b6SSteve Lawrence { 4525efd4c9b6SSteve Lawrence g_quit = B_TRUE; 4526efd4c9b6SSteve Lawrence } 4527efd4c9b6SSteve Lawrence 4528efd4c9b6SSteve Lawrence /* 4529efd4c9b6SSteve Lawrence * The stat thread generates new utilization data when clients request 4530efd4c9b6SSteve Lawrence * it. It also manages opening and closing the subsystems used to gather 4531efd4c9b6SSteve Lawrence * data depending on if clients exist. 4532efd4c9b6SSteve Lawrence */ 4533efd4c9b6SSteve Lawrence /* ARGSUSED */ 4534efd4c9b6SSteve Lawrence void * 4535efd4c9b6SSteve Lawrence stat_thread(void *arg) 4536efd4c9b6SSteve Lawrence { 4537efd4c9b6SSteve Lawrence time_t start; 4538efd4c9b6SSteve Lawrence time_t now; 4539efd4c9b6SSteve Lawrence time_t next_memory; 4540efd4c9b6SSteve Lawrence boolean_t do_memory; 4541efd4c9b6SSteve Lawrence boolean_t do_read; 4542efd4c9b6SSteve Lawrence boolean_t do_close; 4543efd4c9b6SSteve Lawrence 4544efd4c9b6SSteve Lawrence start = time(NULL); 4545efd4c9b6SSteve Lawrence if (start < 0) { 4546efd4c9b6SSteve Lawrence if (g_quit == B_TRUE) 4547efd4c9b6SSteve Lawrence goto quit; 4548efd4c9b6SSteve Lawrence zsd_warn(gettext("Unable to fetch current time")); 4549efd4c9b6SSteve Lawrence g_quit = B_TRUE; 4550efd4c9b6SSteve Lawrence goto quit; 4551efd4c9b6SSteve Lawrence } 4552efd4c9b6SSteve Lawrence 4553efd4c9b6SSteve Lawrence next_memory = start; 4554efd4c9b6SSteve Lawrence while (g_quit == B_FALSE) { 4555efd4c9b6SSteve Lawrence for (;;) { 4556efd4c9b6SSteve Lawrence /* 4557efd4c9b6SSteve Lawrence * These are used to decide if the most recent memory 4558efd4c9b6SSteve Lawrence * calculation was within a sample interval, 4559efd4c9b6SSteve Lawrence * and weather or not the usage collection needs to 4560efd4c9b6SSteve Lawrence * be opened or closed. 4561efd4c9b6SSteve Lawrence */ 4562efd4c9b6SSteve Lawrence do_memory = B_FALSE; 4563efd4c9b6SSteve Lawrence do_read = B_FALSE; 4564efd4c9b6SSteve Lawrence do_close = B_FALSE; 4565efd4c9b6SSteve Lawrence 4566efd4c9b6SSteve Lawrence /* 4567efd4c9b6SSteve Lawrence * If all clients have gone, close usage collecting 4568efd4c9b6SSteve Lawrence */ 4569efd4c9b6SSteve Lawrence (void) mutex_lock(&g_usage_cache_lock); 4570efd4c9b6SSteve Lawrence if (!g_hasclient && g_open == B_TRUE) { 4571efd4c9b6SSteve Lawrence do_close = B_TRUE; 4572efd4c9b6SSteve Lawrence (void) mutex_unlock(&g_usage_cache_lock); 4573efd4c9b6SSteve Lawrence break; 4574efd4c9b6SSteve Lawrence } 4575efd4c9b6SSteve Lawrence if (g_quit == B_TRUE) { 4576efd4c9b6SSteve Lawrence (void) mutex_unlock( 4577efd4c9b6SSteve Lawrence &g_usage_cache_lock); 4578efd4c9b6SSteve Lawrence break; 4579efd4c9b6SSteve Lawrence } 4580efd4c9b6SSteve Lawrence /* 4581efd4c9b6SSteve Lawrence * Wait for a usage data request 4582efd4c9b6SSteve Lawrence */ 4583efd4c9b6SSteve Lawrence if (g_usage_cache_kickers == 0) { 4584efd4c9b6SSteve Lawrence (void) cond_wait(&g_usage_cache_kick, 4585efd4c9b6SSteve Lawrence &g_usage_cache_lock); 4586efd4c9b6SSteve Lawrence } 4587efd4c9b6SSteve Lawrence now = time(NULL); 4588efd4c9b6SSteve Lawrence if (now < 0) { 4589efd4c9b6SSteve Lawrence if (g_quit == B_TRUE) { 4590efd4c9b6SSteve Lawrence (void) mutex_unlock( 4591efd4c9b6SSteve Lawrence &g_usage_cache_lock); 4592efd4c9b6SSteve Lawrence goto quit; 4593efd4c9b6SSteve Lawrence } 4594efd4c9b6SSteve Lawrence g_quit = B_TRUE; 4595efd4c9b6SSteve Lawrence (void) mutex_unlock(&g_usage_cache_lock); 4596efd4c9b6SSteve Lawrence zsd_warn(gettext( 4597efd4c9b6SSteve Lawrence "Unable to fetch current time")); 4598efd4c9b6SSteve Lawrence goto quit; 4599efd4c9b6SSteve Lawrence } 4600efd4c9b6SSteve Lawrence if (g_hasclient) { 4601efd4c9b6SSteve Lawrence do_read = B_TRUE; 4602efd4c9b6SSteve Lawrence if (now >= next_memory) { 4603efd4c9b6SSteve Lawrence do_memory = B_TRUE; 4604efd4c9b6SSteve Lawrence next_memory = now + g_interval; 4605efd4c9b6SSteve Lawrence } 4606efd4c9b6SSteve Lawrence } else { 4607efd4c9b6SSteve Lawrence do_close = B_TRUE; 4608efd4c9b6SSteve Lawrence } 4609efd4c9b6SSteve Lawrence (void) mutex_unlock(&g_usage_cache_lock); 4610efd4c9b6SSteve Lawrence if (do_read || do_close) 4611efd4c9b6SSteve Lawrence break; 4612efd4c9b6SSteve Lawrence } 4613efd4c9b6SSteve Lawrence g_now = now; 4614efd4c9b6SSteve Lawrence g_hrnow = gethrtime(); 4615efd4c9b6SSteve Lawrence if (g_hasclient && g_open == B_FALSE) { 4616efd4c9b6SSteve Lawrence g_start = g_now; 4617efd4c9b6SSteve Lawrence g_hrstart = g_hrnow; 4618efd4c9b6SSteve Lawrence g_ctl = zsd_open(g_ctl); 4619efd4c9b6SSteve Lawrence if (g_ctl == NULL) 4620efd4c9b6SSteve Lawrence zsd_warn(gettext( 4621efd4c9b6SSteve Lawrence "Unable to open zone statistics")); 4622efd4c9b6SSteve Lawrence else 4623efd4c9b6SSteve Lawrence g_open = B_TRUE; 4624efd4c9b6SSteve Lawrence } 4625efd4c9b6SSteve Lawrence if (do_read && g_ctl) { 4626efd4c9b6SSteve Lawrence if (zsd_read(g_ctl, B_FALSE, do_memory) != 0) { 4627efd4c9b6SSteve Lawrence zsd_warn(gettext( 4628efd4c9b6SSteve Lawrence "Unable to read zone statistics")); 4629efd4c9b6SSteve Lawrence g_quit = B_TRUE; 4630efd4c9b6SSteve Lawrence return (NULL); 4631efd4c9b6SSteve Lawrence } 4632efd4c9b6SSteve Lawrence } 4633efd4c9b6SSteve Lawrence (void) mutex_lock(&g_usage_cache_lock); 4634efd4c9b6SSteve Lawrence if (!g_hasclient && g_open == B_TRUE && g_ctl) { 4635efd4c9b6SSteve Lawrence (void) mutex_unlock(&g_usage_cache_lock); 4636efd4c9b6SSteve Lawrence zsd_close(g_ctl); 4637efd4c9b6SSteve Lawrence g_open = B_FALSE; 4638efd4c9b6SSteve Lawrence } else { 4639efd4c9b6SSteve Lawrence (void) mutex_unlock(&g_usage_cache_lock); 4640efd4c9b6SSteve Lawrence } 4641efd4c9b6SSteve Lawrence } 4642efd4c9b6SSteve Lawrence quit: 4643efd4c9b6SSteve Lawrence if (g_open) 4644efd4c9b6SSteve Lawrence zsd_close(g_ctl); 4645efd4c9b6SSteve Lawrence 4646efd4c9b6SSteve Lawrence (void) thr_kill(g_main, SIGINT); 4647efd4c9b6SSteve Lawrence thr_exit(NULL); 4648efd4c9b6SSteve Lawrence return (NULL); 4649efd4c9b6SSteve Lawrence } 4650efd4c9b6SSteve Lawrence 4651efd4c9b6SSteve Lawrence void 4652efd4c9b6SSteve Lawrence zsd_set_fx() 4653efd4c9b6SSteve Lawrence { 4654efd4c9b6SSteve Lawrence pcinfo_t pcinfo; 4655efd4c9b6SSteve Lawrence pcparms_t pcparms; 4656efd4c9b6SSteve Lawrence 4657efd4c9b6SSteve Lawrence (void) strlcpy(pcinfo.pc_clname, "FX", sizeof (pcinfo.pc_clname)); 4658efd4c9b6SSteve Lawrence if (priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo) == -1) { 4659efd4c9b6SSteve Lawrence zsd_warn(gettext("cannot get FX class parameters")); 4660efd4c9b6SSteve Lawrence return; 4661efd4c9b6SSteve Lawrence } 4662efd4c9b6SSteve Lawrence pcparms.pc_cid = pcinfo.pc_cid; 4663efd4c9b6SSteve Lawrence ((fxparms_t *)pcparms.pc_clparms)->fx_upri = 60; 4664efd4c9b6SSteve Lawrence ((fxparms_t *)pcparms.pc_clparms)->fx_uprilim = 60; 4665efd4c9b6SSteve Lawrence ((fxparms_t *)pcparms.pc_clparms)->fx_tqsecs = 0; 4666efd4c9b6SSteve Lawrence ((fxparms_t *)pcparms.pc_clparms)->fx_tqnsecs = FX_NOCHANGE; 4667efd4c9b6SSteve Lawrence if (priocntl(P_PID, getpid(), PC_SETPARMS, (caddr_t)&pcparms) == -1) 4668efd4c9b6SSteve Lawrence zsd_warn(gettext("cannot enter the FX class")); 4669efd4c9b6SSteve Lawrence } 4670efd4c9b6SSteve Lawrence 4671efd4c9b6SSteve Lawrence static int pipe_fd; 4672efd4c9b6SSteve Lawrence 4673efd4c9b6SSteve Lawrence static void 4674efd4c9b6SSteve Lawrence daemonize_ready(char status) 4675efd4c9b6SSteve Lawrence { 4676efd4c9b6SSteve Lawrence /* 4677efd4c9b6SSteve Lawrence * wake the parent with a clue 4678efd4c9b6SSteve Lawrence */ 4679efd4c9b6SSteve Lawrence (void) write(pipe_fd, &status, 1); 4680efd4c9b6SSteve Lawrence (void) close(pipe_fd); 4681efd4c9b6SSteve Lawrence } 4682efd4c9b6SSteve Lawrence 4683efd4c9b6SSteve Lawrence static int 4684efd4c9b6SSteve Lawrence daemonize_start(void) 4685efd4c9b6SSteve Lawrence { 4686efd4c9b6SSteve Lawrence char data; 4687efd4c9b6SSteve Lawrence int status; 4688efd4c9b6SSteve Lawrence 4689efd4c9b6SSteve Lawrence int filedes[2]; 4690efd4c9b6SSteve Lawrence pid_t pid; 4691efd4c9b6SSteve Lawrence 4692efd4c9b6SSteve Lawrence (void) close(0); 4693efd4c9b6SSteve Lawrence (void) dup2(2, 1); 4694efd4c9b6SSteve Lawrence 4695efd4c9b6SSteve Lawrence if (pipe(filedes) < 0) 4696efd4c9b6SSteve Lawrence return (-1); 4697efd4c9b6SSteve Lawrence 4698efd4c9b6SSteve Lawrence (void) fflush(NULL); 4699efd4c9b6SSteve Lawrence 4700efd4c9b6SSteve Lawrence if ((pid = fork1()) < 0) 4701efd4c9b6SSteve Lawrence return (-1); 4702efd4c9b6SSteve Lawrence 4703efd4c9b6SSteve Lawrence if (pid != 0) { 4704efd4c9b6SSteve Lawrence /* 4705efd4c9b6SSteve Lawrence * parent 4706efd4c9b6SSteve Lawrence */ 4707efd4c9b6SSteve Lawrence struct sigaction act; 4708efd4c9b6SSteve Lawrence 4709efd4c9b6SSteve Lawrence act.sa_sigaction = SIG_DFL; 4710efd4c9b6SSteve Lawrence (void) sigemptyset(&act.sa_mask); 4711efd4c9b6SSteve Lawrence act.sa_flags = 0; 4712efd4c9b6SSteve Lawrence 4713efd4c9b6SSteve Lawrence (void) sigaction(SIGPIPE, &act, NULL); /* ignore SIGPIPE */ 4714efd4c9b6SSteve Lawrence 4715efd4c9b6SSteve Lawrence (void) close(filedes[1]); 4716efd4c9b6SSteve Lawrence if (read(filedes[0], &data, 1) == 1) { 4717efd4c9b6SSteve Lawrence /* forward ready code via exit status */ 4718efd4c9b6SSteve Lawrence exit(data); 4719efd4c9b6SSteve Lawrence } 4720efd4c9b6SSteve Lawrence status = -1; 4721efd4c9b6SSteve Lawrence (void) wait4(pid, &status, 0, NULL); 4722efd4c9b6SSteve Lawrence /* daemon process exited before becoming ready */ 4723efd4c9b6SSteve Lawrence if (WIFEXITED(status)) { 4724efd4c9b6SSteve Lawrence /* assume daemon process printed useful message */ 4725efd4c9b6SSteve Lawrence exit(WEXITSTATUS(status)); 4726efd4c9b6SSteve Lawrence } else { 4727efd4c9b6SSteve Lawrence zsd_warn(gettext("daemon process killed or died")); 4728efd4c9b6SSteve Lawrence exit(1); 4729efd4c9b6SSteve Lawrence } 4730efd4c9b6SSteve Lawrence } 4731efd4c9b6SSteve Lawrence 4732efd4c9b6SSteve Lawrence /* 4733efd4c9b6SSteve Lawrence * child 4734efd4c9b6SSteve Lawrence */ 4735efd4c9b6SSteve Lawrence pipe_fd = filedes[1]; 4736efd4c9b6SSteve Lawrence (void) close(filedes[0]); 4737efd4c9b6SSteve Lawrence 4738efd4c9b6SSteve Lawrence /* 4739efd4c9b6SSteve Lawrence * generic Unix setup 4740efd4c9b6SSteve Lawrence */ 4741efd4c9b6SSteve Lawrence (void) setsid(); 4742efd4c9b6SSteve Lawrence (void) umask(0000); 4743efd4c9b6SSteve Lawrence 4744efd4c9b6SSteve Lawrence return (0); 4745efd4c9b6SSteve Lawrence } 4746efd4c9b6SSteve Lawrence 4747efd4c9b6SSteve Lawrence static void 4748efd4c9b6SSteve Lawrence fattach_all_zones(boolean_t detach_only) 4749efd4c9b6SSteve Lawrence { 4750efd4c9b6SSteve Lawrence zoneid_t *zids; 4751efd4c9b6SSteve Lawrence uint_t nzids, nzids_last; 4752efd4c9b6SSteve Lawrence int i; 4753efd4c9b6SSteve Lawrence 4754efd4c9b6SSteve Lawrence again: 4755efd4c9b6SSteve Lawrence (void) zone_list(NULL, &nzids); 4756efd4c9b6SSteve Lawrence nzids_last = nzids; 4757efd4c9b6SSteve Lawrence zids = (zoneid_t *)malloc(sizeof (zoneid_t) * nzids_last); 4758efd4c9b6SSteve Lawrence if (zids == NULL) 4759efd4c9b6SSteve Lawrence zsd_error(gettext("Out of memory")); 4760efd4c9b6SSteve Lawrence 4761efd4c9b6SSteve Lawrence (void) zone_list(zids, &nzids); 4762efd4c9b6SSteve Lawrence if (nzids > nzids_last) { 4763efd4c9b6SSteve Lawrence free(zids); 4764efd4c9b6SSteve Lawrence goto again; 4765efd4c9b6SSteve Lawrence } 4766efd4c9b6SSteve Lawrence for (i = 0; i < nzids; i++) 4767efd4c9b6SSteve Lawrence zsd_fattach_zone(zids[i], g_server_door, detach_only); 4768efd4c9b6SSteve Lawrence 4769efd4c9b6SSteve Lawrence free(zids); 4770efd4c9b6SSteve Lawrence } 4771efd4c9b6SSteve Lawrence 4772efd4c9b6SSteve Lawrence int 4773efd4c9b6SSteve Lawrence main(int argc, char *argv[]) 4774efd4c9b6SSteve Lawrence { 4775efd4c9b6SSteve Lawrence 4776efd4c9b6SSteve Lawrence int arg; 4777efd4c9b6SSteve Lawrence thread_t tid; 4778efd4c9b6SSteve Lawrence scf_simple_prop_t *prop; 4779efd4c9b6SSteve Lawrence uint64_t *intervalp; 4780efd4c9b6SSteve Lawrence boolean_t opt_cleanup = B_FALSE; 4781efd4c9b6SSteve Lawrence 4782efd4c9b6SSteve Lawrence g_main = thr_self(); 4783efd4c9b6SSteve Lawrence g_quit = B_FALSE; 4784efd4c9b6SSteve Lawrence (void) signal(SIGINT, zonestat_quithandler); 4785efd4c9b6SSteve Lawrence (void) signal(SIGTERM, zonestat_quithandler); 4786efd4c9b6SSteve Lawrence (void) signal(SIGHUP, zonestat_quithandler); 4787efd4c9b6SSteve Lawrence /* (void) sigignore(SIGCHLD); */ 4788efd4c9b6SSteve Lawrence (void) sigignore(SIGPIPE); 4789efd4c9b6SSteve Lawrence 4790efd4c9b6SSteve Lawrence if (getzoneid() != GLOBAL_ZONEID) 4791efd4c9b6SSteve Lawrence zsd_error(gettext("Must be run from global zone only")); 4792efd4c9b6SSteve Lawrence 4793efd4c9b6SSteve Lawrence while ((arg = getopt(argc, argv, "c")) 4794efd4c9b6SSteve Lawrence != EOF) { 4795efd4c9b6SSteve Lawrence switch (arg) { 4796efd4c9b6SSteve Lawrence case 'c': 4797efd4c9b6SSteve Lawrence opt_cleanup = B_TRUE; 4798efd4c9b6SSteve Lawrence break; 4799efd4c9b6SSteve Lawrence default: 4800efd4c9b6SSteve Lawrence zsd_error(gettext("Invalid option")); 4801efd4c9b6SSteve Lawrence } 4802efd4c9b6SSteve Lawrence } 4803efd4c9b6SSteve Lawrence 4804efd4c9b6SSteve Lawrence if (opt_cleanup) { 4805efd4c9b6SSteve Lawrence if (zsd_disable_cpu_stats() != 0) 4806efd4c9b6SSteve Lawrence exit(1); 4807efd4c9b6SSteve Lawrence else 4808efd4c9b6SSteve Lawrence exit(0); 4809efd4c9b6SSteve Lawrence } 4810efd4c9b6SSteve Lawrence 4811efd4c9b6SSteve Lawrence /* Get the configured sample interval */ 4812efd4c9b6SSteve Lawrence prop = scf_simple_prop_get(NULL, "svc:/system/zones-monitoring:default", 4813efd4c9b6SSteve Lawrence "config", "sample_interval"); 4814efd4c9b6SSteve Lawrence if (prop == NULL) 4815efd4c9b6SSteve Lawrence zsd_error(gettext("Unable to fetch SMF property " 4816efd4c9b6SSteve Lawrence "\"config/sample_interval\"")); 4817efd4c9b6SSteve Lawrence 4818efd4c9b6SSteve Lawrence if (scf_simple_prop_type(prop) != SCF_TYPE_COUNT) 4819efd4c9b6SSteve Lawrence zsd_error(gettext("Malformed SMF property " 4820efd4c9b6SSteve Lawrence "\"config/sample_interval\". Must be of type \"count\"")); 4821efd4c9b6SSteve Lawrence 4822efd4c9b6SSteve Lawrence intervalp = scf_simple_prop_next_count(prop); 4823efd4c9b6SSteve Lawrence g_interval = *intervalp; 4824efd4c9b6SSteve Lawrence if (g_interval == 0) 4825efd4c9b6SSteve Lawrence zsd_error(gettext("Malformed SMF property " 4826efd4c9b6SSteve Lawrence "\"config/sample_interval\". Must be greater than zero")); 4827efd4c9b6SSteve Lawrence 4828efd4c9b6SSteve Lawrence scf_simple_prop_free(prop); 4829efd4c9b6SSteve Lawrence 4830efd4c9b6SSteve Lawrence if (daemonize_start() < 0) 4831efd4c9b6SSteve Lawrence zsd_error(gettext("Unable to start daemon\n")); 4832efd4c9b6SSteve Lawrence 4833efd4c9b6SSteve Lawrence /* Run at high priority */ 4834efd4c9b6SSteve Lawrence zsd_set_fx(); 4835efd4c9b6SSteve Lawrence 4836efd4c9b6SSteve Lawrence (void) mutex_init(&g_usage_cache_lock, USYNC_THREAD, NULL); 4837efd4c9b6SSteve Lawrence (void) cond_init(&g_usage_cache_kick, USYNC_THREAD, NULL); 4838efd4c9b6SSteve Lawrence (void) cond_init(&g_usage_cache_wait, USYNC_THREAD, NULL); 4839efd4c9b6SSteve Lawrence 4840efd4c9b6SSteve Lawrence g_server_door = door_create(zsd_server, NULL, 4841efd4c9b6SSteve Lawrence DOOR_REFUSE_DESC | DOOR_NO_CANCEL); 4842efd4c9b6SSteve Lawrence if (g_server_door < 0) 4843efd4c9b6SSteve Lawrence zsd_error(gettext("Unable to create server door\n")); 4844efd4c9b6SSteve Lawrence 4845efd4c9b6SSteve Lawrence 4846efd4c9b6SSteve Lawrence g_stat_door = door_create(zsd_stat_server, NULL, DOOR_UNREF_MULTI | 4847efd4c9b6SSteve Lawrence DOOR_REFUSE_DESC | DOOR_NO_CANCEL); 4848efd4c9b6SSteve Lawrence if (g_stat_door < 0) 4849efd4c9b6SSteve Lawrence zsd_error(gettext("Unable to create statistics door\n")); 4850efd4c9b6SSteve Lawrence 4851efd4c9b6SSteve Lawrence fattach_all_zones(B_FALSE); 4852efd4c9b6SSteve Lawrence 4853efd4c9b6SSteve Lawrence if (thr_create(NULL, 0, stat_thread, NULL, 0, &tid) != 0) 4854efd4c9b6SSteve Lawrence zsd_error(gettext("Unable to create statistics thread\n")); 4855efd4c9b6SSteve Lawrence 4856efd4c9b6SSteve Lawrence daemonize_ready(0); 4857efd4c9b6SSteve Lawrence 4858efd4c9b6SSteve Lawrence /* Wait for signal to quit */ 4859efd4c9b6SSteve Lawrence while (g_quit == B_FALSE) 4860efd4c9b6SSteve Lawrence (void) pause(); 4861efd4c9b6SSteve Lawrence 4862efd4c9b6SSteve Lawrence /* detach doors */ 4863efd4c9b6SSteve Lawrence fattach_all_zones(B_TRUE); 4864efd4c9b6SSteve Lawrence 4865efd4c9b6SSteve Lawrence (void) door_revoke(g_server_door); 4866efd4c9b6SSteve Lawrence (void) door_revoke(g_stat_door); 4867efd4c9b6SSteve Lawrence 4868efd4c9b6SSteve Lawrence /* kick stat thread and wait for it to close the statistics */ 4869efd4c9b6SSteve Lawrence (void) mutex_lock(&g_usage_cache_lock); 4870efd4c9b6SSteve Lawrence g_quit = B_TRUE; 4871efd4c9b6SSteve Lawrence (void) cond_signal(&g_usage_cache_kick); 4872efd4c9b6SSteve Lawrence (void) mutex_unlock(&g_usage_cache_lock); 4873efd4c9b6SSteve Lawrence end: 4874efd4c9b6SSteve Lawrence (void) thr_join(tid, NULL, NULL); 4875efd4c9b6SSteve Lawrence return (0); 4876efd4c9b6SSteve Lawrence } 4877