1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/swap.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/buf.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/callb.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 40*7c478bd9Sstevel@tonic-gate #include <vm/seg.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/fs/swapnode.h> 42*7c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/mem_config.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/atomic.h> 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate extern const fs_operation_def_t swap_vnodeops_template[]; 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate /* 50*7c478bd9Sstevel@tonic-gate * swapfs_minfree is the amount of physical memory (actually remaining 51*7c478bd9Sstevel@tonic-gate * availrmem) that we want to keep free for the rest of the system. This 52*7c478bd9Sstevel@tonic-gate * means that swapfs can only grow to availrmem - swapfs_minfree. This 53*7c478bd9Sstevel@tonic-gate * can be set as just constant value or a certain percentage of installed 54*7c478bd9Sstevel@tonic-gate * physical memory. It is set in swapinit(). 55*7c478bd9Sstevel@tonic-gate * 56*7c478bd9Sstevel@tonic-gate * Users who want to change the amount of memory that can be used as swap 57*7c478bd9Sstevel@tonic-gate * space should do so by setting swapfs_desfree at boot time, 58*7c478bd9Sstevel@tonic-gate * not swapfs_minfree. 59*7c478bd9Sstevel@tonic-gate */ 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate pgcnt_t swapfs_desfree = 0; 62*7c478bd9Sstevel@tonic-gate pgcnt_t swapfs_minfree = 0; 63*7c478bd9Sstevel@tonic-gate pgcnt_t swapfs_reserve = 0; 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate #ifdef SWAPFS_DEBUG 66*7c478bd9Sstevel@tonic-gate int swapfs_debug; 67*7c478bd9Sstevel@tonic-gate #endif /* SWAPFS_DEBUG */ 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate static int swapfs_vpcount; 71*7c478bd9Sstevel@tonic-gate static kmutex_t swapfs_lock; 72*7c478bd9Sstevel@tonic-gate static struct async_reqs *sw_ar, *sw_pendlist, *sw_freelist; 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate static struct vnode **swap_vnodes; /* ptr's to swap vnodes */ 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate static void swap_init_mem_config(void); 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate static pgcnt_t initial_swapfs_desfree; 79*7c478bd9Sstevel@tonic-gate static pgcnt_t initial_swapfs_minfree; 80*7c478bd9Sstevel@tonic-gate static pgcnt_t initial_swapfs_reserve; 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate static int swap_sync(struct vfs *vfsp, short flag, struct cred *cr); 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate static void 85*7c478bd9Sstevel@tonic-gate swapfs_recalc_save_initial(void) 86*7c478bd9Sstevel@tonic-gate { 87*7c478bd9Sstevel@tonic-gate initial_swapfs_desfree = swapfs_desfree; 88*7c478bd9Sstevel@tonic-gate initial_swapfs_minfree = swapfs_minfree; 89*7c478bd9Sstevel@tonic-gate initial_swapfs_reserve = swapfs_reserve; 90*7c478bd9Sstevel@tonic-gate } 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate static int 93*7c478bd9Sstevel@tonic-gate swapfs_recalc(pgcnt_t pgs) 94*7c478bd9Sstevel@tonic-gate { 95*7c478bd9Sstevel@tonic-gate pgcnt_t new_swapfs_desfree; 96*7c478bd9Sstevel@tonic-gate pgcnt_t new_swapfs_minfree; 97*7c478bd9Sstevel@tonic-gate pgcnt_t new_swapfs_reserve; 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate new_swapfs_desfree = initial_swapfs_desfree; 100*7c478bd9Sstevel@tonic-gate new_swapfs_minfree = initial_swapfs_minfree; 101*7c478bd9Sstevel@tonic-gate new_swapfs_reserve = initial_swapfs_reserve; 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate if (new_swapfs_desfree == 0) 104*7c478bd9Sstevel@tonic-gate new_swapfs_desfree = btopr(7 * 512 * 1024); /* 3-1/2Mb */; 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate if (new_swapfs_minfree == 0) { 107*7c478bd9Sstevel@tonic-gate /* 108*7c478bd9Sstevel@tonic-gate * We set this lower than we'd like here, 2Mb, because we 109*7c478bd9Sstevel@tonic-gate * always boot on swapfs. It's up to a safer value, 110*7c478bd9Sstevel@tonic-gate * swapfs_desfree, when/if we add physical swap devices 111*7c478bd9Sstevel@tonic-gate * in swapadd(). Users who want to change the amount of 112*7c478bd9Sstevel@tonic-gate * memory that can be used as swap space should do so by 113*7c478bd9Sstevel@tonic-gate * setting swapfs_desfree at boot time, not swapfs_minfree. 114*7c478bd9Sstevel@tonic-gate * However, swapfs_minfree is tunable by install as a 115*7c478bd9Sstevel@tonic-gate * workaround for bugid 1147463. 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate new_swapfs_minfree = MAX(btopr(2 * 1024 * 1024), pgs >> 3); 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate /* 121*7c478bd9Sstevel@tonic-gate * priv processes can reserve memory as swap as long as availrmem 122*7c478bd9Sstevel@tonic-gate * remains greater than swapfs_minfree; in the case of non-priv 123*7c478bd9Sstevel@tonic-gate * processes, memory can be reserved as swap only if availrmem 124*7c478bd9Sstevel@tonic-gate * doesn't fall below (swapfs_minfree + swapfs_reserve). Thus, 125*7c478bd9Sstevel@tonic-gate * swapfs_reserve amount of memswap is not available to non-priv 126*7c478bd9Sstevel@tonic-gate * processes. This protects daemons such as automounter dying 127*7c478bd9Sstevel@tonic-gate * as a result of application processes eating away almost entire 128*7c478bd9Sstevel@tonic-gate * membased swap. This safeguard becomes useless if apps are run 129*7c478bd9Sstevel@tonic-gate * with root access. 130*7c478bd9Sstevel@tonic-gate * 131*7c478bd9Sstevel@tonic-gate * set swapfs_reserve to a minimum of 4Mb or 1/128 of physmem whichever 132*7c478bd9Sstevel@tonic-gate * is greater up to the limit of 128 MB. 133*7c478bd9Sstevel@tonic-gate */ 134*7c478bd9Sstevel@tonic-gate if (new_swapfs_reserve == 0) 135*7c478bd9Sstevel@tonic-gate new_swapfs_reserve = MIN(btopr(128 * 1024 * 1024), 136*7c478bd9Sstevel@tonic-gate MAX(btopr(4 * 1024 * 1024), pgs >> 7)); 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate /* Test basic numeric viability. */ 139*7c478bd9Sstevel@tonic-gate if (new_swapfs_minfree > pgs) 140*7c478bd9Sstevel@tonic-gate return (0); 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate /* Equivalent test to anon_resvmem() check. */ 143*7c478bd9Sstevel@tonic-gate if (availrmem < new_swapfs_minfree) { 144*7c478bd9Sstevel@tonic-gate /* 145*7c478bd9Sstevel@tonic-gate * If ism pages are being used, then there must be agreement 146*7c478bd9Sstevel@tonic-gate * between these two policies. 147*7c478bd9Sstevel@tonic-gate */ 148*7c478bd9Sstevel@tonic-gate if ((availrmem > segspt_minfree) && (segspt_minfree > 0)) { 149*7c478bd9Sstevel@tonic-gate new_swapfs_minfree = segspt_minfree; 150*7c478bd9Sstevel@tonic-gate } else { 151*7c478bd9Sstevel@tonic-gate return (0); 152*7c478bd9Sstevel@tonic-gate } 153*7c478bd9Sstevel@tonic-gate } 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate swapfs_desfree = new_swapfs_desfree; 156*7c478bd9Sstevel@tonic-gate swapfs_minfree = new_swapfs_minfree; 157*7c478bd9Sstevel@tonic-gate swapfs_reserve = new_swapfs_reserve; 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate return (1); 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 163*7c478bd9Sstevel@tonic-gate int 164*7c478bd9Sstevel@tonic-gate swapinit(int fstype, char *name) 165*7c478bd9Sstevel@tonic-gate { /* reserve for mp */ 166*7c478bd9Sstevel@tonic-gate ssize_t sw_freelist_size = klustsize / PAGESIZE * 2; 167*7c478bd9Sstevel@tonic-gate int i, error; 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate static const fs_operation_def_t swap_vfsops[] = { 170*7c478bd9Sstevel@tonic-gate VFSNAME_SYNC, (fs_generic_func_p) swap_sync, 171*7c478bd9Sstevel@tonic-gate NULL, NULL 172*7c478bd9Sstevel@tonic-gate }; 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate SWAPFS_PRINT(SWAP_SUBR, "swapinit\n", 0, 0, 0, 0, 0); 175*7c478bd9Sstevel@tonic-gate mutex_init(&swapfs_lock, NULL, MUTEX_DEFAULT, NULL); 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate swap_vnodes = kmem_zalloc(MAX_SWAP_VNODES * sizeof (struct vnode *), 178*7c478bd9Sstevel@tonic-gate KM_SLEEP); 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate swapfs_recalc_save_initial(); 181*7c478bd9Sstevel@tonic-gate if (!swapfs_recalc(physmem)) 182*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "swapfs_minfree(%lu) > physmem(%lu)", 183*7c478bd9Sstevel@tonic-gate swapfs_minfree, physmem); 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* 186*7c478bd9Sstevel@tonic-gate * Arrange for a callback on memory size change. 187*7c478bd9Sstevel@tonic-gate */ 188*7c478bd9Sstevel@tonic-gate swap_init_mem_config(); 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate sw_ar = (struct async_reqs *) 191*7c478bd9Sstevel@tonic-gate kmem_zalloc(sw_freelist_size*sizeof (struct async_reqs), KM_SLEEP); 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate error = vfs_setfsops(fstype, swap_vfsops, NULL); 194*7c478bd9Sstevel@tonic-gate if (error != 0) { 195*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "swapinit: bad vfs ops template"); 196*7c478bd9Sstevel@tonic-gate return (error); 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate error = vn_make_ops(name, swap_vnodeops_template, &swap_vnodeops); 200*7c478bd9Sstevel@tonic-gate if (error != 0) { 201*7c478bd9Sstevel@tonic-gate (void) vfs_freevfsops_by_type(fstype); 202*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "swapinit: bad vnode ops template"); 203*7c478bd9Sstevel@tonic-gate return (error); 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate sw_freelist = sw_ar; 206*7c478bd9Sstevel@tonic-gate for (i = 0; i < sw_freelist_size - 1; i++) 207*7c478bd9Sstevel@tonic-gate sw_ar[i].a_next = &sw_ar[i + 1]; 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate return (0); 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate /* 213*7c478bd9Sstevel@tonic-gate * Get a swapfs vnode corresponding to the specified identifier. 214*7c478bd9Sstevel@tonic-gate */ 215*7c478bd9Sstevel@tonic-gate struct vnode * 216*7c478bd9Sstevel@tonic-gate swapfs_getvp(ulong_t vidx) 217*7c478bd9Sstevel@tonic-gate { 218*7c478bd9Sstevel@tonic-gate struct vnode *vp; 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate vp = swap_vnodes[vidx]; 221*7c478bd9Sstevel@tonic-gate if (vp) { 222*7c478bd9Sstevel@tonic-gate return (vp); 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate mutex_enter(&swapfs_lock); 226*7c478bd9Sstevel@tonic-gate vp = swap_vnodes[vidx]; 227*7c478bd9Sstevel@tonic-gate if (vp == NULL) { 228*7c478bd9Sstevel@tonic-gate vp = vn_alloc(KM_SLEEP); 229*7c478bd9Sstevel@tonic-gate vn_setops(vp, swap_vnodeops); 230*7c478bd9Sstevel@tonic-gate vp->v_type = VREG; 231*7c478bd9Sstevel@tonic-gate vp->v_flag |= (VISSWAP|VISSWAPFS); 232*7c478bd9Sstevel@tonic-gate swap_vnodes[vidx] = vp; 233*7c478bd9Sstevel@tonic-gate swapfs_vpcount++; 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate mutex_exit(&swapfs_lock); 236*7c478bd9Sstevel@tonic-gate return (vp); 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate int swap_lo; 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 242*7c478bd9Sstevel@tonic-gate static int 243*7c478bd9Sstevel@tonic-gate swap_sync(struct vfs *vfsp, short flag, struct cred *cr) 244*7c478bd9Sstevel@tonic-gate { 245*7c478bd9Sstevel@tonic-gate struct vnode *vp; 246*7c478bd9Sstevel@tonic-gate int i; 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate if (!(flag & SYNC_ALL)) 249*7c478bd9Sstevel@tonic-gate return (1); 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate /* 252*7c478bd9Sstevel@tonic-gate * assumes that we are the only one left to access this so that 253*7c478bd9Sstevel@tonic-gate * no need to use swapfs_lock (since it's staticly defined) 254*7c478bd9Sstevel@tonic-gate */ 255*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAX_SWAP_VNODES; i++) { 256*7c478bd9Sstevel@tonic-gate vp = swap_vnodes[i]; 257*7c478bd9Sstevel@tonic-gate if (vp) { 258*7c478bd9Sstevel@tonic-gate VN_HOLD(vp); 259*7c478bd9Sstevel@tonic-gate (void) VOP_PUTPAGE(vp, (offset_t)0, 0, 260*7c478bd9Sstevel@tonic-gate (B_ASYNC | B_FREE), kcred); 261*7c478bd9Sstevel@tonic-gate VN_RELE(vp); 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate return (0); 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate extern int sw_pending_size; 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate /* 270*7c478bd9Sstevel@tonic-gate * Take an async request off the pending queue 271*7c478bd9Sstevel@tonic-gate */ 272*7c478bd9Sstevel@tonic-gate struct async_reqs * 273*7c478bd9Sstevel@tonic-gate sw_getreq() 274*7c478bd9Sstevel@tonic-gate { 275*7c478bd9Sstevel@tonic-gate struct async_reqs *arg; 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate mutex_enter(&swapfs_lock); 278*7c478bd9Sstevel@tonic-gate arg = sw_pendlist; 279*7c478bd9Sstevel@tonic-gate if (arg) { 280*7c478bd9Sstevel@tonic-gate sw_pendlist = arg->a_next; 281*7c478bd9Sstevel@tonic-gate arg->a_next = NULL; 282*7c478bd9Sstevel@tonic-gate sw_pending_size -= PAGESIZE; 283*7c478bd9Sstevel@tonic-gate } 284*7c478bd9Sstevel@tonic-gate ASSERT(sw_pending_size >= 0); 285*7c478bd9Sstevel@tonic-gate mutex_exit(&swapfs_lock); 286*7c478bd9Sstevel@tonic-gate return (arg); 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate /* 290*7c478bd9Sstevel@tonic-gate * Put an async request on the pending queue 291*7c478bd9Sstevel@tonic-gate */ 292*7c478bd9Sstevel@tonic-gate void 293*7c478bd9Sstevel@tonic-gate sw_putreq(struct async_reqs *arg) 294*7c478bd9Sstevel@tonic-gate { 295*7c478bd9Sstevel@tonic-gate /* Hold onto it */ 296*7c478bd9Sstevel@tonic-gate VN_HOLD(arg->a_vp); 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate mutex_enter(&swapfs_lock); 299*7c478bd9Sstevel@tonic-gate arg->a_next = sw_pendlist; 300*7c478bd9Sstevel@tonic-gate sw_pendlist = arg; 301*7c478bd9Sstevel@tonic-gate sw_pending_size += PAGESIZE; 302*7c478bd9Sstevel@tonic-gate mutex_exit(&swapfs_lock); 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate /* 306*7c478bd9Sstevel@tonic-gate * Put an async request back on the pending queue 307*7c478bd9Sstevel@tonic-gate */ 308*7c478bd9Sstevel@tonic-gate void 309*7c478bd9Sstevel@tonic-gate sw_putbackreq(struct async_reqs *arg) 310*7c478bd9Sstevel@tonic-gate { 311*7c478bd9Sstevel@tonic-gate mutex_enter(&swapfs_lock); 312*7c478bd9Sstevel@tonic-gate arg->a_next = sw_pendlist; 313*7c478bd9Sstevel@tonic-gate sw_pendlist = arg; 314*7c478bd9Sstevel@tonic-gate sw_pending_size += PAGESIZE; 315*7c478bd9Sstevel@tonic-gate mutex_exit(&swapfs_lock); 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate /* 319*7c478bd9Sstevel@tonic-gate * Take an async request structure off the free list 320*7c478bd9Sstevel@tonic-gate */ 321*7c478bd9Sstevel@tonic-gate struct async_reqs * 322*7c478bd9Sstevel@tonic-gate sw_getfree() 323*7c478bd9Sstevel@tonic-gate { 324*7c478bd9Sstevel@tonic-gate struct async_reqs *arg; 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate mutex_enter(&swapfs_lock); 327*7c478bd9Sstevel@tonic-gate arg = sw_freelist; 328*7c478bd9Sstevel@tonic-gate if (arg) { 329*7c478bd9Sstevel@tonic-gate sw_freelist = arg->a_next; 330*7c478bd9Sstevel@tonic-gate arg->a_next = NULL; 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate mutex_exit(&swapfs_lock); 333*7c478bd9Sstevel@tonic-gate return (arg); 334*7c478bd9Sstevel@tonic-gate } 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate /* 337*7c478bd9Sstevel@tonic-gate * Put an async request structure on the free list 338*7c478bd9Sstevel@tonic-gate */ 339*7c478bd9Sstevel@tonic-gate void 340*7c478bd9Sstevel@tonic-gate sw_putfree(struct async_reqs *arg) 341*7c478bd9Sstevel@tonic-gate { 342*7c478bd9Sstevel@tonic-gate /* Release our hold - should have locked the page by now */ 343*7c478bd9Sstevel@tonic-gate VN_RELE(arg->a_vp); 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate mutex_enter(&swapfs_lock); 346*7c478bd9Sstevel@tonic-gate arg->a_next = sw_freelist; 347*7c478bd9Sstevel@tonic-gate sw_freelist = arg; 348*7c478bd9Sstevel@tonic-gate mutex_exit(&swapfs_lock); 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate static pgcnt_t swapfs_pending_delete; 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 354*7c478bd9Sstevel@tonic-gate static void 355*7c478bd9Sstevel@tonic-gate swap_mem_config_post_add( 356*7c478bd9Sstevel@tonic-gate void *arg, 357*7c478bd9Sstevel@tonic-gate pgcnt_t delta_swaps) 358*7c478bd9Sstevel@tonic-gate { 359*7c478bd9Sstevel@tonic-gate (void) swapfs_recalc(physmem - swapfs_pending_delete); 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 363*7c478bd9Sstevel@tonic-gate static int 364*7c478bd9Sstevel@tonic-gate swap_mem_config_pre_del( 365*7c478bd9Sstevel@tonic-gate void *arg, 366*7c478bd9Sstevel@tonic-gate pgcnt_t delta_swaps) 367*7c478bd9Sstevel@tonic-gate { 368*7c478bd9Sstevel@tonic-gate pgcnt_t nv; 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate nv = atomic_add_long_nv(&swapfs_pending_delete, (spgcnt_t)delta_swaps); 371*7c478bd9Sstevel@tonic-gate if (!swapfs_recalc(physmem - nv)) { 372*7c478bd9Sstevel@tonic-gate /* 373*7c478bd9Sstevel@tonic-gate * Tidy-up is done by the call to post_del which 374*7c478bd9Sstevel@tonic-gate * is always made. 375*7c478bd9Sstevel@tonic-gate */ 376*7c478bd9Sstevel@tonic-gate return (EBUSY); 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate return (0); 379*7c478bd9Sstevel@tonic-gate } 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 382*7c478bd9Sstevel@tonic-gate static void 383*7c478bd9Sstevel@tonic-gate swap_mem_config_post_del( 384*7c478bd9Sstevel@tonic-gate void *arg, 385*7c478bd9Sstevel@tonic-gate pgcnt_t delta_swaps, 386*7c478bd9Sstevel@tonic-gate int cancelled) 387*7c478bd9Sstevel@tonic-gate { 388*7c478bd9Sstevel@tonic-gate pgcnt_t nv; 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate nv = atomic_add_long_nv(&swapfs_pending_delete, -(spgcnt_t)delta_swaps); 391*7c478bd9Sstevel@tonic-gate (void) swapfs_recalc(physmem - nv); 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate static kphysm_setup_vector_t swap_mem_config_vec = { 395*7c478bd9Sstevel@tonic-gate KPHYSM_SETUP_VECTOR_VERSION, 396*7c478bd9Sstevel@tonic-gate swap_mem_config_post_add, 397*7c478bd9Sstevel@tonic-gate swap_mem_config_pre_del, 398*7c478bd9Sstevel@tonic-gate swap_mem_config_post_del, 399*7c478bd9Sstevel@tonic-gate }; 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate static void 402*7c478bd9Sstevel@tonic-gate swap_init_mem_config(void) 403*7c478bd9Sstevel@tonic-gate { 404*7c478bd9Sstevel@tonic-gate int ret; 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate ret = kphysm_setup_func_register(&swap_mem_config_vec, (void *)NULL); 407*7c478bd9Sstevel@tonic-gate ASSERT(ret == 0); 408*7c478bd9Sstevel@tonic-gate } 409