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