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