17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 522942fabSgm149974 * Common Development and Distribution License (the "License"). 622942fabSgm149974 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21*d4204c85Sraf 227c478bd9Sstevel@tonic-gate /* 23*d4204c85Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <sys/pool.h> 307c478bd9Sstevel@tonic-gate #include <sys/pool_impl.h> 317c478bd9Sstevel@tonic-gate #include <sys/pool_pset.h> 327c478bd9Sstevel@tonic-gate #include <sys/id_space.h> 337c478bd9Sstevel@tonic-gate #include <sys/mutex.h> 347c478bd9Sstevel@tonic-gate #include <sys/nvpair.h> 357c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 367c478bd9Sstevel@tonic-gate #include <sys/errno.h> 377c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 387c478bd9Sstevel@tonic-gate #include <sys/systm.h> 397c478bd9Sstevel@tonic-gate #include <sys/proc.h> 407c478bd9Sstevel@tonic-gate #include <sys/fss.h> 417c478bd9Sstevel@tonic-gate #include <sys/class.h> 427c478bd9Sstevel@tonic-gate #include <sys/exacct.h> 437c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 447c478bd9Sstevel@tonic-gate #include <sys/procset.h> 457c478bd9Sstevel@tonic-gate #include <sys/atomic.h> 467c478bd9Sstevel@tonic-gate #include <sys/zone.h> 477c478bd9Sstevel@tonic-gate #include <sys/policy.h> 48*d4204c85Sraf #include <sys/schedctl.h> 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate /* 517c478bd9Sstevel@tonic-gate * RESOURCE POOLS 527c478bd9Sstevel@tonic-gate * 537c478bd9Sstevel@tonic-gate * The resource pools facility brings together process-bindable resource into 547c478bd9Sstevel@tonic-gate * a common abstraction called a pool. Processor sets and other entities can 557c478bd9Sstevel@tonic-gate * be configured, grouped, and labelled such that workload components can be 567c478bd9Sstevel@tonic-gate * associated with a subset of a system's total resources. 577c478bd9Sstevel@tonic-gate * 587c478bd9Sstevel@tonic-gate * When disabled, the pools facility is "invisible". All processes belong 597c478bd9Sstevel@tonic-gate * to the same pool (pool_default), and processor sets can be managed through 607c478bd9Sstevel@tonic-gate * the old pset() system call. When enabled, processor sets can only be 617c478bd9Sstevel@tonic-gate * managed via the pools facility. New pools can be created and associated 627c478bd9Sstevel@tonic-gate * with processor sets. Processes can be bound to pools which have non-empty 637c478bd9Sstevel@tonic-gate * resource sets. 647c478bd9Sstevel@tonic-gate * 657c478bd9Sstevel@tonic-gate * Locking: pool_lock() protects global pools state and must be called 667c478bd9Sstevel@tonic-gate * before modifying the configuration, or when taking a snapshot of the 677c478bd9Sstevel@tonic-gate * configuration. If pool_lock_intr() is used, the operation may be 687c478bd9Sstevel@tonic-gate * interrupted by a signal or a request. 697c478bd9Sstevel@tonic-gate * 707c478bd9Sstevel@tonic-gate * To prevent processes from being rebound between pools while they are 717c478bd9Sstevel@tonic-gate * the middle of an operation which affects resource set bindings, such 727c478bd9Sstevel@tonic-gate * operations must be surrounded by calls to pool_barrier_enter() and 737c478bd9Sstevel@tonic-gate * pool_barrier_exit(). This mechanism guarantees that such processes will 747c478bd9Sstevel@tonic-gate * be stopped either at the beginning or at the end of the barrier so that 757c478bd9Sstevel@tonic-gate * the rebind operation can atomically bind the process and its threads 767c478bd9Sstevel@tonic-gate * to new resource sets, and then let process run again. 777c478bd9Sstevel@tonic-gate * 787c478bd9Sstevel@tonic-gate * Lock ordering with respect to other locks is as follows: 797c478bd9Sstevel@tonic-gate * 807c478bd9Sstevel@tonic-gate * pool_lock() -> cpu_lock -> pidlock -> p_lock -> pool_barrier_lock 817c478bd9Sstevel@tonic-gate * 827c478bd9Sstevel@tonic-gate * Most static and global variables defined in this file are protected 837c478bd9Sstevel@tonic-gate * by calling pool_lock(). 847c478bd9Sstevel@tonic-gate * 857c478bd9Sstevel@tonic-gate * The operation that binds tasks and projects to pools is atomic. That is, 867c478bd9Sstevel@tonic-gate * either all processes in a given task or a project will be bound to a 877c478bd9Sstevel@tonic-gate * new pool, or (in case of an error) they will be all left bound to the 887c478bd9Sstevel@tonic-gate * old pool. Processes in a given task or a given project can only be bound to 897c478bd9Sstevel@tonic-gate * different pools if they were rebound individually one by one as single 907c478bd9Sstevel@tonic-gate * processes. Threads or LWPs of the same process do not have pool bindings, 917c478bd9Sstevel@tonic-gate * and are bound to the same resource sets associated with the resource pool 927c478bd9Sstevel@tonic-gate * of that process. 937c478bd9Sstevel@tonic-gate * 947c478bd9Sstevel@tonic-gate * The following picture shows one possible pool configuration with three 957c478bd9Sstevel@tonic-gate * pools and three processor sets. Note that processor set "foo" is not 967c478bd9Sstevel@tonic-gate * associated with any pools and therefore cannot have any processes 977c478bd9Sstevel@tonic-gate * bound to it. Two pools (default and foo) are associated with the 987c478bd9Sstevel@tonic-gate * same processor set (default). Also, note that processes in Task 2 997c478bd9Sstevel@tonic-gate * are bound to different pools. 1007c478bd9Sstevel@tonic-gate * 1017c478bd9Sstevel@tonic-gate * 1027c478bd9Sstevel@tonic-gate * Processor Sets 1037c478bd9Sstevel@tonic-gate * +---------+ 1047c478bd9Sstevel@tonic-gate * +--------------+========================>| default | 1057c478bd9Sstevel@tonic-gate * a| | +---------+ 1067c478bd9Sstevel@tonic-gate * s| | || 1077c478bd9Sstevel@tonic-gate * s| | +---------+ 1087c478bd9Sstevel@tonic-gate * o| | | foo | 1097c478bd9Sstevel@tonic-gate * c| | +---------+ 1107c478bd9Sstevel@tonic-gate * i| | || 1117c478bd9Sstevel@tonic-gate * a| | +---------+ 1127c478bd9Sstevel@tonic-gate * t| | +------>| bar | 1137c478bd9Sstevel@tonic-gate * e| | | +---------+ 1147c478bd9Sstevel@tonic-gate * d| | | 1157c478bd9Sstevel@tonic-gate * | | | 1167c478bd9Sstevel@tonic-gate * +---------+ +---------+ +---------+ 1177c478bd9Sstevel@tonic-gate * Pools | default |======| foo |======| bar | 1187c478bd9Sstevel@tonic-gate * +---------+ +---------+ +---------+ 1197c478bd9Sstevel@tonic-gate * @ @ @ @ @ @ 1207c478bd9Sstevel@tonic-gate * b| | | | | | 1217c478bd9Sstevel@tonic-gate * o| | | | | | 1227c478bd9Sstevel@tonic-gate * u| +-----+ | +-------+ | +---+ 1237c478bd9Sstevel@tonic-gate * n| | | | | | 1247c478bd9Sstevel@tonic-gate * ....d|........|......|......|.........|.......|.... 1257c478bd9Sstevel@tonic-gate * : | :: | | | :: | | : 1267c478bd9Sstevel@tonic-gate * : +---+ :: +---+ +---+ +---+ :: +---+ +---+ : 1277c478bd9Sstevel@tonic-gate * Processes : | p | :: | p | | p | | p | :: | p |...| p | : 1287c478bd9Sstevel@tonic-gate * : +---+ :: +---+ +---+ +---+ :: +---+ +---+ : 1297c478bd9Sstevel@tonic-gate * :........::......................::...............: 1307c478bd9Sstevel@tonic-gate * Task 1 Task 2 Task N 1317c478bd9Sstevel@tonic-gate * | | | 1327c478bd9Sstevel@tonic-gate * | | | 1337c478bd9Sstevel@tonic-gate * | +-----------+ | +-----------+ 1347c478bd9Sstevel@tonic-gate * +--| Project 1 |--+ | Project N | 1357c478bd9Sstevel@tonic-gate * +-----------+ +-----------+ 1367c478bd9Sstevel@tonic-gate * 1377c478bd9Sstevel@tonic-gate * This is just an illustration of relationships between processes, tasks, 1387c478bd9Sstevel@tonic-gate * projects, pools, and processor sets. New types of resource sets will be 1397c478bd9Sstevel@tonic-gate * added in the future. 1407c478bd9Sstevel@tonic-gate */ 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate pool_t *pool_default; /* default pool which always exists */ 1437c478bd9Sstevel@tonic-gate int pool_count; /* number of pools created on this system */ 1447c478bd9Sstevel@tonic-gate int pool_state; /* pools state -- enabled/disabled */ 1457c478bd9Sstevel@tonic-gate void *pool_buf; /* pre-commit snapshot of the pools state */ 1467c478bd9Sstevel@tonic-gate size_t pool_bufsz; /* size of pool_buf */ 1477c478bd9Sstevel@tonic-gate static hrtime_t pool_pool_mod; /* last modification time for pools */ 1487c478bd9Sstevel@tonic-gate static hrtime_t pool_sys_mod; /* last modification time for system */ 1497c478bd9Sstevel@tonic-gate static nvlist_t *pool_sys_prop; /* system properties */ 1507c478bd9Sstevel@tonic-gate static id_space_t *pool_ids; /* pool ID space */ 1517c478bd9Sstevel@tonic-gate static list_t pool_list; /* doubly-linked list of pools */ 1527c478bd9Sstevel@tonic-gate static kmutex_t pool_mutex; /* protects pool_busy_* */ 1537c478bd9Sstevel@tonic-gate static kcondvar_t pool_busy_cv; /* waiting for "pool_lock" */ 1547c478bd9Sstevel@tonic-gate static kthread_t *pool_busy_thread; /* thread holding "pool_lock" */ 1557c478bd9Sstevel@tonic-gate static kmutex_t pool_barrier_lock; /* synch. with pool_barrier_* */ 1567c478bd9Sstevel@tonic-gate static kcondvar_t pool_barrier_cv; /* synch. with pool_barrier_* */ 1577c478bd9Sstevel@tonic-gate static int pool_barrier_count; /* synch. with pool_barrier_* */ 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate /* 1607c478bd9Sstevel@tonic-gate * Boot-time pool initialization. 1617c478bd9Sstevel@tonic-gate */ 1627c478bd9Sstevel@tonic-gate void 1637c478bd9Sstevel@tonic-gate pool_init(void) 1647c478bd9Sstevel@tonic-gate { 1657c478bd9Sstevel@tonic-gate pool_ids = id_space_create("pool_ids", POOL_DEFAULT + 1, POOL_MAXID); 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate /* 1687c478bd9Sstevel@tonic-gate * Initialize default pool. 1697c478bd9Sstevel@tonic-gate */ 1707c478bd9Sstevel@tonic-gate pool_default = kmem_zalloc(sizeof (pool_t), KM_SLEEP); 1717c478bd9Sstevel@tonic-gate pool_default->pool_id = POOL_DEFAULT; 1727c478bd9Sstevel@tonic-gate list_create(&pool_list, sizeof (pool_t), offsetof(pool_t, pool_link)); 1737c478bd9Sstevel@tonic-gate list_insert_head(&pool_list, pool_default); 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate /* 1767c478bd9Sstevel@tonic-gate * Initialize plugins for resource sets. 1777c478bd9Sstevel@tonic-gate */ 1787c478bd9Sstevel@tonic-gate pool_pset_init(); 1797c478bd9Sstevel@tonic-gate pool_count = 1; 1807c478bd9Sstevel@tonic-gate p0.p_pool = pool_default; 1817c478bd9Sstevel@tonic-gate global_zone->zone_pool = pool_default; 1827c478bd9Sstevel@tonic-gate pool_default->pool_ref = 1; 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate /* 1867c478bd9Sstevel@tonic-gate * Synchronization routines. 1877c478bd9Sstevel@tonic-gate * 1887c478bd9Sstevel@tonic-gate * pool_lock is only called from syscall-level routines (processor_bind(), 1897c478bd9Sstevel@tonic-gate * pset_*(), and /dev/pool ioctls). The pool "lock" may be held for long 1907c478bd9Sstevel@tonic-gate * periods of time, including across sleeping operations, so we allow its 1917c478bd9Sstevel@tonic-gate * acquisition to be interruptible. 1927c478bd9Sstevel@tonic-gate * 1937c478bd9Sstevel@tonic-gate * The current thread that owns the "lock" is stored in the variable 1947c478bd9Sstevel@tonic-gate * pool_busy_thread, both to let pool_lock_held() work and to aid debugging. 1957c478bd9Sstevel@tonic-gate */ 1967c478bd9Sstevel@tonic-gate void 1977c478bd9Sstevel@tonic-gate pool_lock(void) 1987c478bd9Sstevel@tonic-gate { 1997c478bd9Sstevel@tonic-gate mutex_enter(&pool_mutex); 200e76e762eSacruz ASSERT(!pool_lock_held()); 2017c478bd9Sstevel@tonic-gate while (pool_busy_thread != NULL) 2027c478bd9Sstevel@tonic-gate cv_wait(&pool_busy_cv, &pool_mutex); 2037c478bd9Sstevel@tonic-gate pool_busy_thread = curthread; 2047c478bd9Sstevel@tonic-gate mutex_exit(&pool_mutex); 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate int 2087c478bd9Sstevel@tonic-gate pool_lock_intr(void) 2097c478bd9Sstevel@tonic-gate { 2107c478bd9Sstevel@tonic-gate mutex_enter(&pool_mutex); 211e76e762eSacruz ASSERT(!pool_lock_held()); 2127c478bd9Sstevel@tonic-gate while (pool_busy_thread != NULL) { 2137c478bd9Sstevel@tonic-gate if (cv_wait_sig(&pool_busy_cv, &pool_mutex) == 0) { 2147c478bd9Sstevel@tonic-gate cv_signal(&pool_busy_cv); 2157c478bd9Sstevel@tonic-gate mutex_exit(&pool_mutex); 2167c478bd9Sstevel@tonic-gate return (1); 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate pool_busy_thread = curthread; 2207c478bd9Sstevel@tonic-gate mutex_exit(&pool_mutex); 2217c478bd9Sstevel@tonic-gate return (0); 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate int 2257c478bd9Sstevel@tonic-gate pool_lock_held(void) 2267c478bd9Sstevel@tonic-gate { 2277c478bd9Sstevel@tonic-gate return (pool_busy_thread == curthread); 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate void 2317c478bd9Sstevel@tonic-gate pool_unlock(void) 2327c478bd9Sstevel@tonic-gate { 2337c478bd9Sstevel@tonic-gate mutex_enter(&pool_mutex); 234e76e762eSacruz ASSERT(pool_lock_held()); 2357c478bd9Sstevel@tonic-gate pool_busy_thread = NULL; 2367c478bd9Sstevel@tonic-gate cv_signal(&pool_busy_cv); 2377c478bd9Sstevel@tonic-gate mutex_exit(&pool_mutex); 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate /* 2417c478bd9Sstevel@tonic-gate * Routines allowing fork(), exec(), exit(), and lwp_create() to synchronize 2427c478bd9Sstevel@tonic-gate * with pool_do_bind(). 2437c478bd9Sstevel@tonic-gate * 2447c478bd9Sstevel@tonic-gate * Calls to pool_barrier_enter() and pool_barrier_exit() must bracket all 2457c478bd9Sstevel@tonic-gate * operations which modify pool or pset associations. They can be called 2467c478bd9Sstevel@tonic-gate * while the process is multi-threaded. In the common case, when current 2477c478bd9Sstevel@tonic-gate * process is not being rebound (PBWAIT flag is not set), these functions 2487c478bd9Sstevel@tonic-gate * will be just incrementing and decrementing reference counts. 2497c478bd9Sstevel@tonic-gate */ 2507c478bd9Sstevel@tonic-gate void 2517c478bd9Sstevel@tonic-gate pool_barrier_enter(void) 2527c478bd9Sstevel@tonic-gate { 2537c478bd9Sstevel@tonic-gate proc_t *p = curproc; 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 2567c478bd9Sstevel@tonic-gate while (p->p_poolflag & PBWAIT) 2577c478bd9Sstevel@tonic-gate cv_wait(&p->p_poolcv, &p->p_lock); 2587c478bd9Sstevel@tonic-gate p->p_poolcnt++; 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate void 2627c478bd9Sstevel@tonic-gate pool_barrier_exit(void) 2637c478bd9Sstevel@tonic-gate { 2647c478bd9Sstevel@tonic-gate proc_t *p = curproc; 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&p->p_lock)); 2677c478bd9Sstevel@tonic-gate ASSERT(p->p_poolcnt > 0); 2687c478bd9Sstevel@tonic-gate p->p_poolcnt--; 2697c478bd9Sstevel@tonic-gate if (p->p_poolflag & PBWAIT) { 2707c478bd9Sstevel@tonic-gate mutex_enter(&pool_barrier_lock); 2717c478bd9Sstevel@tonic-gate ASSERT(pool_barrier_count > 0); 2727c478bd9Sstevel@tonic-gate pool_barrier_count--; 2737c478bd9Sstevel@tonic-gate if (pool_barrier_count == 0) 2747c478bd9Sstevel@tonic-gate cv_signal(&pool_barrier_cv); 2757c478bd9Sstevel@tonic-gate mutex_exit(&pool_barrier_lock); 2767c478bd9Sstevel@tonic-gate while (p->p_poolflag & PBWAIT) 2777c478bd9Sstevel@tonic-gate cv_wait(&p->p_poolcv, &p->p_lock); 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate /* 2827c478bd9Sstevel@tonic-gate * Enable pools facility. 2837c478bd9Sstevel@tonic-gate */ 2847c478bd9Sstevel@tonic-gate static int 2857c478bd9Sstevel@tonic-gate pool_enable(void) 2867c478bd9Sstevel@tonic-gate { 2877c478bd9Sstevel@tonic-gate int ret; 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 2907c478bd9Sstevel@tonic-gate ASSERT(pool_count == 1); 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate ret = pool_pset_enable(); 2937c478bd9Sstevel@tonic-gate if (ret != 0) 2947c478bd9Sstevel@tonic-gate return (ret); 2957c478bd9Sstevel@tonic-gate (void) nvlist_alloc(&pool_sys_prop, NV_UNIQUE_NAME, KM_SLEEP); 2967c478bd9Sstevel@tonic-gate (void) nvlist_add_string(pool_sys_prop, "system.name", 29722942fabSgm149974 "default"); 2987c478bd9Sstevel@tonic-gate (void) nvlist_add_string(pool_sys_prop, "system.comment", ""); 2997c478bd9Sstevel@tonic-gate (void) nvlist_add_int64(pool_sys_prop, "system.version", 1); 3007c478bd9Sstevel@tonic-gate (void) nvlist_add_byte(pool_sys_prop, "system.bind-default", 1); 3010209230bSgjelinek (void) nvlist_add_string(pool_sys_prop, "system.poold.objectives", 3020209230bSgjelinek "wt-load"); 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate (void) nvlist_alloc(&pool_default->pool_props, 3057c478bd9Sstevel@tonic-gate NV_UNIQUE_NAME, KM_SLEEP); 3067c478bd9Sstevel@tonic-gate (void) nvlist_add_string(pool_default->pool_props, 3077c478bd9Sstevel@tonic-gate "pool.name", "pool_default"); 3087c478bd9Sstevel@tonic-gate (void) nvlist_add_string(pool_default->pool_props, "pool.comment", ""); 3097c478bd9Sstevel@tonic-gate (void) nvlist_add_byte(pool_default->pool_props, "pool.default", 1); 3107c478bd9Sstevel@tonic-gate (void) nvlist_add_byte(pool_default->pool_props, "pool.active", 1); 3117c478bd9Sstevel@tonic-gate (void) nvlist_add_int64(pool_default->pool_props, 3127c478bd9Sstevel@tonic-gate "pool.importance", 1); 3137c478bd9Sstevel@tonic-gate (void) nvlist_add_int64(pool_default->pool_props, "pool.sys_id", 3147c478bd9Sstevel@tonic-gate pool_default->pool_id); 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate pool_sys_mod = pool_pool_mod = gethrtime(); 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate return (ret); 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate /* 3227c478bd9Sstevel@tonic-gate * Disable pools facility. 3237c478bd9Sstevel@tonic-gate */ 3247c478bd9Sstevel@tonic-gate static int 3257c478bd9Sstevel@tonic-gate pool_disable(void) 3267c478bd9Sstevel@tonic-gate { 3277c478bd9Sstevel@tonic-gate int ret; 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate if (pool_count > 1) /* must destroy all pools first */ 3327c478bd9Sstevel@tonic-gate return (EBUSY); 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate ret = pool_pset_disable(); 3357c478bd9Sstevel@tonic-gate if (ret != 0) 3367c478bd9Sstevel@tonic-gate return (ret); 3377c478bd9Sstevel@tonic-gate if (pool_sys_prop != NULL) { 3387c478bd9Sstevel@tonic-gate nvlist_free(pool_sys_prop); 3397c478bd9Sstevel@tonic-gate pool_sys_prop = NULL; 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate if (pool_default->pool_props != NULL) { 3427c478bd9Sstevel@tonic-gate nvlist_free(pool_default->pool_props); 3437c478bd9Sstevel@tonic-gate pool_default->pool_props = NULL; 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate return (0); 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate pool_t * 3497c478bd9Sstevel@tonic-gate pool_lookup_pool_by_name(char *name) 3507c478bd9Sstevel@tonic-gate { 3517c478bd9Sstevel@tonic-gate pool_t *pool = pool_default; 3527c478bd9Sstevel@tonic-gate char *p; 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 3557c478bd9Sstevel@tonic-gate for (pool = list_head(&pool_list); pool; 3567c478bd9Sstevel@tonic-gate pool = list_next(&pool_list, pool)) { 3577c478bd9Sstevel@tonic-gate if (nvlist_lookup_string(pool->pool_props, 3587c478bd9Sstevel@tonic-gate "pool.name", &p) == 0 && strcmp(name, p) == 0) 3597c478bd9Sstevel@tonic-gate return (pool); 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate return (NULL); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate pool_t * 3657c478bd9Sstevel@tonic-gate pool_lookup_pool_by_id(poolid_t poolid) 3667c478bd9Sstevel@tonic-gate { 3677c478bd9Sstevel@tonic-gate pool_t *pool = pool_default; 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 3707c478bd9Sstevel@tonic-gate for (pool = list_head(&pool_list); pool; 3717c478bd9Sstevel@tonic-gate pool = list_next(&pool_list, pool)) { 3727c478bd9Sstevel@tonic-gate if (pool->pool_id == poolid) 3737c478bd9Sstevel@tonic-gate return (pool); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate return (NULL); 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate /* 3797c478bd9Sstevel@tonic-gate * Create new pool, associate it with default resource sets, and give 3807c478bd9Sstevel@tonic-gate * it a temporary name. 3817c478bd9Sstevel@tonic-gate */ 3827c478bd9Sstevel@tonic-gate static int 3837c478bd9Sstevel@tonic-gate pool_pool_create(poolid_t *poolid) 3847c478bd9Sstevel@tonic-gate { 3857c478bd9Sstevel@tonic-gate pool_t *pool; 3867c478bd9Sstevel@tonic-gate char pool_name[40]; 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate pool = kmem_zalloc(sizeof (pool_t), KM_SLEEP); 3917c478bd9Sstevel@tonic-gate pool->pool_id = *poolid = id_alloc(pool_ids); 3927c478bd9Sstevel@tonic-gate pool->pool_pset = pool_pset_default; 3937c478bd9Sstevel@tonic-gate pool_pset_default->pset_npools++; 3947c478bd9Sstevel@tonic-gate list_insert_tail(&pool_list, pool); 3957c478bd9Sstevel@tonic-gate (void) nvlist_alloc(&pool->pool_props, NV_UNIQUE_NAME, KM_SLEEP); 3967c478bd9Sstevel@tonic-gate (void) nvlist_add_int64(pool->pool_props, "pool.sys_id", pool->pool_id); 3977c478bd9Sstevel@tonic-gate (void) nvlist_add_byte(pool->pool_props, "pool.default", 0); 3987c478bd9Sstevel@tonic-gate pool_pool_mod = gethrtime(); 3997c478bd9Sstevel@tonic-gate (void) snprintf(pool_name, sizeof (pool_name), "pool_%lld", 4007c478bd9Sstevel@tonic-gate pool_pool_mod); 4017c478bd9Sstevel@tonic-gate (void) nvlist_add_string(pool->pool_props, "pool.name", pool_name); 4027c478bd9Sstevel@tonic-gate pool_count++; 4037c478bd9Sstevel@tonic-gate return (0); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate struct destroy_zone_arg { 4077c478bd9Sstevel@tonic-gate pool_t *old; 4087c478bd9Sstevel@tonic-gate pool_t *new; 4097c478bd9Sstevel@tonic-gate }; 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate /* 4127c478bd9Sstevel@tonic-gate * Update pool pointers for zones that are currently bound to pool "old" 4137c478bd9Sstevel@tonic-gate * to be bound to pool "new". 4147c478bd9Sstevel@tonic-gate */ 4157c478bd9Sstevel@tonic-gate static int 4167c478bd9Sstevel@tonic-gate pool_destroy_zone_cb(zone_t *zone, void *arg) 4177c478bd9Sstevel@tonic-gate { 4187c478bd9Sstevel@tonic-gate struct destroy_zone_arg *dza = arg; 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 4217c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock)); 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate if (zone_pool_get(zone) == dza->old) 4247c478bd9Sstevel@tonic-gate zone_pool_set(zone, dza->new); 4257c478bd9Sstevel@tonic-gate return (0); 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate /* 4297c478bd9Sstevel@tonic-gate * Destroy specified pool, and rebind all processes in it 4307c478bd9Sstevel@tonic-gate * to the default pool. 4317c478bd9Sstevel@tonic-gate */ 4327c478bd9Sstevel@tonic-gate static int 4337c478bd9Sstevel@tonic-gate pool_pool_destroy(poolid_t poolid) 4347c478bd9Sstevel@tonic-gate { 4357c478bd9Sstevel@tonic-gate pool_t *pool; 4367c478bd9Sstevel@tonic-gate int ret; 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate if (poolid == POOL_DEFAULT) 4417c478bd9Sstevel@tonic-gate return (EINVAL); 4427c478bd9Sstevel@tonic-gate if ((pool = pool_lookup_pool_by_id(poolid)) == NULL) 4437c478bd9Sstevel@tonic-gate return (ESRCH); 4447c478bd9Sstevel@tonic-gate ret = pool_do_bind(pool_default, P_POOLID, poolid, POOL_BIND_ALL); 4457c478bd9Sstevel@tonic-gate if (ret == 0) { 4467c478bd9Sstevel@tonic-gate struct destroy_zone_arg dzarg; 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate dzarg.old = pool; 4497c478bd9Sstevel@tonic-gate dzarg.new = pool_default; 4507c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 4517c478bd9Sstevel@tonic-gate ret = zone_walk(pool_destroy_zone_cb, &dzarg); 4527c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 4537c478bd9Sstevel@tonic-gate ASSERT(ret == 0); 4547c478bd9Sstevel@tonic-gate ASSERT(pool->pool_ref == 0); 4557c478bd9Sstevel@tonic-gate (void) nvlist_free(pool->pool_props); 4567c478bd9Sstevel@tonic-gate id_free(pool_ids, pool->pool_id); 4577c478bd9Sstevel@tonic-gate pool->pool_pset->pset_npools--; 4587c478bd9Sstevel@tonic-gate list_remove(&pool_list, pool); 4597c478bd9Sstevel@tonic-gate pool_count--; 4607c478bd9Sstevel@tonic-gate pool_pool_mod = gethrtime(); 4617c478bd9Sstevel@tonic-gate kmem_free(pool, sizeof (pool_t)); 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate return (ret); 4647c478bd9Sstevel@tonic-gate } 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate /* 4677c478bd9Sstevel@tonic-gate * Create new pool or resource set. 4687c478bd9Sstevel@tonic-gate */ 4697c478bd9Sstevel@tonic-gate int 4707c478bd9Sstevel@tonic-gate pool_create(int class, int subclass, id_t *id) 4717c478bd9Sstevel@tonic-gate { 4727c478bd9Sstevel@tonic-gate int ret; 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 4757c478bd9Sstevel@tonic-gate if (pool_state == POOL_DISABLED) 4767c478bd9Sstevel@tonic-gate return (ENOTACTIVE); 4777c478bd9Sstevel@tonic-gate switch (class) { 4787c478bd9Sstevel@tonic-gate case PEC_POOL: 4797c478bd9Sstevel@tonic-gate ret = pool_pool_create((poolid_t *)id); 4807c478bd9Sstevel@tonic-gate break; 4817c478bd9Sstevel@tonic-gate case PEC_RES_COMP: 4827c478bd9Sstevel@tonic-gate switch (subclass) { 4837c478bd9Sstevel@tonic-gate case PREC_PSET: 4847c478bd9Sstevel@tonic-gate ret = pool_pset_create((psetid_t *)id); 4857c478bd9Sstevel@tonic-gate break; 4867c478bd9Sstevel@tonic-gate default: 4877c478bd9Sstevel@tonic-gate ret = EINVAL; 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate break; 4907c478bd9Sstevel@tonic-gate case PEC_RES_AGG: 4917c478bd9Sstevel@tonic-gate ret = ENOTSUP; 4927c478bd9Sstevel@tonic-gate break; 4937c478bd9Sstevel@tonic-gate default: 4947c478bd9Sstevel@tonic-gate ret = EINVAL; 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate return (ret); 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate /* 5007c478bd9Sstevel@tonic-gate * Destroy an existing pool or resource set. 5017c478bd9Sstevel@tonic-gate */ 5027c478bd9Sstevel@tonic-gate int 5037c478bd9Sstevel@tonic-gate pool_destroy(int class, int subclass, id_t id) 5047c478bd9Sstevel@tonic-gate { 5057c478bd9Sstevel@tonic-gate int ret; 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 5087c478bd9Sstevel@tonic-gate if (pool_state == POOL_DISABLED) 5097c478bd9Sstevel@tonic-gate return (ENOTACTIVE); 5107c478bd9Sstevel@tonic-gate switch (class) { 5117c478bd9Sstevel@tonic-gate case PEC_POOL: 5127c478bd9Sstevel@tonic-gate ret = pool_pool_destroy((poolid_t)id); 5137c478bd9Sstevel@tonic-gate break; 5147c478bd9Sstevel@tonic-gate case PEC_RES_COMP: 5157c478bd9Sstevel@tonic-gate switch (subclass) { 5167c478bd9Sstevel@tonic-gate case PREC_PSET: 5177c478bd9Sstevel@tonic-gate ret = pool_pset_destroy((psetid_t)id); 5187c478bd9Sstevel@tonic-gate break; 5197c478bd9Sstevel@tonic-gate default: 5207c478bd9Sstevel@tonic-gate ret = EINVAL; 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate break; 5237c478bd9Sstevel@tonic-gate case PEC_RES_AGG: 5247c478bd9Sstevel@tonic-gate ret = ENOTSUP; 5257c478bd9Sstevel@tonic-gate break; 5267c478bd9Sstevel@tonic-gate default: 5277c478bd9Sstevel@tonic-gate ret = EINVAL; 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate return (ret); 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate /* 5337c478bd9Sstevel@tonic-gate * Enable or disable pools. 5347c478bd9Sstevel@tonic-gate */ 5357c478bd9Sstevel@tonic-gate int 5367c478bd9Sstevel@tonic-gate pool_status(int status) 5377c478bd9Sstevel@tonic-gate { 5387c478bd9Sstevel@tonic-gate int ret = 0; 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate if (pool_state == status) 5437c478bd9Sstevel@tonic-gate return (0); 5447c478bd9Sstevel@tonic-gate switch (status) { 5457c478bd9Sstevel@tonic-gate case POOL_ENABLED: 5467c478bd9Sstevel@tonic-gate ret = pool_enable(); 5477c478bd9Sstevel@tonic-gate if (ret != 0) 5487c478bd9Sstevel@tonic-gate return (ret); 5497c478bd9Sstevel@tonic-gate pool_state = POOL_ENABLED; 5507c478bd9Sstevel@tonic-gate break; 5517c478bd9Sstevel@tonic-gate case POOL_DISABLED: 5527c478bd9Sstevel@tonic-gate ret = pool_disable(); 5537c478bd9Sstevel@tonic-gate if (ret != 0) 5547c478bd9Sstevel@tonic-gate return (ret); 5557c478bd9Sstevel@tonic-gate pool_state = POOL_DISABLED; 5567c478bd9Sstevel@tonic-gate break; 5577c478bd9Sstevel@tonic-gate default: 5587c478bd9Sstevel@tonic-gate ret = EINVAL; 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate return (ret); 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate /* 5647c478bd9Sstevel@tonic-gate * Associate pool with resource set. 5657c478bd9Sstevel@tonic-gate */ 5667c478bd9Sstevel@tonic-gate int 5677c478bd9Sstevel@tonic-gate pool_assoc(poolid_t poolid, int idtype, id_t id) 5687c478bd9Sstevel@tonic-gate { 5697c478bd9Sstevel@tonic-gate int ret; 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 5727c478bd9Sstevel@tonic-gate if (pool_state == POOL_DISABLED) 5737c478bd9Sstevel@tonic-gate return (ENOTACTIVE); 5747c478bd9Sstevel@tonic-gate switch (idtype) { 5757c478bd9Sstevel@tonic-gate case PREC_PSET: 5767c478bd9Sstevel@tonic-gate ret = pool_pset_assoc(poolid, (psetid_t)id); 5777c478bd9Sstevel@tonic-gate break; 5787c478bd9Sstevel@tonic-gate default: 5797c478bd9Sstevel@tonic-gate ret = EINVAL; 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate if (ret == 0) 5827c478bd9Sstevel@tonic-gate pool_pool_mod = gethrtime(); 5837c478bd9Sstevel@tonic-gate return (ret); 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate /* 5877c478bd9Sstevel@tonic-gate * Disassociate resource set from pool. 5887c478bd9Sstevel@tonic-gate */ 5897c478bd9Sstevel@tonic-gate int 5907c478bd9Sstevel@tonic-gate pool_dissoc(poolid_t poolid, int idtype) 5917c478bd9Sstevel@tonic-gate { 5927c478bd9Sstevel@tonic-gate int ret; 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 5957c478bd9Sstevel@tonic-gate if (pool_state == POOL_DISABLED) 5967c478bd9Sstevel@tonic-gate return (ENOTACTIVE); 5977c478bd9Sstevel@tonic-gate switch (idtype) { 5987c478bd9Sstevel@tonic-gate case PREC_PSET: 5997c478bd9Sstevel@tonic-gate ret = pool_pset_assoc(poolid, PS_NONE); 6007c478bd9Sstevel@tonic-gate break; 6017c478bd9Sstevel@tonic-gate default: 6027c478bd9Sstevel@tonic-gate ret = EINVAL; 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate if (ret == 0) 6057c478bd9Sstevel@tonic-gate pool_pool_mod = gethrtime(); 6067c478bd9Sstevel@tonic-gate return (ret); 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate /* 6107c478bd9Sstevel@tonic-gate * Transfer specified quantity of resources between resource sets. 6117c478bd9Sstevel@tonic-gate */ 6127c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 6137c478bd9Sstevel@tonic-gate int 6147c478bd9Sstevel@tonic-gate pool_transfer(int type, id_t src, id_t dst, uint64_t qty) 6157c478bd9Sstevel@tonic-gate { 6167c478bd9Sstevel@tonic-gate int ret = EINVAL; 6177c478bd9Sstevel@tonic-gate return (ret); 6187c478bd9Sstevel@tonic-gate } 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate /* 6217c478bd9Sstevel@tonic-gate * Transfer resources specified by their IDs between resource sets. 6227c478bd9Sstevel@tonic-gate */ 6237c478bd9Sstevel@tonic-gate int 6247c478bd9Sstevel@tonic-gate pool_xtransfer(int type, id_t src, id_t dst, uint_t size, id_t *ids) 6257c478bd9Sstevel@tonic-gate { 6267c478bd9Sstevel@tonic-gate int ret; 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 6297c478bd9Sstevel@tonic-gate if (pool_state == POOL_DISABLED) 6307c478bd9Sstevel@tonic-gate return (ENOTACTIVE); 6317c478bd9Sstevel@tonic-gate switch (type) { 6327c478bd9Sstevel@tonic-gate case PREC_PSET: 6337c478bd9Sstevel@tonic-gate ret = pool_pset_xtransfer((psetid_t)src, (psetid_t)dst, 6347c478bd9Sstevel@tonic-gate size, ids); 6357c478bd9Sstevel@tonic-gate break; 6367c478bd9Sstevel@tonic-gate default: 6377c478bd9Sstevel@tonic-gate ret = EINVAL; 6387c478bd9Sstevel@tonic-gate } 6397c478bd9Sstevel@tonic-gate return (ret); 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate /* 6437c478bd9Sstevel@tonic-gate * Bind processes to pools. 6447c478bd9Sstevel@tonic-gate */ 6457c478bd9Sstevel@tonic-gate int 6467c478bd9Sstevel@tonic-gate pool_bind(poolid_t poolid, idtype_t idtype, id_t id) 6477c478bd9Sstevel@tonic-gate { 6487c478bd9Sstevel@tonic-gate pool_t *pool; 6497c478bd9Sstevel@tonic-gate 6507c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate if (pool_state == POOL_DISABLED) 6537c478bd9Sstevel@tonic-gate return (ENOTACTIVE); 6547c478bd9Sstevel@tonic-gate if ((pool = pool_lookup_pool_by_id(poolid)) == NULL) 6557c478bd9Sstevel@tonic-gate return (ESRCH); 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate switch (idtype) { 6587c478bd9Sstevel@tonic-gate case P_PID: 6597c478bd9Sstevel@tonic-gate case P_TASKID: 6607c478bd9Sstevel@tonic-gate case P_PROJID: 6617c478bd9Sstevel@tonic-gate case P_ZONEID: 6627c478bd9Sstevel@tonic-gate break; 6637c478bd9Sstevel@tonic-gate default: 6647c478bd9Sstevel@tonic-gate return (EINVAL); 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate return (pool_do_bind(pool, idtype, id, POOL_BIND_ALL)); 6677c478bd9Sstevel@tonic-gate } 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate /* 6707c478bd9Sstevel@tonic-gate * Query pool binding of the specifed process. 6717c478bd9Sstevel@tonic-gate */ 6727c478bd9Sstevel@tonic-gate int 6737c478bd9Sstevel@tonic-gate pool_query_binding(idtype_t idtype, id_t id, id_t *poolid) 6747c478bd9Sstevel@tonic-gate { 6757c478bd9Sstevel@tonic-gate proc_t *p; 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate if (idtype != P_PID) 6787c478bd9Sstevel@tonic-gate return (ENOTSUP); 6797c478bd9Sstevel@tonic-gate if (id == P_MYID) 6807c478bd9Sstevel@tonic-gate id = curproc->p_pid; 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 6857c478bd9Sstevel@tonic-gate if ((p = prfind((pid_t)id)) == NULL) { 6867c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 6877c478bd9Sstevel@tonic-gate return (ESRCH); 6887c478bd9Sstevel@tonic-gate } 6897c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 6907c478bd9Sstevel@tonic-gate /* 6917c478bd9Sstevel@tonic-gate * In local zones, lie about pool bindings of processes from 6927c478bd9Sstevel@tonic-gate * the global zone. 6937c478bd9Sstevel@tonic-gate */ 6947c478bd9Sstevel@tonic-gate if (!INGLOBALZONE(curproc) && INGLOBALZONE(p)) { 6957c478bd9Sstevel@tonic-gate pool_t *pool; 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate pool = zone_pool_get(curproc->p_zone); 6987c478bd9Sstevel@tonic-gate *poolid = pool->pool_id; 6997c478bd9Sstevel@tonic-gate } else { 7007c478bd9Sstevel@tonic-gate *poolid = p->p_pool->pool_id; 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 7037c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 7047c478bd9Sstevel@tonic-gate return (0); 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate static ea_object_t * 7087c478bd9Sstevel@tonic-gate pool_system_pack(void) 7097c478bd9Sstevel@tonic-gate { 7107c478bd9Sstevel@tonic-gate ea_object_t *eo_system; 7117c478bd9Sstevel@tonic-gate size_t bufsz = 0; 7127c478bd9Sstevel@tonic-gate char *buf = NULL; 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate eo_system = ea_alloc_group(EXT_GROUP | EXC_LOCAL | EXD_GROUP_SYSTEM); 7177c478bd9Sstevel@tonic-gate (void) ea_attach_item(eo_system, &pool_sys_mod, sizeof (hrtime_t), 7187c478bd9Sstevel@tonic-gate EXC_LOCAL | EXD_SYSTEM_TSTAMP | EXT_UINT64); 7197c478bd9Sstevel@tonic-gate if (INGLOBALZONE(curproc)) 7207c478bd9Sstevel@tonic-gate (void) ea_attach_item(eo_system, &pool_pool_mod, 7217c478bd9Sstevel@tonic-gate sizeof (hrtime_t), 7227c478bd9Sstevel@tonic-gate EXC_LOCAL | EXD_POOL_TSTAMP | EXT_UINT64); 7237c478bd9Sstevel@tonic-gate else 7247c478bd9Sstevel@tonic-gate (void) ea_attach_item(eo_system, 7257c478bd9Sstevel@tonic-gate &curproc->p_zone->zone_pool_mod, 7267c478bd9Sstevel@tonic-gate sizeof (hrtime_t), 7277c478bd9Sstevel@tonic-gate EXC_LOCAL | EXD_POOL_TSTAMP | EXT_UINT64); 7287c478bd9Sstevel@tonic-gate (void) ea_attach_item(eo_system, &pool_pset_mod, sizeof (hrtime_t), 7297c478bd9Sstevel@tonic-gate EXC_LOCAL | EXD_PSET_TSTAMP | EXT_UINT64); 7307c478bd9Sstevel@tonic-gate (void) ea_attach_item(eo_system, &pool_cpu_mod, sizeof (hrtime_t), 7317c478bd9Sstevel@tonic-gate EXC_LOCAL | EXD_CPU_TSTAMP | EXT_UINT64); 7327c478bd9Sstevel@tonic-gate (void) nvlist_pack(pool_sys_prop, &buf, &bufsz, NV_ENCODE_NATIVE, 0); 7337c478bd9Sstevel@tonic-gate (void) ea_attach_item(eo_system, buf, bufsz, 7347c478bd9Sstevel@tonic-gate EXC_LOCAL | EXD_SYSTEM_PROP | EXT_RAW); 7357c478bd9Sstevel@tonic-gate kmem_free(buf, bufsz); 7367c478bd9Sstevel@tonic-gate return (eo_system); 7377c478bd9Sstevel@tonic-gate } 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate /* 7407c478bd9Sstevel@tonic-gate * Pack information about pools and attach it to specified exacct group. 7417c478bd9Sstevel@tonic-gate */ 7427c478bd9Sstevel@tonic-gate static int 7437c478bd9Sstevel@tonic-gate pool_pool_pack(ea_object_t *eo_system) 7447c478bd9Sstevel@tonic-gate { 7457c478bd9Sstevel@tonic-gate ea_object_t *eo_pool; 7467c478bd9Sstevel@tonic-gate pool_t *pool; 7477c478bd9Sstevel@tonic-gate size_t bufsz; 7487c478bd9Sstevel@tonic-gate char *buf; 7497c478bd9Sstevel@tonic-gate pool_t *myzonepool; 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 7527c478bd9Sstevel@tonic-gate myzonepool = zone_pool_get(curproc->p_zone); 7537c478bd9Sstevel@tonic-gate for (pool = list_head(&pool_list); pool; 7547c478bd9Sstevel@tonic-gate pool = list_next(&pool_list, pool)) { 7557c478bd9Sstevel@tonic-gate if (!INGLOBALZONE(curproc) && myzonepool != pool) 7567c478bd9Sstevel@tonic-gate continue; 7577c478bd9Sstevel@tonic-gate bufsz = 0; 7587c478bd9Sstevel@tonic-gate buf = NULL; 7597c478bd9Sstevel@tonic-gate eo_pool = ea_alloc_group(EXT_GROUP | 7607c478bd9Sstevel@tonic-gate EXC_LOCAL | EXD_GROUP_POOL); 7617c478bd9Sstevel@tonic-gate (void) ea_attach_item(eo_pool, &pool->pool_id, sizeof (id_t), 7627c478bd9Sstevel@tonic-gate EXC_LOCAL | EXD_POOL_POOLID | EXT_UINT32); 7637c478bd9Sstevel@tonic-gate (void) ea_attach_item(eo_pool, &pool->pool_pset->pset_id, 7647c478bd9Sstevel@tonic-gate sizeof (id_t), EXC_LOCAL | EXD_POOL_PSETID | EXT_UINT32); 7657c478bd9Sstevel@tonic-gate (void) nvlist_pack(pool->pool_props, &buf, &bufsz, 7667c478bd9Sstevel@tonic-gate NV_ENCODE_NATIVE, 0); 7677c478bd9Sstevel@tonic-gate (void) ea_attach_item(eo_pool, buf, bufsz, 7687c478bd9Sstevel@tonic-gate EXC_LOCAL | EXD_POOL_PROP | EXT_RAW); 7697c478bd9Sstevel@tonic-gate kmem_free(buf, bufsz); 7707c478bd9Sstevel@tonic-gate (void) ea_attach_to_group(eo_system, eo_pool); 7717c478bd9Sstevel@tonic-gate } 7727c478bd9Sstevel@tonic-gate return (0); 7737c478bd9Sstevel@tonic-gate } 7747c478bd9Sstevel@tonic-gate 7757c478bd9Sstevel@tonic-gate /* 7767c478bd9Sstevel@tonic-gate * Pack the whole pool configuration in the specified buffer. 7777c478bd9Sstevel@tonic-gate */ 7787c478bd9Sstevel@tonic-gate int 7797c478bd9Sstevel@tonic-gate pool_pack_conf(void *kbuf, size_t kbufsz, size_t *asize) 7807c478bd9Sstevel@tonic-gate { 7817c478bd9Sstevel@tonic-gate ea_object_t *eo_system; 7827c478bd9Sstevel@tonic-gate size_t ksize; 7837c478bd9Sstevel@tonic-gate int ret = 0; 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate eo_system = pool_system_pack(); /* 1. pack system */ 7887c478bd9Sstevel@tonic-gate (void) pool_pool_pack(eo_system); /* 2. pack all pools */ 7897c478bd9Sstevel@tonic-gate (void) pool_pset_pack(eo_system); /* 3. pack all psets */ 7907c478bd9Sstevel@tonic-gate ksize = ea_pack_object(eo_system, NULL, 0); 7917c478bd9Sstevel@tonic-gate if (kbuf == NULL || kbufsz == 0) 7927c478bd9Sstevel@tonic-gate *asize = ksize; 7937c478bd9Sstevel@tonic-gate else if (ksize > kbufsz) 7947c478bd9Sstevel@tonic-gate ret = ENOMEM; 7957c478bd9Sstevel@tonic-gate else 7967c478bd9Sstevel@tonic-gate *asize = ea_pack_object(eo_system, kbuf, kbufsz); 7977c478bd9Sstevel@tonic-gate ea_free_object(eo_system, EUP_ALLOC); 7987c478bd9Sstevel@tonic-gate return (ret); 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate /* 8027c478bd9Sstevel@tonic-gate * Start/end the commit transaction. If commit transaction is currently 8037c478bd9Sstevel@tonic-gate * in progress, then all POOL_QUERY ioctls will return pools configuration 8047c478bd9Sstevel@tonic-gate * at the beginning of transaction. 8057c478bd9Sstevel@tonic-gate */ 8067c478bd9Sstevel@tonic-gate int 8077c478bd9Sstevel@tonic-gate pool_commit(int state) 8087c478bd9Sstevel@tonic-gate { 8097c478bd9Sstevel@tonic-gate ea_object_t *eo_system; 8107c478bd9Sstevel@tonic-gate int ret = 0; 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate if (pool_state == POOL_DISABLED) 8157c478bd9Sstevel@tonic-gate return (ENOTACTIVE); 8167c478bd9Sstevel@tonic-gate switch (state) { 8177c478bd9Sstevel@tonic-gate case 1: 8187c478bd9Sstevel@tonic-gate /* 8197c478bd9Sstevel@tonic-gate * Beginning commit transation. 8207c478bd9Sstevel@tonic-gate */ 8217c478bd9Sstevel@tonic-gate if (pool_buf != NULL) /* transaction in progress */ 8227c478bd9Sstevel@tonic-gate return (EBUSY); 8237c478bd9Sstevel@tonic-gate eo_system = pool_system_pack(); /* 1. pack system */ 8247c478bd9Sstevel@tonic-gate (void) pool_pool_pack(eo_system); /* 2. pack all pools */ 8257c478bd9Sstevel@tonic-gate (void) pool_pset_pack(eo_system); /* 3. pack all psets */ 8267c478bd9Sstevel@tonic-gate pool_bufsz = ea_pack_object(eo_system, NULL, 0); 8277c478bd9Sstevel@tonic-gate pool_buf = kmem_alloc(pool_bufsz, KM_SLEEP); 8287c478bd9Sstevel@tonic-gate pool_bufsz = ea_pack_object(eo_system, pool_buf, pool_bufsz); 8297c478bd9Sstevel@tonic-gate ea_free_object(eo_system, EUP_ALLOC); 8307c478bd9Sstevel@tonic-gate break; 8317c478bd9Sstevel@tonic-gate case 0: 8327c478bd9Sstevel@tonic-gate /* 8337c478bd9Sstevel@tonic-gate * Finishing commit transaction. 8347c478bd9Sstevel@tonic-gate */ 8357c478bd9Sstevel@tonic-gate if (pool_buf != NULL) { 8367c478bd9Sstevel@tonic-gate kmem_free(pool_buf, pool_bufsz); 8377c478bd9Sstevel@tonic-gate pool_buf = NULL; 8387c478bd9Sstevel@tonic-gate pool_bufsz = 0; 8397c478bd9Sstevel@tonic-gate } 8407c478bd9Sstevel@tonic-gate break; 8417c478bd9Sstevel@tonic-gate default: 8427c478bd9Sstevel@tonic-gate ret = EINVAL; 8437c478bd9Sstevel@tonic-gate } 8447c478bd9Sstevel@tonic-gate return (ret); 8457c478bd9Sstevel@tonic-gate } 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate /* 8487c478bd9Sstevel@tonic-gate * Check is the specified property is special 8497c478bd9Sstevel@tonic-gate */ 8507c478bd9Sstevel@tonic-gate static pool_property_t * 8517c478bd9Sstevel@tonic-gate pool_property_find(char *name, pool_property_t *list) 8527c478bd9Sstevel@tonic-gate { 8537c478bd9Sstevel@tonic-gate pool_property_t *prop; 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate for (prop = list; prop->pp_name != NULL; prop++) 8567c478bd9Sstevel@tonic-gate if (strcmp(prop->pp_name, name) == 0) 8577c478bd9Sstevel@tonic-gate return (prop); 8587c478bd9Sstevel@tonic-gate return (NULL); 8597c478bd9Sstevel@tonic-gate } 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate static pool_property_t pool_prop_sys[] = { 8627c478bd9Sstevel@tonic-gate { "system.name", DATA_TYPE_STRING, PP_RDWR }, 8637c478bd9Sstevel@tonic-gate { "system.comment", DATA_TYPE_STRING, PP_RDWR }, 8647c478bd9Sstevel@tonic-gate { "system.version", DATA_TYPE_UINT64, PP_READ }, 8657c478bd9Sstevel@tonic-gate { "system.bind-default", DATA_TYPE_BYTE, PP_RDWR }, 8667c478bd9Sstevel@tonic-gate { "system.allocate-method", DATA_TYPE_STRING, 8677c478bd9Sstevel@tonic-gate PP_RDWR | PP_OPTIONAL }, 8687c478bd9Sstevel@tonic-gate { "system.poold.log-level", DATA_TYPE_STRING, 8697c478bd9Sstevel@tonic-gate PP_RDWR | PP_OPTIONAL }, 8707c478bd9Sstevel@tonic-gate { "system.poold.log-location", DATA_TYPE_STRING, 8717c478bd9Sstevel@tonic-gate PP_RDWR | PP_OPTIONAL }, 8727c478bd9Sstevel@tonic-gate { "system.poold.monitor-interval", DATA_TYPE_UINT64, 8737c478bd9Sstevel@tonic-gate PP_RDWR | PP_OPTIONAL }, 8747c478bd9Sstevel@tonic-gate { "system.poold.history-file", DATA_TYPE_STRING, 8757c478bd9Sstevel@tonic-gate PP_RDWR | PP_OPTIONAL }, 8767c478bd9Sstevel@tonic-gate { "system.poold.objectives", DATA_TYPE_STRING, 8777c478bd9Sstevel@tonic-gate PP_RDWR | PP_OPTIONAL }, 8787c478bd9Sstevel@tonic-gate { NULL, 0, 0 } 8797c478bd9Sstevel@tonic-gate }; 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate static pool_property_t pool_prop_pool[] = { 8827c478bd9Sstevel@tonic-gate { "pool.sys_id", DATA_TYPE_UINT64, PP_READ }, 8837c478bd9Sstevel@tonic-gate { "pool.name", DATA_TYPE_STRING, PP_RDWR }, 8847c478bd9Sstevel@tonic-gate { "pool.default", DATA_TYPE_BYTE, PP_READ }, 8857c478bd9Sstevel@tonic-gate { "pool.active", DATA_TYPE_BYTE, PP_RDWR }, 8867c478bd9Sstevel@tonic-gate { "pool.importance", DATA_TYPE_INT64, PP_RDWR }, 8877c478bd9Sstevel@tonic-gate { "pool.comment", DATA_TYPE_STRING, PP_RDWR }, 8887c478bd9Sstevel@tonic-gate { "pool.scheduler", DATA_TYPE_STRING, 8897c478bd9Sstevel@tonic-gate PP_RDWR | PP_OPTIONAL }, 8907c478bd9Sstevel@tonic-gate { NULL, 0, 0 } 8917c478bd9Sstevel@tonic-gate }; 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate /* 8947c478bd9Sstevel@tonic-gate * Common routine to put new property on the specified list 8957c478bd9Sstevel@tonic-gate */ 8967c478bd9Sstevel@tonic-gate int 8977c478bd9Sstevel@tonic-gate pool_propput_common(nvlist_t *nvlist, nvpair_t *pair, pool_property_t *props) 8987c478bd9Sstevel@tonic-gate { 8997c478bd9Sstevel@tonic-gate pool_property_t *prop; 9007c478bd9Sstevel@tonic-gate 9017c478bd9Sstevel@tonic-gate if ((prop = pool_property_find(nvpair_name(pair), props)) != NULL) { 9027c478bd9Sstevel@tonic-gate /* 9037c478bd9Sstevel@tonic-gate * No read-only properties or properties with bad types 9047c478bd9Sstevel@tonic-gate */ 9057c478bd9Sstevel@tonic-gate if (!(prop->pp_perm & PP_WRITE) || 9067c478bd9Sstevel@tonic-gate prop->pp_type != nvpair_type(pair)) 9077c478bd9Sstevel@tonic-gate return (EINVAL); 9087c478bd9Sstevel@tonic-gate } 9097c478bd9Sstevel@tonic-gate return (nvlist_add_nvpair(nvlist, pair)); 9107c478bd9Sstevel@tonic-gate } 9117c478bd9Sstevel@tonic-gate 9127c478bd9Sstevel@tonic-gate /* 9137c478bd9Sstevel@tonic-gate * Common routine to remove property from the given list 9147c478bd9Sstevel@tonic-gate */ 9157c478bd9Sstevel@tonic-gate int 9167c478bd9Sstevel@tonic-gate pool_proprm_common(nvlist_t *nvlist, char *name, pool_property_t *props) 9177c478bd9Sstevel@tonic-gate { 9187c478bd9Sstevel@tonic-gate pool_property_t *prop; 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate if ((prop = pool_property_find(name, props)) != NULL) { 9217c478bd9Sstevel@tonic-gate if (!(prop->pp_perm & PP_OPTIONAL)) 9227c478bd9Sstevel@tonic-gate return (EINVAL); 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate return (nvlist_remove_all(nvlist, name)); 9257c478bd9Sstevel@tonic-gate } 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate static int 9287c478bd9Sstevel@tonic-gate pool_system_propput(nvpair_t *pair) 9297c478bd9Sstevel@tonic-gate { 9307c478bd9Sstevel@tonic-gate int ret; 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 9337c478bd9Sstevel@tonic-gate ret = pool_propput_common(pool_sys_prop, pair, pool_prop_sys); 9347c478bd9Sstevel@tonic-gate if (ret == 0) 9357c478bd9Sstevel@tonic-gate pool_sys_mod = gethrtime(); 9367c478bd9Sstevel@tonic-gate return (ret); 9377c478bd9Sstevel@tonic-gate } 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate static int 9407c478bd9Sstevel@tonic-gate pool_system_proprm(char *name) 9417c478bd9Sstevel@tonic-gate { 9427c478bd9Sstevel@tonic-gate int ret; 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 9457c478bd9Sstevel@tonic-gate ret = pool_proprm_common(pool_sys_prop, name, pool_prop_sys); 9467c478bd9Sstevel@tonic-gate if (ret == 0) 9477c478bd9Sstevel@tonic-gate pool_sys_mod = gethrtime(); 9487c478bd9Sstevel@tonic-gate return (ret); 9497c478bd9Sstevel@tonic-gate } 9507c478bd9Sstevel@tonic-gate 9517c478bd9Sstevel@tonic-gate static int 9527c478bd9Sstevel@tonic-gate pool_pool_propput(poolid_t poolid, nvpair_t *pair) 9537c478bd9Sstevel@tonic-gate { 9547c478bd9Sstevel@tonic-gate pool_t *pool; 9557c478bd9Sstevel@tonic-gate int ret; 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 9587c478bd9Sstevel@tonic-gate if ((pool = pool_lookup_pool_by_id(poolid)) == NULL) 9597c478bd9Sstevel@tonic-gate return (ESRCH); 9607c478bd9Sstevel@tonic-gate ret = pool_propput_common(pool->pool_props, pair, pool_prop_pool); 9617c478bd9Sstevel@tonic-gate if (ret == 0) 9627c478bd9Sstevel@tonic-gate pool_pool_mod = gethrtime(); 9637c478bd9Sstevel@tonic-gate return (ret); 9647c478bd9Sstevel@tonic-gate } 9657c478bd9Sstevel@tonic-gate 9667c478bd9Sstevel@tonic-gate static int 9677c478bd9Sstevel@tonic-gate pool_pool_proprm(poolid_t poolid, char *name) 9687c478bd9Sstevel@tonic-gate { 9697c478bd9Sstevel@tonic-gate int ret; 9707c478bd9Sstevel@tonic-gate pool_t *pool; 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 9737c478bd9Sstevel@tonic-gate if ((pool = pool_lookup_pool_by_id(poolid)) == NULL) 9747c478bd9Sstevel@tonic-gate return (ESRCH); 9757c478bd9Sstevel@tonic-gate ret = pool_proprm_common(pool->pool_props, name, pool_prop_pool); 9767c478bd9Sstevel@tonic-gate if (ret == 0) 9777c478bd9Sstevel@tonic-gate pool_pool_mod = gethrtime(); 9787c478bd9Sstevel@tonic-gate return (ret); 9797c478bd9Sstevel@tonic-gate } 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate int 9827c478bd9Sstevel@tonic-gate pool_propput(int class, int subclass, id_t id, nvpair_t *pair) 9837c478bd9Sstevel@tonic-gate { 9847c478bd9Sstevel@tonic-gate int ret; 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 9877c478bd9Sstevel@tonic-gate if (pool_state == POOL_DISABLED) 9887c478bd9Sstevel@tonic-gate return (ENOTACTIVE); 9897c478bd9Sstevel@tonic-gate switch (class) { 9907c478bd9Sstevel@tonic-gate case PEC_SYSTEM: 9917c478bd9Sstevel@tonic-gate ret = pool_system_propput(pair); 9927c478bd9Sstevel@tonic-gate break; 9937c478bd9Sstevel@tonic-gate case PEC_POOL: 9947c478bd9Sstevel@tonic-gate ret = pool_pool_propput((poolid_t)id, pair); 9957c478bd9Sstevel@tonic-gate break; 9967c478bd9Sstevel@tonic-gate case PEC_RES_COMP: 9977c478bd9Sstevel@tonic-gate switch (subclass) { 9987c478bd9Sstevel@tonic-gate case PREC_PSET: 9997c478bd9Sstevel@tonic-gate ret = pool_pset_propput((psetid_t)id, pair); 10007c478bd9Sstevel@tonic-gate break; 10017c478bd9Sstevel@tonic-gate default: 10027c478bd9Sstevel@tonic-gate ret = EINVAL; 10037c478bd9Sstevel@tonic-gate } 10047c478bd9Sstevel@tonic-gate break; 10057c478bd9Sstevel@tonic-gate case PEC_RES_AGG: 10067c478bd9Sstevel@tonic-gate ret = ENOTSUP; 10077c478bd9Sstevel@tonic-gate break; 10087c478bd9Sstevel@tonic-gate case PEC_COMP: 10097c478bd9Sstevel@tonic-gate switch (subclass) { 10107c478bd9Sstevel@tonic-gate case PCEC_CPU: 10117c478bd9Sstevel@tonic-gate ret = pool_cpu_propput((processorid_t)id, pair); 10127c478bd9Sstevel@tonic-gate break; 10137c478bd9Sstevel@tonic-gate default: 10147c478bd9Sstevel@tonic-gate ret = EINVAL; 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate break; 10177c478bd9Sstevel@tonic-gate default: 10187c478bd9Sstevel@tonic-gate ret = EINVAL; 10197c478bd9Sstevel@tonic-gate } 10207c478bd9Sstevel@tonic-gate return (ret); 10217c478bd9Sstevel@tonic-gate } 10227c478bd9Sstevel@tonic-gate 10237c478bd9Sstevel@tonic-gate int 10247c478bd9Sstevel@tonic-gate pool_proprm(int class, int subclass, id_t id, char *name) 10257c478bd9Sstevel@tonic-gate { 10267c478bd9Sstevel@tonic-gate int ret; 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 10297c478bd9Sstevel@tonic-gate if (pool_state == POOL_DISABLED) 10307c478bd9Sstevel@tonic-gate return (ENOTACTIVE); 10317c478bd9Sstevel@tonic-gate switch (class) { 10327c478bd9Sstevel@tonic-gate case PEC_SYSTEM: 10337c478bd9Sstevel@tonic-gate ret = pool_system_proprm(name); 10347c478bd9Sstevel@tonic-gate break; 10357c478bd9Sstevel@tonic-gate case PEC_POOL: 10367c478bd9Sstevel@tonic-gate ret = pool_pool_proprm((poolid_t)id, name); 10377c478bd9Sstevel@tonic-gate break; 10387c478bd9Sstevel@tonic-gate case PEC_RES_COMP: 10397c478bd9Sstevel@tonic-gate switch (subclass) { 10407c478bd9Sstevel@tonic-gate case PREC_PSET: 10417c478bd9Sstevel@tonic-gate ret = pool_pset_proprm((psetid_t)id, name); 10427c478bd9Sstevel@tonic-gate break; 10437c478bd9Sstevel@tonic-gate default: 10447c478bd9Sstevel@tonic-gate ret = EINVAL; 10457c478bd9Sstevel@tonic-gate } 10467c478bd9Sstevel@tonic-gate break; 10477c478bd9Sstevel@tonic-gate case PEC_RES_AGG: 10487c478bd9Sstevel@tonic-gate ret = ENOTSUP; 10497c478bd9Sstevel@tonic-gate break; 10507c478bd9Sstevel@tonic-gate case PEC_COMP: 10517c478bd9Sstevel@tonic-gate switch (subclass) { 10527c478bd9Sstevel@tonic-gate case PCEC_CPU: 10537c478bd9Sstevel@tonic-gate ret = pool_cpu_proprm((processorid_t)id, name); 10547c478bd9Sstevel@tonic-gate break; 10557c478bd9Sstevel@tonic-gate default: 10567c478bd9Sstevel@tonic-gate ret = EINVAL; 10577c478bd9Sstevel@tonic-gate } 10587c478bd9Sstevel@tonic-gate break; 10597c478bd9Sstevel@tonic-gate default: 10607c478bd9Sstevel@tonic-gate ret = EINVAL; 10617c478bd9Sstevel@tonic-gate } 10627c478bd9Sstevel@tonic-gate return (ret); 10637c478bd9Sstevel@tonic-gate } 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate int 10667c478bd9Sstevel@tonic-gate pool_propget(char *name, int class, int subclass, id_t id, nvlist_t **nvlp) 10677c478bd9Sstevel@tonic-gate { 10687c478bd9Sstevel@tonic-gate int ret; 10697c478bd9Sstevel@tonic-gate nvlist_t *nvl; 10707c478bd9Sstevel@tonic-gate 10717c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 10727c478bd9Sstevel@tonic-gate if (pool_state == POOL_DISABLED) 10737c478bd9Sstevel@tonic-gate return (ENOTACTIVE); 10747c478bd9Sstevel@tonic-gate 10757c478bd9Sstevel@tonic-gate (void) nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP); 10767c478bd9Sstevel@tonic-gate 10777c478bd9Sstevel@tonic-gate switch (class) { 10787c478bd9Sstevel@tonic-gate case PEC_SYSTEM: 10797c478bd9Sstevel@tonic-gate case PEC_POOL: 10807c478bd9Sstevel@tonic-gate ret = EINVAL; 10817c478bd9Sstevel@tonic-gate break; 10827c478bd9Sstevel@tonic-gate case PEC_RES_COMP: 10837c478bd9Sstevel@tonic-gate switch (subclass) { 10847c478bd9Sstevel@tonic-gate case PREC_PSET: 10857c478bd9Sstevel@tonic-gate ret = pool_pset_propget((psetid_t)id, name, nvl); 10867c478bd9Sstevel@tonic-gate break; 10877c478bd9Sstevel@tonic-gate default: 10887c478bd9Sstevel@tonic-gate ret = EINVAL; 10897c478bd9Sstevel@tonic-gate } 10907c478bd9Sstevel@tonic-gate break; 10917c478bd9Sstevel@tonic-gate case PEC_RES_AGG: 10927c478bd9Sstevel@tonic-gate ret = ENOTSUP; 10937c478bd9Sstevel@tonic-gate break; 10947c478bd9Sstevel@tonic-gate case PEC_COMP: 10957c478bd9Sstevel@tonic-gate switch (subclass) { 10967c478bd9Sstevel@tonic-gate case PCEC_CPU: 10977c478bd9Sstevel@tonic-gate ret = pool_cpu_propget((processorid_t)id, name, nvl); 10987c478bd9Sstevel@tonic-gate break; 10997c478bd9Sstevel@tonic-gate default: 11007c478bd9Sstevel@tonic-gate ret = EINVAL; 11017c478bd9Sstevel@tonic-gate } 11027c478bd9Sstevel@tonic-gate break; 11037c478bd9Sstevel@tonic-gate default: 11047c478bd9Sstevel@tonic-gate ret = EINVAL; 11057c478bd9Sstevel@tonic-gate } 11067c478bd9Sstevel@tonic-gate if (ret == 0) 11077c478bd9Sstevel@tonic-gate *nvlp = nvl; 11087c478bd9Sstevel@tonic-gate else 11097c478bd9Sstevel@tonic-gate nvlist_free(nvl); 11107c478bd9Sstevel@tonic-gate return (ret); 11117c478bd9Sstevel@tonic-gate } 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate /* 11147c478bd9Sstevel@tonic-gate * pool_bind_wake and pool_bind_wakeall are helper functions to undo PBWAITs 11157c478bd9Sstevel@tonic-gate * in case of failure in pool_do_bind(). 11167c478bd9Sstevel@tonic-gate */ 11177c478bd9Sstevel@tonic-gate static void 11187c478bd9Sstevel@tonic-gate pool_bind_wake(proc_t *p) 11197c478bd9Sstevel@tonic-gate { 11207c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 11217c478bd9Sstevel@tonic-gate 11227c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 11237c478bd9Sstevel@tonic-gate ASSERT(p->p_poolflag & PBWAIT); 11247c478bd9Sstevel@tonic-gate if (p->p_poolcnt > 0) { 11257c478bd9Sstevel@tonic-gate mutex_enter(&pool_barrier_lock); 11267c478bd9Sstevel@tonic-gate pool_barrier_count -= p->p_poolcnt; 11277c478bd9Sstevel@tonic-gate mutex_exit(&pool_barrier_lock); 11287c478bd9Sstevel@tonic-gate } 11297c478bd9Sstevel@tonic-gate p->p_poolflag &= ~PBWAIT; 11307c478bd9Sstevel@tonic-gate cv_signal(&p->p_poolcv); 11317c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 11327c478bd9Sstevel@tonic-gate } 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate static void 11357c478bd9Sstevel@tonic-gate pool_bind_wakeall(proc_t **procs) 11367c478bd9Sstevel@tonic-gate { 11377c478bd9Sstevel@tonic-gate proc_t *p, **pp; 11387c478bd9Sstevel@tonic-gate 11397c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 11407c478bd9Sstevel@tonic-gate for (pp = procs; (p = *pp) != NULL; pp++) 11417c478bd9Sstevel@tonic-gate pool_bind_wake(p); 11427c478bd9Sstevel@tonic-gate } 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate /* 11457c478bd9Sstevel@tonic-gate * Return the scheduling class for this pool, or 11467c478bd9Sstevel@tonic-gate * POOL_CLASS_UNSET if not set 11477c478bd9Sstevel@tonic-gate * POOL_CLASS_INVAL if set to an invalid class ID. 11487c478bd9Sstevel@tonic-gate */ 11497c478bd9Sstevel@tonic-gate id_t 11507c478bd9Sstevel@tonic-gate pool_get_class(pool_t *pool) 11517c478bd9Sstevel@tonic-gate { 11527c478bd9Sstevel@tonic-gate char *name; 11537c478bd9Sstevel@tonic-gate id_t cid; 11547c478bd9Sstevel@tonic-gate 11557c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 11567c478bd9Sstevel@tonic-gate 11577c478bd9Sstevel@tonic-gate if (nvlist_lookup_string(pool->pool_props, "pool.scheduler", 11587c478bd9Sstevel@tonic-gate &name) == 0) { 11597c478bd9Sstevel@tonic-gate if (getcidbyname(name, &cid) == 0) 11607c478bd9Sstevel@tonic-gate return (cid); 11617c478bd9Sstevel@tonic-gate else 11627c478bd9Sstevel@tonic-gate return (POOL_CLASS_INVAL); 11637c478bd9Sstevel@tonic-gate } 11647c478bd9Sstevel@tonic-gate return (POOL_CLASS_UNSET); 11657c478bd9Sstevel@tonic-gate } 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate /* 11687c478bd9Sstevel@tonic-gate * Move process to the new scheduling class. 11697c478bd9Sstevel@tonic-gate */ 11707c478bd9Sstevel@tonic-gate static void 11717c478bd9Sstevel@tonic-gate pool_change_class(proc_t *p, id_t cid) 11727c478bd9Sstevel@tonic-gate { 11737c478bd9Sstevel@tonic-gate kthread_t *t; 11747c478bd9Sstevel@tonic-gate void *cldata; 11757c478bd9Sstevel@tonic-gate id_t oldcid; 11767c478bd9Sstevel@tonic-gate void **bufs; 11777c478bd9Sstevel@tonic-gate void **buf; 11787c478bd9Sstevel@tonic-gate int nlwp; 11797c478bd9Sstevel@tonic-gate int ret; 11807c478bd9Sstevel@tonic-gate int i; 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate /* 11837c478bd9Sstevel@tonic-gate * Do not move kernel processes (such as zsched). 11847c478bd9Sstevel@tonic-gate */ 11857c478bd9Sstevel@tonic-gate if (p->p_flag & SSYS) 11867c478bd9Sstevel@tonic-gate return; 11877c478bd9Sstevel@tonic-gate /* 11887c478bd9Sstevel@tonic-gate * This process is in the pool barrier, so it can't possibly be 11897c478bd9Sstevel@tonic-gate * adding new threads and we can use p_lwpcnt + p_zombcnt + 1 11907c478bd9Sstevel@tonic-gate * (for possible agent LWP which doesn't use pool barrier) as 11917c478bd9Sstevel@tonic-gate * our upper bound. 11927c478bd9Sstevel@tonic-gate */ 11937c478bd9Sstevel@tonic-gate nlwp = p->p_lwpcnt + p->p_zombcnt + 1; 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate /* 11967c478bd9Sstevel@tonic-gate * Pre-allocate scheduling class specific buffers before 11977c478bd9Sstevel@tonic-gate * grabbing p_lock. 11987c478bd9Sstevel@tonic-gate */ 11997c478bd9Sstevel@tonic-gate bufs = kmem_zalloc(nlwp * sizeof (void *), KM_SLEEP); 12007c478bd9Sstevel@tonic-gate for (i = 0, buf = bufs; i < nlwp; i++, buf++) { 12017c478bd9Sstevel@tonic-gate ret = CL_ALLOC(buf, cid, KM_SLEEP); 12027c478bd9Sstevel@tonic-gate ASSERT(ret == 0); 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate /* 12067c478bd9Sstevel@tonic-gate * Move threads one by one to the new scheduling class. 12077c478bd9Sstevel@tonic-gate * This never fails because we have all the right 12087c478bd9Sstevel@tonic-gate * privileges here. 12097c478bd9Sstevel@tonic-gate */ 12107c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 12117c478bd9Sstevel@tonic-gate ASSERT(p->p_poolflag & PBWAIT); 12127c478bd9Sstevel@tonic-gate buf = bufs; 12137c478bd9Sstevel@tonic-gate t = p->p_tlist; 12147c478bd9Sstevel@tonic-gate ASSERT(t != NULL); 12157c478bd9Sstevel@tonic-gate do { 12167c478bd9Sstevel@tonic-gate if (t->t_cid != cid) { 12177c478bd9Sstevel@tonic-gate oldcid = t->t_cid; 12187c478bd9Sstevel@tonic-gate cldata = t->t_cldata; 12197c478bd9Sstevel@tonic-gate ret = CL_ENTERCLASS(t, cid, NULL, NULL, *buf); 12207c478bd9Sstevel@tonic-gate ASSERT(ret == 0); 12217c478bd9Sstevel@tonic-gate CL_EXITCLASS(oldcid, cldata); 1222*d4204c85Sraf schedctl_set_cidpri(t); 12237c478bd9Sstevel@tonic-gate *buf++ = NULL; 12247c478bd9Sstevel@tonic-gate } 12257c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist); 12267c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 12277c478bd9Sstevel@tonic-gate /* 12287c478bd9Sstevel@tonic-gate * Free unused scheduling class specific buffers. 12297c478bd9Sstevel@tonic-gate */ 12307c478bd9Sstevel@tonic-gate for (i = 0, buf = bufs; i < nlwp; i++, buf++) { 12317c478bd9Sstevel@tonic-gate if (*buf != NULL) { 12327c478bd9Sstevel@tonic-gate CL_FREE(cid, *buf); 12337c478bd9Sstevel@tonic-gate *buf = NULL; 12347c478bd9Sstevel@tonic-gate } 12357c478bd9Sstevel@tonic-gate } 12367c478bd9Sstevel@tonic-gate kmem_free(bufs, nlwp * sizeof (void *)); 12377c478bd9Sstevel@tonic-gate } 12387c478bd9Sstevel@tonic-gate 12397c478bd9Sstevel@tonic-gate /* 12407c478bd9Sstevel@tonic-gate * The meat of the bind operation. The steps in pool_do_bind are: 12417c478bd9Sstevel@tonic-gate * 12427c478bd9Sstevel@tonic-gate * 1) Set PBWAIT in the p_poolflag of any process of interest, and add all 12437c478bd9Sstevel@tonic-gate * such processes to an array. For any interesting process that has 12447c478bd9Sstevel@tonic-gate * threads inside the pool barrier set, increment a counter by the 12457c478bd9Sstevel@tonic-gate * count of such threads. Once PBWAIT is set on a process, that process 12467c478bd9Sstevel@tonic-gate * will not disappear. 12477c478bd9Sstevel@tonic-gate * 12487c478bd9Sstevel@tonic-gate * 2) Wait for the counter from step 2 to drop to zero. Any process which 12497c478bd9Sstevel@tonic-gate * calls pool_barrier_exit() and notices that PBWAIT has been set on it 12507c478bd9Sstevel@tonic-gate * will decrement that counter before going to sleep, and the process 12517c478bd9Sstevel@tonic-gate * calling pool_barrier_exit() which does the final decrement will wake us. 12527c478bd9Sstevel@tonic-gate * 12537c478bd9Sstevel@tonic-gate * 3) For each interesting process, perform a calculation on it to see if 12547c478bd9Sstevel@tonic-gate * the bind will actually succeed. This uses the following three 12557c478bd9Sstevel@tonic-gate * resource-set-specific functions: 12567c478bd9Sstevel@tonic-gate * 12577c478bd9Sstevel@tonic-gate * - int set_bind_start(procs, pool) 12587c478bd9Sstevel@tonic-gate * 12597c478bd9Sstevel@tonic-gate * Determine whether the given array of processes can be bound to the 12607c478bd9Sstevel@tonic-gate * resource set associated with the given pool. If it can, take and hold 12617c478bd9Sstevel@tonic-gate * any locks necessary to ensure that the operation will succeed, and 12627c478bd9Sstevel@tonic-gate * make any necessary reservations in the target resource set. If it 12637c478bd9Sstevel@tonic-gate * can't, return failure with no reservations made and no new locks held. 12647c478bd9Sstevel@tonic-gate * 12657c478bd9Sstevel@tonic-gate * - void set_bind_abort(procs, pool) 12667c478bd9Sstevel@tonic-gate * 12677c478bd9Sstevel@tonic-gate * set_bind_start() has completed successfully, but another resource set's 12687c478bd9Sstevel@tonic-gate * set_bind_start() has failed, and we haven't begun the bind yet. Undo 12697c478bd9Sstevel@tonic-gate * any reservations made and drop any locks acquired by our 12707c478bd9Sstevel@tonic-gate * set_bind_start(). 12717c478bd9Sstevel@tonic-gate * 12727c478bd9Sstevel@tonic-gate * - void set_bind_finish(void) 12737c478bd9Sstevel@tonic-gate * 12747c478bd9Sstevel@tonic-gate * The bind has completed successfully. The processes have been released, 12757c478bd9Sstevel@tonic-gate * and the reservation acquired in set_bind_start() has been depleted as 12767c478bd9Sstevel@tonic-gate * the processes have finished their bindings. Drop any locks acquired by 12777c478bd9Sstevel@tonic-gate * set_bind_start(). 12787c478bd9Sstevel@tonic-gate * 12797c478bd9Sstevel@tonic-gate * 4) If we've decided that we can proceed with the bind, iterate through 12807c478bd9Sstevel@tonic-gate * the list of interesting processes, grab the necessary locks (which 12817c478bd9Sstevel@tonic-gate * may differ per resource set), perform the bind, and ASSERT that it 12827c478bd9Sstevel@tonic-gate * succeeds. Once a process has been rebound, it can be awakened. 12837c478bd9Sstevel@tonic-gate * 12847c478bd9Sstevel@tonic-gate * The operations from step 4 must be kept in sync with anything which might 12857c478bd9Sstevel@tonic-gate * cause the bind operations (e.g., cpupart_bind_thread()) to fail, and 12867c478bd9Sstevel@tonic-gate * are thus located in the same source files as the associated bind operations. 12877c478bd9Sstevel@tonic-gate */ 12887c478bd9Sstevel@tonic-gate int 12897c478bd9Sstevel@tonic-gate pool_do_bind(pool_t *pool, idtype_t idtype, id_t id, int flags) 12907c478bd9Sstevel@tonic-gate { 12917c478bd9Sstevel@tonic-gate extern uint_t nproc; 12927c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 12937c478bd9Sstevel@tonic-gate proc_t **pp, **procs; 12947c478bd9Sstevel@tonic-gate proc_t *prstart; 12957c478bd9Sstevel@tonic-gate int procs_count = 0; 12967c478bd9Sstevel@tonic-gate kproject_t *kpj; 12977c478bd9Sstevel@tonic-gate procset_t set; 12987c478bd9Sstevel@tonic-gate zone_t *zone; 12997c478bd9Sstevel@tonic-gate int procs_size; 13007c478bd9Sstevel@tonic-gate int rv = 0; 13017c478bd9Sstevel@tonic-gate proc_t *p; 13027c478bd9Sstevel@tonic-gate id_t cid = -1; 13037c478bd9Sstevel@tonic-gate 13047c478bd9Sstevel@tonic-gate ASSERT(pool_lock_held()); 13057c478bd9Sstevel@tonic-gate 13067c478bd9Sstevel@tonic-gate if ((cid = pool_get_class(pool)) == POOL_CLASS_INVAL) 13077c478bd9Sstevel@tonic-gate return (EINVAL); 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate if (idtype == P_ZONEID) { 13107c478bd9Sstevel@tonic-gate zone = zone_find_by_id(id); 13117c478bd9Sstevel@tonic-gate if (zone == NULL) 13127c478bd9Sstevel@tonic-gate return (ESRCH); 13137c478bd9Sstevel@tonic-gate if (zone_status_get(zone) > ZONE_IS_RUNNING) { 13147c478bd9Sstevel@tonic-gate zone_rele(zone); 13157c478bd9Sstevel@tonic-gate return (EBUSY); 13167c478bd9Sstevel@tonic-gate } 13177c478bd9Sstevel@tonic-gate } 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate if (idtype == P_PROJID) { 13200209230bSgjelinek kpj = project_hold_by_id(id, global_zone, PROJECT_HOLD_FIND); 13217c478bd9Sstevel@tonic-gate if (kpj == NULL) 13227c478bd9Sstevel@tonic-gate return (ESRCH); 13237c478bd9Sstevel@tonic-gate mutex_enter(&kpj->kpj_poolbind); 13247c478bd9Sstevel@tonic-gate } 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate if (idtype == P_PID) { 13277c478bd9Sstevel@tonic-gate /* 13287c478bd9Sstevel@tonic-gate * Fast-path for a single process case. 13297c478bd9Sstevel@tonic-gate */ 13307c478bd9Sstevel@tonic-gate procs_size = 2; /* procs is NULL-terminated */ 13317c478bd9Sstevel@tonic-gate procs = kmem_zalloc(procs_size * sizeof (proc_t *), KM_SLEEP); 13327c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 13337c478bd9Sstevel@tonic-gate } else { 13347c478bd9Sstevel@tonic-gate /* 13357c478bd9Sstevel@tonic-gate * We will need enough slots for proc_t pointers for as many as 13367c478bd9Sstevel@tonic-gate * twice the number of currently running processes (assuming 13377c478bd9Sstevel@tonic-gate * that each one could be in fork() creating a new child). 13387c478bd9Sstevel@tonic-gate */ 13397c478bd9Sstevel@tonic-gate for (;;) { 13407c478bd9Sstevel@tonic-gate procs_size = nproc * 2; 13417c478bd9Sstevel@tonic-gate procs = kmem_zalloc(procs_size * sizeof (proc_t *), 13427c478bd9Sstevel@tonic-gate KM_SLEEP); 13437c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 13447c478bd9Sstevel@tonic-gate 13457c478bd9Sstevel@tonic-gate if (nproc * 2 <= procs_size) 13467c478bd9Sstevel@tonic-gate break; 13477c478bd9Sstevel@tonic-gate /* 13487c478bd9Sstevel@tonic-gate * If nproc has changed, try again. 13497c478bd9Sstevel@tonic-gate */ 13507c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 13517c478bd9Sstevel@tonic-gate kmem_free(procs, procs_size * sizeof (proc_t *)); 13527c478bd9Sstevel@tonic-gate } 13537c478bd9Sstevel@tonic-gate } 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate if (id == P_MYID) 13567c478bd9Sstevel@tonic-gate id = getmyid(idtype); 13577c478bd9Sstevel@tonic-gate setprocset(&set, POP_AND, idtype, id, P_ALL, 0); 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate /* 13607c478bd9Sstevel@tonic-gate * Do a first scan, and select target processes. 13617c478bd9Sstevel@tonic-gate */ 13627c478bd9Sstevel@tonic-gate if (idtype == P_PID) 13637c478bd9Sstevel@tonic-gate prstart = prfind(id); 13647c478bd9Sstevel@tonic-gate else 13657c478bd9Sstevel@tonic-gate prstart = practive; 13667c478bd9Sstevel@tonic-gate for (p = prstart, pp = procs; p != NULL; p = p->p_next) { 13677c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 13687c478bd9Sstevel@tonic-gate /* 13697c478bd9Sstevel@tonic-gate * Skip processes that don't match our (id, idtype) set or 13707c478bd9Sstevel@tonic-gate * on the way of becoming zombies. Skip kernel processes 13717c478bd9Sstevel@tonic-gate * from the global zone. 13727c478bd9Sstevel@tonic-gate */ 13737c478bd9Sstevel@tonic-gate if (procinset(p, &set) == 0 || 13747c478bd9Sstevel@tonic-gate p->p_poolflag & PEXITED || 13757c478bd9Sstevel@tonic-gate ((p->p_flag & SSYS) && INGLOBALZONE(p))) { 13767c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 13777c478bd9Sstevel@tonic-gate continue; 13787c478bd9Sstevel@tonic-gate } 13797c478bd9Sstevel@tonic-gate if (!INGLOBALZONE(p)) { 13807c478bd9Sstevel@tonic-gate switch (idtype) { 13817c478bd9Sstevel@tonic-gate case P_PID: 13827c478bd9Sstevel@tonic-gate case P_TASKID: 13837c478bd9Sstevel@tonic-gate /* 13847c478bd9Sstevel@tonic-gate * Can't bind processes or tasks 13857c478bd9Sstevel@tonic-gate * in local zones to pools. 13867c478bd9Sstevel@tonic-gate */ 13877c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 13887c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 13897c478bd9Sstevel@tonic-gate pool_bind_wakeall(procs); 13907c478bd9Sstevel@tonic-gate rv = EINVAL; 13917c478bd9Sstevel@tonic-gate goto out; 13927c478bd9Sstevel@tonic-gate case P_PROJID: 13937c478bd9Sstevel@tonic-gate /* 13947c478bd9Sstevel@tonic-gate * Only projects in the global 13957c478bd9Sstevel@tonic-gate * zone can be rebound. 13967c478bd9Sstevel@tonic-gate */ 13977c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 13987c478bd9Sstevel@tonic-gate continue; 13997c478bd9Sstevel@tonic-gate case P_POOLID: 14007c478bd9Sstevel@tonic-gate /* 14017c478bd9Sstevel@tonic-gate * When rebinding pools, processes can be 14027c478bd9Sstevel@tonic-gate * in different zones. 14037c478bd9Sstevel@tonic-gate */ 14047c478bd9Sstevel@tonic-gate break; 14057c478bd9Sstevel@tonic-gate } 14067c478bd9Sstevel@tonic-gate } 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate p->p_poolflag |= PBWAIT; 14097c478bd9Sstevel@tonic-gate /* 14107c478bd9Sstevel@tonic-gate * If some threads in this process are inside the pool 14117c478bd9Sstevel@tonic-gate * barrier, add them to pool_barrier_count, as we have 14127c478bd9Sstevel@tonic-gate * to wait for all of them to exit the barrier. 14137c478bd9Sstevel@tonic-gate */ 14147c478bd9Sstevel@tonic-gate if (p->p_poolcnt > 0) { 14157c478bd9Sstevel@tonic-gate mutex_enter(&pool_barrier_lock); 14167c478bd9Sstevel@tonic-gate pool_barrier_count += p->p_poolcnt; 14177c478bd9Sstevel@tonic-gate mutex_exit(&pool_barrier_lock); 14187c478bd9Sstevel@tonic-gate } 14197c478bd9Sstevel@tonic-gate ASSERT(pp < &procs[procs_size]); 14207c478bd9Sstevel@tonic-gate *pp++ = p; 14217c478bd9Sstevel@tonic-gate procs_count++; 14227c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 14237c478bd9Sstevel@tonic-gate 14247c478bd9Sstevel@tonic-gate /* 14257c478bd9Sstevel@tonic-gate * We just found our process, so if we're only rebinding a 14267c478bd9Sstevel@tonic-gate * single process then get out of this loop. 14277c478bd9Sstevel@tonic-gate */ 14287c478bd9Sstevel@tonic-gate if (idtype == P_PID) 14297c478bd9Sstevel@tonic-gate break; 14307c478bd9Sstevel@tonic-gate } 14317c478bd9Sstevel@tonic-gate *pp = NULL; /* cap off the end of the array */ 14327c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate /* 14357c478bd9Sstevel@tonic-gate * Wait for relevant processes to stop before they try to enter the 14367c478bd9Sstevel@tonic-gate * barrier or at the exit from the barrier. Make sure that we do 14377c478bd9Sstevel@tonic-gate * not get stopped here while we're holding pool_lock. If we were 14387c478bd9Sstevel@tonic-gate * requested to stop, or got a signal then return EAGAIN to let the 14397c478bd9Sstevel@tonic-gate * library know that it needs to retry. 14407c478bd9Sstevel@tonic-gate */ 14417c478bd9Sstevel@tonic-gate mutex_enter(&pool_barrier_lock); 14427c478bd9Sstevel@tonic-gate lwp->lwp_nostop++; 14437c478bd9Sstevel@tonic-gate while (pool_barrier_count > 0) { 14447c478bd9Sstevel@tonic-gate (void) cv_wait_sig(&pool_barrier_cv, &pool_barrier_lock); 14457c478bd9Sstevel@tonic-gate if (pool_barrier_count > 0) { 14467c478bd9Sstevel@tonic-gate /* 14477c478bd9Sstevel@tonic-gate * We either got a signal or were requested to 14487c478bd9Sstevel@tonic-gate * stop by /proc. Bail out with EAGAIN. If we were 14497c478bd9Sstevel@tonic-gate * requested to stop, we'll stop in post_syscall() 14507c478bd9Sstevel@tonic-gate * on our way back to userland. 14517c478bd9Sstevel@tonic-gate */ 14527c478bd9Sstevel@tonic-gate mutex_exit(&pool_barrier_lock); 14537c478bd9Sstevel@tonic-gate pool_bind_wakeall(procs); 14547c478bd9Sstevel@tonic-gate lwp->lwp_nostop--; 14557c478bd9Sstevel@tonic-gate rv = EAGAIN; 14567c478bd9Sstevel@tonic-gate goto out; 14577c478bd9Sstevel@tonic-gate } 14587c478bd9Sstevel@tonic-gate } 14597c478bd9Sstevel@tonic-gate lwp->lwp_nostop--; 14607c478bd9Sstevel@tonic-gate mutex_exit(&pool_barrier_lock); 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate if (idtype == P_PID) 14637c478bd9Sstevel@tonic-gate goto skip; 14647c478bd9Sstevel@tonic-gate 14657c478bd9Sstevel@tonic-gate /* 14667c478bd9Sstevel@tonic-gate * Do another run, and drop processes that were inside the barrier 14677c478bd9Sstevel@tonic-gate * in exit(), but when they have dropped to pool_barrier_exit 14687c478bd9Sstevel@tonic-gate * they have become of no interest to us. Pick up child processes that 14697c478bd9Sstevel@tonic-gate * were created by fork() but didn't exist during our first scan. 14707c478bd9Sstevel@tonic-gate * Their parents are now stopped at pool_barrier_exit in cfork(). 14717c478bd9Sstevel@tonic-gate */ 14727c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 14737c478bd9Sstevel@tonic-gate for (pp = procs; (p = *pp) != NULL; pp++) { 14747c478bd9Sstevel@tonic-gate if (p->p_poolflag & PEXITED) { 14757c478bd9Sstevel@tonic-gate ASSERT(p->p_lwpcnt == 0); 14767c478bd9Sstevel@tonic-gate pool_bind_wake(p); 14777c478bd9Sstevel@tonic-gate /* flip w/last non-NULL slot */ 14787c478bd9Sstevel@tonic-gate *pp = procs[procs_count - 1]; 14797c478bd9Sstevel@tonic-gate procs[procs_count - 1] = NULL; 14807c478bd9Sstevel@tonic-gate procs_count--; 14817c478bd9Sstevel@tonic-gate pp--; /* try this slot again */ 14827c478bd9Sstevel@tonic-gate continue; 14837c478bd9Sstevel@tonic-gate } 14847c478bd9Sstevel@tonic-gate /* 14857c478bd9Sstevel@tonic-gate * Look at the child and check if it should be rebound also. 14867c478bd9Sstevel@tonic-gate * We're holding pidlock, so it is safe to reference p_child. 14877c478bd9Sstevel@tonic-gate */ 14887c478bd9Sstevel@tonic-gate if ((p = p->p_child) == NULL) 14897c478bd9Sstevel@tonic-gate continue; 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 14927c478bd9Sstevel@tonic-gate /* 14937c478bd9Sstevel@tonic-gate * Skip processes in local zones if we're not binding 14947c478bd9Sstevel@tonic-gate * zones to pools (P_ZONEID). Skip kernel processes also. 14957c478bd9Sstevel@tonic-gate */ 14967c478bd9Sstevel@tonic-gate if ((!INGLOBALZONE(p) && idtype != P_ZONEID) || 14977c478bd9Sstevel@tonic-gate p->p_flag & SSYS) { 14987c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 14997c478bd9Sstevel@tonic-gate continue; 15007c478bd9Sstevel@tonic-gate } 15017c478bd9Sstevel@tonic-gate 15027c478bd9Sstevel@tonic-gate /* 15037c478bd9Sstevel@tonic-gate * If the child process has been already created by fork(), has 15047c478bd9Sstevel@tonic-gate * not exited, and has not been added to the list already, 15057c478bd9Sstevel@tonic-gate * then add it now. We will hit this process again (since we 15067c478bd9Sstevel@tonic-gate * stick it at the end of the procs list) but it will ignored 15077c478bd9Sstevel@tonic-gate * because it will have the PBWAIT flag set. 15087c478bd9Sstevel@tonic-gate */ 15097c478bd9Sstevel@tonic-gate if (procinset(p, &set) && 15107c478bd9Sstevel@tonic-gate !(p->p_poolflag & PEXITED) && 15117c478bd9Sstevel@tonic-gate !(p->p_poolflag & PBWAIT)) { 15127c478bd9Sstevel@tonic-gate ASSERT(p->p_child == NULL); /* no child of a child */ 15137c478bd9Sstevel@tonic-gate procs[procs_count] = p; 15147c478bd9Sstevel@tonic-gate procs[procs_count + 1] = NULL; 15157c478bd9Sstevel@tonic-gate procs_count++; 15167c478bd9Sstevel@tonic-gate p->p_poolflag |= PBWAIT; 15177c478bd9Sstevel@tonic-gate } 15187c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 15197c478bd9Sstevel@tonic-gate } 15207c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 15217c478bd9Sstevel@tonic-gate skip: 15227c478bd9Sstevel@tonic-gate /* 15237c478bd9Sstevel@tonic-gate * If there's no processes to rebind then return ESRCH, unless 15247c478bd9Sstevel@tonic-gate * we're associating a pool with new resource set, destroying it, 15257c478bd9Sstevel@tonic-gate * or binding a zone to a pool. 15267c478bd9Sstevel@tonic-gate */ 15277c478bd9Sstevel@tonic-gate if (procs_count == 0) { 15287c478bd9Sstevel@tonic-gate if (idtype == P_POOLID || idtype == P_ZONEID) 15297c478bd9Sstevel@tonic-gate rv = 0; 15307c478bd9Sstevel@tonic-gate else 15317c478bd9Sstevel@tonic-gate rv = ESRCH; 15327c478bd9Sstevel@tonic-gate goto out; 15337c478bd9Sstevel@tonic-gate } 15347c478bd9Sstevel@tonic-gate 15357c478bd9Sstevel@tonic-gate #ifdef DEBUG 15367c478bd9Sstevel@tonic-gate /* 15377c478bd9Sstevel@tonic-gate * All processes in the array should have PBWAIT set, and none should 15387c478bd9Sstevel@tonic-gate * be in the critical section. Even though p_poolflag is protected by 15397c478bd9Sstevel@tonic-gate * the p_lock, these assertions should be stable across the dropping of 15407c478bd9Sstevel@tonic-gate * p_lock. 15417c478bd9Sstevel@tonic-gate */ 15427c478bd9Sstevel@tonic-gate for (pp = procs; (p = *pp) != NULL; pp++) { 15437c478bd9Sstevel@tonic-gate ASSERT(p->p_poolflag & PBWAIT); 15447c478bd9Sstevel@tonic-gate ASSERT(p->p_poolcnt == 0); 15457c478bd9Sstevel@tonic-gate ASSERT(procinset(p, &set)); 15467c478bd9Sstevel@tonic-gate } 15477c478bd9Sstevel@tonic-gate #endif 15487c478bd9Sstevel@tonic-gate 15497c478bd9Sstevel@tonic-gate /* 15507c478bd9Sstevel@tonic-gate * Do the check if processor set rebinding is going to succeed or not. 15517c478bd9Sstevel@tonic-gate */ 15527c478bd9Sstevel@tonic-gate if ((flags & POOL_BIND_PSET) && 15537c478bd9Sstevel@tonic-gate (rv = pset_bind_start(procs, pool)) != 0) { 15547c478bd9Sstevel@tonic-gate pool_bind_wakeall(procs); 15557c478bd9Sstevel@tonic-gate goto out; 15567c478bd9Sstevel@tonic-gate } 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate /* 15597c478bd9Sstevel@tonic-gate * At this point, all bind operations should succeed. 15607c478bd9Sstevel@tonic-gate */ 15617c478bd9Sstevel@tonic-gate for (pp = procs; (p = *pp) != NULL; pp++) { 15627c478bd9Sstevel@tonic-gate if (flags & POOL_BIND_PSET) { 15637c478bd9Sstevel@tonic-gate psetid_t psetid = pool->pool_pset->pset_id; 15647c478bd9Sstevel@tonic-gate void *zonebuf; 15657c478bd9Sstevel@tonic-gate void *projbuf; 15667c478bd9Sstevel@tonic-gate 15677c478bd9Sstevel@tonic-gate /* 15687c478bd9Sstevel@tonic-gate * Pre-allocate one buffer for FSS (per-project 15697c478bd9Sstevel@tonic-gate * buffer for a new pset) in case if this is the 15707c478bd9Sstevel@tonic-gate * first thread from its current project getting 15717c478bd9Sstevel@tonic-gate * bound to this processor set. 15727c478bd9Sstevel@tonic-gate */ 15737c478bd9Sstevel@tonic-gate projbuf = fss_allocbuf(FSS_ONE_BUF, FSS_ALLOC_PROJ); 15747c478bd9Sstevel@tonic-gate zonebuf = fss_allocbuf(FSS_ONE_BUF, FSS_ALLOC_ZONE); 15757c478bd9Sstevel@tonic-gate 15767c478bd9Sstevel@tonic-gate mutex_enter(&pidlock); 15777c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 15787c478bd9Sstevel@tonic-gate pool_pset_bind(p, psetid, projbuf, zonebuf); 15797c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 15807c478bd9Sstevel@tonic-gate mutex_exit(&pidlock); 15817c478bd9Sstevel@tonic-gate /* 15827c478bd9Sstevel@tonic-gate * Free buffers pre-allocated above if it 15837c478bd9Sstevel@tonic-gate * wasn't actually used. 15847c478bd9Sstevel@tonic-gate */ 15857c478bd9Sstevel@tonic-gate fss_freebuf(projbuf, FSS_ALLOC_PROJ); 15867c478bd9Sstevel@tonic-gate fss_freebuf(zonebuf, FSS_ALLOC_ZONE); 15877c478bd9Sstevel@tonic-gate } 15887c478bd9Sstevel@tonic-gate /* 15897c478bd9Sstevel@tonic-gate * Now let's change the scheduling class of this 15907c478bd9Sstevel@tonic-gate * process if our target pool has it defined. 15917c478bd9Sstevel@tonic-gate */ 15927c478bd9Sstevel@tonic-gate if (cid != POOL_CLASS_UNSET) 15937c478bd9Sstevel@tonic-gate pool_change_class(p, cid); 15947c478bd9Sstevel@tonic-gate 15957c478bd9Sstevel@tonic-gate /* 15967c478bd9Sstevel@tonic-gate * It is safe to reference p_pool here without holding 15977c478bd9Sstevel@tonic-gate * p_lock because it cannot change underneath of us. 15987c478bd9Sstevel@tonic-gate * We're holding pool_lock here, so nobody else can be 15997c478bd9Sstevel@tonic-gate * moving this process between pools. If process "p" 16007c478bd9Sstevel@tonic-gate * would be exiting, we're guaranteed that it would be blocked 16017c478bd9Sstevel@tonic-gate * at pool_barrier_enter() in exit(). Otherwise, it would've 16027c478bd9Sstevel@tonic-gate * been skipped by one of our scans of the practive list 16037c478bd9Sstevel@tonic-gate * as a process with PEXITED flag set. 16047c478bd9Sstevel@tonic-gate */ 16057c478bd9Sstevel@tonic-gate if (p->p_pool != pool) { 16067c478bd9Sstevel@tonic-gate ASSERT(p->p_pool->pool_ref > 0); 16077c478bd9Sstevel@tonic-gate atomic_add_32(&p->p_pool->pool_ref, -1); 16087c478bd9Sstevel@tonic-gate p->p_pool = pool; 16097c478bd9Sstevel@tonic-gate atomic_add_32(&p->p_pool->pool_ref, 1); 16107c478bd9Sstevel@tonic-gate } 16117c478bd9Sstevel@tonic-gate /* 16127c478bd9Sstevel@tonic-gate * Okay, we've tortured this guy enough. 16137c478bd9Sstevel@tonic-gate * Let this poor process go now. 16147c478bd9Sstevel@tonic-gate */ 16157c478bd9Sstevel@tonic-gate pool_bind_wake(p); 16167c478bd9Sstevel@tonic-gate } 16177c478bd9Sstevel@tonic-gate if (flags & POOL_BIND_PSET) 16187c478bd9Sstevel@tonic-gate pset_bind_finish(); 16197c478bd9Sstevel@tonic-gate 16207c478bd9Sstevel@tonic-gate out: switch (idtype) { 16217c478bd9Sstevel@tonic-gate case P_PROJID: 16227c478bd9Sstevel@tonic-gate ASSERT(kpj != NULL); 16237c478bd9Sstevel@tonic-gate mutex_exit(&kpj->kpj_poolbind); 16247c478bd9Sstevel@tonic-gate project_rele(kpj); 16257c478bd9Sstevel@tonic-gate break; 16267c478bd9Sstevel@tonic-gate case P_ZONEID: 16277c478bd9Sstevel@tonic-gate if (rv == 0) { 16287c478bd9Sstevel@tonic-gate mutex_enter(&cpu_lock); 16297c478bd9Sstevel@tonic-gate zone_pool_set(zone, pool); 16307c478bd9Sstevel@tonic-gate mutex_exit(&cpu_lock); 16317c478bd9Sstevel@tonic-gate } 16327c478bd9Sstevel@tonic-gate zone->zone_pool_mod = gethrtime(); 16337c478bd9Sstevel@tonic-gate zone_rele(zone); 16347c478bd9Sstevel@tonic-gate break; 16357c478bd9Sstevel@tonic-gate } 16367c478bd9Sstevel@tonic-gate 16377c478bd9Sstevel@tonic-gate kmem_free(procs, procs_size * sizeof (proc_t *)); 16387c478bd9Sstevel@tonic-gate ASSERT(pool_barrier_count == 0); 16397c478bd9Sstevel@tonic-gate return (rv); 16407c478bd9Sstevel@tonic-gate } 1641