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