145749Smckusick /* 245749Smckusick * Copyright (c) 1990 University of Utah. 363379Sbostic * Copyright (c) 1991, 1993 463379Sbostic * The Regents of the University of California. All rights reserved. 545749Smckusick * 645749Smckusick * This code is derived from software contributed to Berkeley by 745749Smckusick * the Systems Programming Group of the University of Utah Computer 845749Smckusick * Science Department. 945749Smckusick * 1045749Smckusick * %sccs.include.redist.c% 1145749Smckusick * 1249289Shibler * from: Utah $Hdr: swap_pager.c 1.4 91/04/30$ 1349289Shibler * 14*65682Shibler * @(#)swap_pager.c 8.6 (Berkeley) 01/12/94 1545749Smckusick */ 1645749Smckusick 1745749Smckusick /* 1845749Smckusick * Quick hack to page to dedicated partition(s). 1945749Smckusick * TODO: 2045749Smckusick * Add multiprocessor locks 2145749Smckusick * Deal with async writes in a better fashion 2245749Smckusick */ 2345749Smckusick 2453341Sbostic #include <sys/param.h> 2553341Sbostic #include <sys/systm.h> 2653341Sbostic #include <sys/proc.h> 2753341Sbostic #include <sys/buf.h> 2853341Sbostic #include <sys/map.h> 2953496Sheideman #include <sys/vnode.h> 3053341Sbostic #include <sys/malloc.h> 3145749Smckusick 3255051Spendry #include <miscfs/specfs/specdev.h> 3355051Spendry 3453341Sbostic #include <vm/vm.h> 3553341Sbostic #include <vm/vm_page.h> 3653341Sbostic #include <vm/vm_pageout.h> 3753341Sbostic #include <vm/swap_pager.h> 3845749Smckusick 3945749Smckusick #define NSWSIZES 16 /* size of swtab */ 40*65682Shibler #define MAXDADDRS 64 /* max # of disk addrs for fixed allocations */ 41*65682Shibler #ifndef NPENDINGIO 4245749Smckusick #define NPENDINGIO 64 /* max # of pending cleans */ 43*65682Shibler #endif 4445749Smckusick 4545749Smckusick #ifdef DEBUG 4645749Smckusick int swpagerdebug = 0x100; 4745749Smckusick #define SDB_FOLLOW 0x001 4845749Smckusick #define SDB_INIT 0x002 4945749Smckusick #define SDB_ALLOC 0x004 5045749Smckusick #define SDB_IO 0x008 5145749Smckusick #define SDB_WRITE 0x010 5245749Smckusick #define SDB_FAIL 0x020 5345749Smckusick #define SDB_ALLOCBLK 0x040 5445749Smckusick #define SDB_FULL 0x080 5545749Smckusick #define SDB_ANOM 0x100 5645749Smckusick #define SDB_ANOMPANIC 0x200 57*65682Shibler #define SDB_CLUSTER 0x400 58*65682Shibler #define SDB_PARANOIA 0x800 5945749Smckusick #endif 6045749Smckusick 6165231Smckusick TAILQ_HEAD(swpclean, swpagerclean); 6265231Smckusick 6345749Smckusick struct swpagerclean { 6465231Smckusick TAILQ_ENTRY(swpagerclean) spc_list; 6565231Smckusick int spc_flags; 6665231Smckusick struct buf *spc_bp; 6765231Smckusick sw_pager_t spc_swp; 6865231Smckusick vm_offset_t spc_kva; 6965231Smckusick vm_page_t spc_m; 70*65682Shibler int spc_npages; 7145749Smckusick } swcleanlist[NPENDINGIO]; 7253341Sbostic typedef struct swpagerclean *swp_clean_t; 7345749Smckusick 7445749Smckusick /* spc_flags values */ 7545749Smckusick #define SPC_FREE 0x00 7645749Smckusick #define SPC_BUSY 0x01 7745749Smckusick #define SPC_DONE 0x02 7845749Smckusick #define SPC_ERROR 0x04 7945749Smckusick 8045749Smckusick struct swtab { 8145749Smckusick vm_size_t st_osize; /* size of object (bytes) */ 8245749Smckusick int st_bsize; /* vs. size of swap block (DEV_BSIZE units) */ 8345749Smckusick #ifdef DEBUG 8445749Smckusick u_long st_inuse; /* number in this range in use */ 8545749Smckusick u_long st_usecnt; /* total used of this size */ 8645749Smckusick #endif 8745749Smckusick } swtab[NSWSIZES+1]; 8845749Smckusick 8945749Smckusick #ifdef DEBUG 9045749Smckusick int swap_pager_poip; /* pageouts in progress */ 9145749Smckusick int swap_pager_piip; /* pageins in progress */ 9245749Smckusick #endif 9345749Smckusick 94*65682Shibler int swap_pager_maxcluster; /* maximum cluster size */ 95*65682Shibler int swap_pager_npendingio; /* number of pager clean structs */ 96*65682Shibler 9765231Smckusick struct swpclean swap_pager_inuse; /* list of pending page cleans */ 9865231Smckusick struct swpclean swap_pager_free; /* list of free pager clean structs */ 9965231Smckusick struct pagerlst swap_pager_list; /* list of "named" anon regions */ 10045749Smckusick 10153341Sbostic static int swap_pager_finish __P((swp_clean_t)); 10253341Sbostic static void swap_pager_init __P((void)); 10364827Storek static vm_pager_t swap_pager_alloc 10464827Storek __P((caddr_t, vm_size_t, vm_prot_t, vm_offset_t)); 105*65682Shibler static void swap_pager_clean __P((int)); 106*65682Shibler #ifdef DEBUG 107*65682Shibler static void swap_pager_clean_check __P((vm_page_t *, int, int)); 108*65682Shibler #endif 109*65682Shibler static void swap_pager_cluster 110*65682Shibler __P((vm_pager_t, vm_offset_t, 111*65682Shibler vm_offset_t *, vm_offset_t *)); 11253341Sbostic static void swap_pager_dealloc __P((vm_pager_t)); 11353341Sbostic static int swap_pager_getpage 114*65682Shibler __P((vm_pager_t, vm_page_t *, int, boolean_t)); 11553341Sbostic static boolean_t swap_pager_haspage __P((vm_pager_t, vm_offset_t)); 116*65682Shibler static int swap_pager_io __P((sw_pager_t, vm_page_t *, int, int)); 11753341Sbostic static void swap_pager_iodone __P((struct buf *)); 11853341Sbostic static int swap_pager_putpage 119*65682Shibler __P((vm_pager_t, vm_page_t *, int, boolean_t)); 12053341Sbostic 12153341Sbostic struct pagerops swappagerops = { 12253341Sbostic swap_pager_init, 12353341Sbostic swap_pager_alloc, 12453341Sbostic swap_pager_dealloc, 12553341Sbostic swap_pager_getpage, 12653341Sbostic swap_pager_putpage, 127*65682Shibler swap_pager_haspage, 128*65682Shibler swap_pager_cluster 12953341Sbostic }; 13053341Sbostic 13153341Sbostic static void 13245749Smckusick swap_pager_init() 13345749Smckusick { 13445749Smckusick register swp_clean_t spc; 13545749Smckusick register int i, bsize; 13645749Smckusick extern int dmmin, dmmax; 13745749Smckusick int maxbsize; 13845749Smckusick 13945749Smckusick #ifdef DEBUG 14045749Smckusick if (swpagerdebug & (SDB_FOLLOW|SDB_INIT)) 14145749Smckusick printf("swpg_init()\n"); 14245749Smckusick #endif 14345749Smckusick dfltpagerops = &swappagerops; 14465231Smckusick TAILQ_INIT(&swap_pager_list); 14545749Smckusick 14645749Smckusick /* 147*65682Shibler * Allocate async IO structures. 148*65682Shibler * 149*65682Shibler * XXX it would be nice if we could do this dynamically based on 150*65682Shibler * the value of nswbuf (since we are ultimately limited by that) 151*65682Shibler * but neither nswbuf or malloc has been initialized yet. So the 152*65682Shibler * structs are statically allocated above. 153*65682Shibler */ 154*65682Shibler swap_pager_npendingio = NPENDINGIO; 155*65682Shibler 156*65682Shibler /* 15745749Smckusick * Initialize clean lists 15845749Smckusick */ 15965231Smckusick TAILQ_INIT(&swap_pager_inuse); 16065231Smckusick TAILQ_INIT(&swap_pager_free); 161*65682Shibler for (i = 0, spc = swcleanlist; i < swap_pager_npendingio; i++, spc++) { 16265231Smckusick TAILQ_INSERT_TAIL(&swap_pager_free, spc, spc_list); 16345749Smckusick spc->spc_flags = SPC_FREE; 16445749Smckusick } 16545749Smckusick 16645749Smckusick /* 16745749Smckusick * Calculate the swap allocation constants. 16845749Smckusick */ 16945749Smckusick if (dmmin == 0) { 17045749Smckusick dmmin = DMMIN; 17145749Smckusick if (dmmin < CLBYTES/DEV_BSIZE) 17245749Smckusick dmmin = CLBYTES/DEV_BSIZE; 17345749Smckusick } 17445749Smckusick if (dmmax == 0) 17545749Smckusick dmmax = DMMAX; 17645749Smckusick 17745749Smckusick /* 17845749Smckusick * Fill in our table of object size vs. allocation size 17945749Smckusick */ 18045749Smckusick bsize = btodb(PAGE_SIZE); 18145749Smckusick if (bsize < dmmin) 18245749Smckusick bsize = dmmin; 18345749Smckusick maxbsize = btodb(sizeof(sw_bm_t) * NBBY * PAGE_SIZE); 18445749Smckusick if (maxbsize > dmmax) 18545749Smckusick maxbsize = dmmax; 18645749Smckusick for (i = 0; i < NSWSIZES; i++) { 18745749Smckusick swtab[i].st_osize = (vm_size_t) (MAXDADDRS * dbtob(bsize)); 18845749Smckusick swtab[i].st_bsize = bsize; 189*65682Shibler if (bsize <= btodb(MAXPHYS)) 190*65682Shibler swap_pager_maxcluster = dbtob(bsize); 19145749Smckusick #ifdef DEBUG 19245749Smckusick if (swpagerdebug & SDB_INIT) 19345749Smckusick printf("swpg_init: ix %d, size %x, bsize %x\n", 19445749Smckusick i, swtab[i].st_osize, swtab[i].st_bsize); 19545749Smckusick #endif 19645749Smckusick if (bsize >= maxbsize) 19745749Smckusick break; 19845749Smckusick bsize *= 2; 19945749Smckusick } 20045749Smckusick swtab[i].st_osize = 0; 20145749Smckusick swtab[i].st_bsize = bsize; 20245749Smckusick } 20345749Smckusick 20445749Smckusick /* 20545749Smckusick * Allocate a pager structure and associated resources. 20645749Smckusick * Note that if we are called from the pageout daemon (handle == NULL) 20745749Smckusick * we should not wait for memory as it could resulting in deadlock. 20845749Smckusick */ 20953341Sbostic static vm_pager_t 21064827Storek swap_pager_alloc(handle, size, prot, foff) 21145749Smckusick caddr_t handle; 21245749Smckusick register vm_size_t size; 21345749Smckusick vm_prot_t prot; 21464827Storek vm_offset_t foff; 21545749Smckusick { 21645749Smckusick register vm_pager_t pager; 21745749Smckusick register sw_pager_t swp; 21845749Smckusick struct swtab *swt; 21945749Smckusick int waitok; 22045749Smckusick 22145749Smckusick #ifdef DEBUG 22245749Smckusick if (swpagerdebug & (SDB_FOLLOW|SDB_ALLOC)) 22345749Smckusick printf("swpg_alloc(%x, %x, %x)\n", handle, size, prot); 22445749Smckusick #endif 22545749Smckusick /* 22645749Smckusick * If this is a "named" anonymous region, look it up and 22745749Smckusick * return the appropriate pager if it exists. 22845749Smckusick */ 22945749Smckusick if (handle) { 23045749Smckusick pager = vm_pager_lookup(&swap_pager_list, handle); 23148386Skarels if (pager != NULL) { 23245749Smckusick /* 23345749Smckusick * Use vm_object_lookup to gain a reference 23445749Smckusick * to the object and also to remove from the 23545749Smckusick * object cache. 23645749Smckusick */ 23748386Skarels if (vm_object_lookup(pager) == NULL) 23845749Smckusick panic("swap_pager_alloc: bad object"); 23945749Smckusick return(pager); 24045749Smckusick } 24145749Smckusick } 24245749Smckusick /* 24345749Smckusick * Pager doesn't exist, allocate swap management resources 24445749Smckusick * and initialize. 24545749Smckusick */ 24645749Smckusick waitok = handle ? M_WAITOK : M_NOWAIT; 24745749Smckusick pager = (vm_pager_t)malloc(sizeof *pager, M_VMPAGER, waitok); 24848386Skarels if (pager == NULL) 24948386Skarels return(NULL); 25045749Smckusick swp = (sw_pager_t)malloc(sizeof *swp, M_VMPGDATA, waitok); 25145749Smckusick if (swp == NULL) { 25245749Smckusick #ifdef DEBUG 25345749Smckusick if (swpagerdebug & SDB_FAIL) 25445749Smckusick printf("swpg_alloc: swpager malloc failed\n"); 25545749Smckusick #endif 25645749Smckusick free((caddr_t)pager, M_VMPAGER); 25748386Skarels return(NULL); 25845749Smckusick } 25945749Smckusick size = round_page(size); 26045749Smckusick for (swt = swtab; swt->st_osize; swt++) 26145749Smckusick if (size <= swt->st_osize) 26245749Smckusick break; 26345749Smckusick #ifdef DEBUG 26445749Smckusick swt->st_inuse++; 26545749Smckusick swt->st_usecnt++; 26645749Smckusick #endif 26745749Smckusick swp->sw_osize = size; 26845749Smckusick swp->sw_bsize = swt->st_bsize; 26945749Smckusick swp->sw_nblocks = (btodb(size) + swp->sw_bsize - 1) / swp->sw_bsize; 27045749Smckusick swp->sw_blocks = (sw_blk_t) 27145749Smckusick malloc(swp->sw_nblocks*sizeof(*swp->sw_blocks), 27245749Smckusick M_VMPGDATA, M_NOWAIT); 27345749Smckusick if (swp->sw_blocks == NULL) { 27445749Smckusick free((caddr_t)swp, M_VMPGDATA); 27545749Smckusick free((caddr_t)pager, M_VMPAGER); 27645749Smckusick #ifdef DEBUG 27745749Smckusick if (swpagerdebug & SDB_FAIL) 27845749Smckusick printf("swpg_alloc: sw_blocks malloc failed\n"); 27945749Smckusick swt->st_inuse--; 28045749Smckusick swt->st_usecnt--; 28145749Smckusick #endif 28245749Smckusick return(FALSE); 28345749Smckusick } 28445749Smckusick bzero((caddr_t)swp->sw_blocks, 28545749Smckusick swp->sw_nblocks * sizeof(*swp->sw_blocks)); 28645749Smckusick swp->sw_poip = 0; 28745749Smckusick if (handle) { 28845749Smckusick vm_object_t object; 28945749Smckusick 29045749Smckusick swp->sw_flags = SW_NAMED; 29165231Smckusick TAILQ_INSERT_TAIL(&swap_pager_list, pager, pg_list); 29245749Smckusick /* 29345749Smckusick * Consistant with other pagers: return with object 29445749Smckusick * referenced. Can't do this with handle == NULL 29545749Smckusick * since it might be the pageout daemon calling. 29645749Smckusick */ 29745749Smckusick object = vm_object_allocate(size); 29845749Smckusick vm_object_enter(object, pager); 29945749Smckusick vm_object_setpager(object, pager, 0, FALSE); 30045749Smckusick } else { 30145749Smckusick swp->sw_flags = 0; 30265231Smckusick pager->pg_list.tqe_next = NULL; 30365231Smckusick pager->pg_list.tqe_prev = NULL; 30445749Smckusick } 30545749Smckusick pager->pg_handle = handle; 30645749Smckusick pager->pg_ops = &swappagerops; 30745749Smckusick pager->pg_type = PG_SWAP; 308*65682Shibler pager->pg_flags = PG_CLUSTERPUT; 30964860Shibler pager->pg_data = swp; 31045749Smckusick 31145749Smckusick #ifdef DEBUG 31245749Smckusick if (swpagerdebug & SDB_ALLOC) 31345749Smckusick printf("swpg_alloc: pg_data %x, %x of %x at %x\n", 31445749Smckusick swp, swp->sw_nblocks, swp->sw_bsize, swp->sw_blocks); 31545749Smckusick #endif 31645749Smckusick return(pager); 31745749Smckusick } 31845749Smckusick 31953341Sbostic static void 32045749Smckusick swap_pager_dealloc(pager) 32145749Smckusick vm_pager_t pager; 32245749Smckusick { 32345749Smckusick register int i; 32445749Smckusick register sw_blk_t bp; 32545749Smckusick register sw_pager_t swp; 32645749Smckusick struct swtab *swt; 32745749Smckusick int s; 32845749Smckusick 32945749Smckusick #ifdef DEBUG 33045749Smckusick /* save panic time state */ 33145749Smckusick if ((swpagerdebug & SDB_ANOMPANIC) && panicstr) 33245749Smckusick return; 33345749Smckusick if (swpagerdebug & (SDB_FOLLOW|SDB_ALLOC)) 33445749Smckusick printf("swpg_dealloc(%x)\n", pager); 33545749Smckusick #endif 33645749Smckusick /* 33745749Smckusick * Remove from list right away so lookups will fail if we 33845749Smckusick * block for pageout completion. 33945749Smckusick */ 34045749Smckusick swp = (sw_pager_t) pager->pg_data; 34145749Smckusick if (swp->sw_flags & SW_NAMED) { 34265231Smckusick TAILQ_REMOVE(&swap_pager_list, pager, pg_list); 34345749Smckusick swp->sw_flags &= ~SW_NAMED; 34445749Smckusick } 34545749Smckusick #ifdef DEBUG 34645749Smckusick for (swt = swtab; swt->st_osize; swt++) 34745749Smckusick if (swp->sw_osize <= swt->st_osize) 34845749Smckusick break; 34945749Smckusick swt->st_inuse--; 35045749Smckusick #endif 35145749Smckusick 35245749Smckusick /* 35345749Smckusick * Wait for all pageouts to finish and remove 35445749Smckusick * all entries from cleaning list. 35545749Smckusick */ 35645749Smckusick s = splbio(); 35745749Smckusick while (swp->sw_poip) { 35845749Smckusick swp->sw_flags |= SW_WANTED; 359*65682Shibler (void) tsleep(swp, PVM, "swpgdealloc", 0); 36045749Smckusick } 36145749Smckusick splx(s); 362*65682Shibler swap_pager_clean(B_WRITE); 36345749Smckusick 36445749Smckusick /* 36545749Smckusick * Free left over swap blocks 36645749Smckusick */ 36745749Smckusick for (i = 0, bp = swp->sw_blocks; i < swp->sw_nblocks; i++, bp++) 36845749Smckusick if (bp->swb_block) { 36945749Smckusick #ifdef DEBUG 37045749Smckusick if (swpagerdebug & (SDB_ALLOCBLK|SDB_FULL)) 37145749Smckusick printf("swpg_dealloc: blk %x\n", 37245749Smckusick bp->swb_block); 37345749Smckusick #endif 37445749Smckusick rmfree(swapmap, swp->sw_bsize, bp->swb_block); 37545749Smckusick } 37645749Smckusick /* 37745749Smckusick * Free swap management resources 37845749Smckusick */ 37945749Smckusick free((caddr_t)swp->sw_blocks, M_VMPGDATA); 38045749Smckusick free((caddr_t)swp, M_VMPGDATA); 38145749Smckusick free((caddr_t)pager, M_VMPAGER); 38245749Smckusick } 38345749Smckusick 38453341Sbostic static int 385*65682Shibler swap_pager_getpage(pager, mlist, npages, sync) 38645749Smckusick vm_pager_t pager; 387*65682Shibler vm_page_t *mlist; 388*65682Shibler int npages; 38945749Smckusick boolean_t sync; 39045749Smckusick { 39145749Smckusick #ifdef DEBUG 39245749Smckusick if (swpagerdebug & SDB_FOLLOW) 393*65682Shibler printf("swpg_getpage(%x, %x, %x, %x)\n", 394*65682Shibler pager, mlist, npages, sync); 39545749Smckusick #endif 396*65682Shibler return(swap_pager_io((sw_pager_t)pager->pg_data, 397*65682Shibler mlist, npages, B_READ)); 39845749Smckusick } 39945749Smckusick 40053341Sbostic static int 401*65682Shibler swap_pager_putpage(pager, mlist, npages, sync) 40245749Smckusick vm_pager_t pager; 403*65682Shibler vm_page_t *mlist; 404*65682Shibler int npages; 40545749Smckusick boolean_t sync; 40645749Smckusick { 40745749Smckusick int flags; 40845749Smckusick 40945749Smckusick #ifdef DEBUG 41045749Smckusick if (swpagerdebug & SDB_FOLLOW) 411*65682Shibler printf("swpg_putpage(%x, %x, %x, %x)\n", 412*65682Shibler pager, mlist, npages, sync); 41345749Smckusick #endif 41448386Skarels if (pager == NULL) { 415*65682Shibler swap_pager_clean(B_WRITE); 41654817Storek return (VM_PAGER_OK); /* ??? */ 41745749Smckusick } 41845749Smckusick flags = B_WRITE; 41945749Smckusick if (!sync) 42045749Smckusick flags |= B_ASYNC; 421*65682Shibler return(swap_pager_io((sw_pager_t)pager->pg_data, 422*65682Shibler mlist, npages, flags)); 42345749Smckusick } 42445749Smckusick 42553341Sbostic static boolean_t 42645749Smckusick swap_pager_haspage(pager, offset) 42745749Smckusick vm_pager_t pager; 42845749Smckusick vm_offset_t offset; 42945749Smckusick { 43045749Smckusick register sw_pager_t swp; 43145749Smckusick register sw_blk_t swb; 43245749Smckusick int ix; 43345749Smckusick 43445749Smckusick #ifdef DEBUG 43545749Smckusick if (swpagerdebug & (SDB_FOLLOW|SDB_ALLOCBLK)) 43645749Smckusick printf("swpg_haspage(%x, %x) ", pager, offset); 43745749Smckusick #endif 43845749Smckusick swp = (sw_pager_t) pager->pg_data; 43945749Smckusick ix = offset / dbtob(swp->sw_bsize); 44045749Smckusick if (swp->sw_blocks == NULL || ix >= swp->sw_nblocks) { 44145749Smckusick #ifdef DEBUG 44245749Smckusick if (swpagerdebug & (SDB_FAIL|SDB_FOLLOW|SDB_ALLOCBLK)) 44345749Smckusick printf("swpg_haspage: %x bad offset %x, ix %x\n", 44445749Smckusick swp->sw_blocks, offset, ix); 44545749Smckusick #endif 44645749Smckusick return(FALSE); 44745749Smckusick } 44845749Smckusick swb = &swp->sw_blocks[ix]; 44945749Smckusick if (swb->swb_block) 45045749Smckusick ix = atop(offset % dbtob(swp->sw_bsize)); 45145749Smckusick #ifdef DEBUG 45245749Smckusick if (swpagerdebug & SDB_ALLOCBLK) 45345749Smckusick printf("%x blk %x+%x ", swp->sw_blocks, swb->swb_block, ix); 45445749Smckusick if (swpagerdebug & (SDB_FOLLOW|SDB_ALLOCBLK)) 45545749Smckusick printf("-> %c\n", 45645749Smckusick "FT"[swb->swb_block && (swb->swb_mask & (1 << ix))]); 45745749Smckusick #endif 45845749Smckusick if (swb->swb_block && (swb->swb_mask & (1 << ix))) 45945749Smckusick return(TRUE); 46045749Smckusick return(FALSE); 46145749Smckusick } 46245749Smckusick 463*65682Shibler static void 464*65682Shibler swap_pager_cluster(pager, offset, loffset, hoffset) 465*65682Shibler vm_pager_t pager; 466*65682Shibler vm_offset_t offset; 467*65682Shibler vm_offset_t *loffset; 468*65682Shibler vm_offset_t *hoffset; 469*65682Shibler { 470*65682Shibler sw_pager_t swp; 471*65682Shibler register int bsize; 472*65682Shibler vm_offset_t loff, hoff; 473*65682Shibler 474*65682Shibler #ifdef DEBUG 475*65682Shibler if (swpagerdebug & (SDB_FOLLOW|SDB_CLUSTER)) 476*65682Shibler printf("swpg_cluster(%x, %x) ", pager, offset); 477*65682Shibler #endif 478*65682Shibler swp = (sw_pager_t) pager->pg_data; 479*65682Shibler bsize = dbtob(swp->sw_bsize); 480*65682Shibler if (bsize > swap_pager_maxcluster) 481*65682Shibler bsize = swap_pager_maxcluster; 482*65682Shibler 483*65682Shibler loff = offset - (offset % bsize); 484*65682Shibler if (loff >= swp->sw_osize) 485*65682Shibler panic("swap_pager_cluster: bad offset"); 486*65682Shibler 487*65682Shibler hoff = loff + bsize; 488*65682Shibler if (hoff > swp->sw_osize) 489*65682Shibler hoff = swp->sw_osize; 490*65682Shibler 491*65682Shibler *loffset = loff; 492*65682Shibler *hoffset = hoff; 493*65682Shibler #ifdef DEBUG 494*65682Shibler if (swpagerdebug & (SDB_FOLLOW|SDB_CLUSTER)) 495*65682Shibler printf("returns [%x-%x]\n", loff, hoff); 496*65682Shibler #endif 497*65682Shibler } 498*65682Shibler 49945749Smckusick /* 50045749Smckusick * Scaled down version of swap(). 50145749Smckusick * Assumes that PAGE_SIZE < MAXPHYS; i.e. only one operation needed. 50245749Smckusick * BOGUS: lower level IO routines expect a KVA so we have to map our 50345749Smckusick * provided physical page into the KVA to keep them happy. 50445749Smckusick */ 50553341Sbostic static int 506*65682Shibler swap_pager_io(swp, mlist, npages, flags) 50745749Smckusick register sw_pager_t swp; 508*65682Shibler vm_page_t *mlist; 509*65682Shibler int npages; 51045749Smckusick int flags; 51145749Smckusick { 51245749Smckusick register struct buf *bp; 51345749Smckusick register sw_blk_t swb; 51445749Smckusick register int s; 515*65682Shibler int ix, mask; 51645749Smckusick boolean_t rv; 51745749Smckusick vm_offset_t kva, off; 51845749Smckusick swp_clean_t spc; 519*65682Shibler vm_page_t m; 52045749Smckusick 52145749Smckusick #ifdef DEBUG 52245749Smckusick /* save panic time state */ 52345749Smckusick if ((swpagerdebug & SDB_ANOMPANIC) && panicstr) 52453341Sbostic return (VM_PAGER_FAIL); /* XXX: correct return? */ 52545749Smckusick if (swpagerdebug & (SDB_FOLLOW|SDB_IO)) 526*65682Shibler printf("swpg_io(%x, %x, %x, %x)\n", swp, mlist, npages, flags); 527*65682Shibler if (flags & B_READ) { 528*65682Shibler if (flags & B_ASYNC) 529*65682Shibler panic("swap_pager_io: cannot do ASYNC reads"); 530*65682Shibler if (npages != 1) 531*65682Shibler panic("swap_pager_io: cannot do clustered reads"); 532*65682Shibler } 53345749Smckusick #endif 53445749Smckusick 53545749Smckusick /* 53664860Shibler * First determine if the page exists in the pager if this is 53764860Shibler * a sync read. This quickly handles cases where we are 53864860Shibler * following shadow chains looking for the top level object 53964860Shibler * with the page. 54064860Shibler */ 541*65682Shibler m = *mlist; 54264860Shibler off = m->offset + m->object->paging_offset; 54364860Shibler ix = off / dbtob(swp->sw_bsize); 544*65682Shibler if (swp->sw_blocks == NULL || ix >= swp->sw_nblocks) { 545*65682Shibler #ifdef DEBUG 546*65682Shibler if ((flags & B_READ) == 0 && (swpagerdebug & SDB_ANOM)) { 547*65682Shibler printf("swap_pager_io: no swap block on write\n"); 548*65682Shibler return(VM_PAGER_BAD); 549*65682Shibler } 550*65682Shibler #endif 55164860Shibler return(VM_PAGER_FAIL); 552*65682Shibler } 55364860Shibler swb = &swp->sw_blocks[ix]; 55464860Shibler off = off % dbtob(swp->sw_bsize); 55564860Shibler if ((flags & B_READ) && 55664860Shibler (swb->swb_block == 0 || (swb->swb_mask & (1 << atop(off))) == 0)) 55764860Shibler return(VM_PAGER_FAIL); 55864860Shibler 55964860Shibler /* 56045749Smckusick * For reads (pageins) and synchronous writes, we clean up 56149289Shibler * all completed async pageouts. 56245749Smckusick */ 56345749Smckusick if ((flags & B_ASYNC) == 0) { 56445749Smckusick s = splbio(); 565*65682Shibler swap_pager_clean(flags&B_READ); 56649289Shibler #ifdef DEBUG 567*65682Shibler if (swpagerdebug & SDB_PARANOIA) 568*65682Shibler swap_pager_clean_check(mlist, npages, flags&B_READ); 56949289Shibler #endif 57045749Smckusick splx(s); 57145749Smckusick } 57245749Smckusick /* 57345749Smckusick * For async writes (pageouts), we cleanup completed pageouts so 57445749Smckusick * that all available resources are freed. Also tells us if this 57545749Smckusick * page is already being cleaned. If it is, or no resources 57645749Smckusick * are available, we try again later. 57745749Smckusick */ 578*65682Shibler else { 579*65682Shibler swap_pager_clean(B_WRITE); 58049289Shibler #ifdef DEBUG 581*65682Shibler if (swpagerdebug & SDB_PARANOIA) 582*65682Shibler swap_pager_clean_check(mlist, npages, B_WRITE); 58349289Shibler #endif 584*65682Shibler if (swap_pager_free.tqh_first == NULL) { 585*65682Shibler #ifdef DEBUG 586*65682Shibler if (swpagerdebug & SDB_FAIL) 587*65682Shibler printf("%s: no available io headers\n", 588*65682Shibler "swap_pager_io"); 589*65682Shibler #endif 590*65682Shibler return(VM_PAGER_AGAIN); 591*65682Shibler } 59249289Shibler } 59345749Smckusick 59445749Smckusick /* 59564860Shibler * Allocate a swap block if necessary. 59645749Smckusick */ 59764860Shibler if (swb->swb_block == 0) { 59845749Smckusick swb->swb_block = rmalloc(swapmap, swp->sw_bsize); 59945749Smckusick if (swb->swb_block == 0) { 60045749Smckusick #ifdef DEBUG 60145749Smckusick if (swpagerdebug & SDB_FAIL) 60245749Smckusick printf("swpg_io: rmalloc of %x failed\n", 60345749Smckusick swp->sw_bsize); 60445749Smckusick #endif 605*65682Shibler /* 606*65682Shibler * XXX this is technically a resource shortage that 607*65682Shibler * should return AGAIN, but the situation isn't likely 608*65682Shibler * to be remedied just by delaying a little while and 609*65682Shibler * trying again (the pageout daemon's current response 610*65682Shibler * to AGAIN) so we just return FAIL. 611*65682Shibler */ 61245749Smckusick return(VM_PAGER_FAIL); 61345749Smckusick } 61445749Smckusick #ifdef DEBUG 61545749Smckusick if (swpagerdebug & (SDB_FULL|SDB_ALLOCBLK)) 61645749Smckusick printf("swpg_io: %x alloc blk %x at ix %x\n", 61745749Smckusick swp->sw_blocks, swb->swb_block, ix); 61845749Smckusick #endif 61945749Smckusick } 62045749Smckusick 62145749Smckusick /* 62245749Smckusick * Allocate a kernel virtual address and initialize so that PTE 62345749Smckusick * is available for lower level IO drivers. 62445749Smckusick */ 625*65682Shibler kva = vm_pager_map_pages(mlist, npages, !(flags & B_ASYNC)); 626*65682Shibler if (kva == NULL) { 627*65682Shibler #ifdef DEBUG 628*65682Shibler if (swpagerdebug & SDB_FAIL) 629*65682Shibler printf("%s: no KVA space to map pages\n", 630*65682Shibler "swap_pager_io"); 631*65682Shibler #endif 632*65682Shibler return(VM_PAGER_AGAIN); 633*65682Shibler } 63445749Smckusick 63545749Smckusick /* 636*65682Shibler * Get a swap buffer header and initialize it. 63745749Smckusick */ 63845749Smckusick s = splbio(); 63956393Smckusick while (bswlist.b_actf == NULL) { 64045749Smckusick #ifdef DEBUG 64145749Smckusick if (swpagerdebug & SDB_ANOM) 64249289Shibler printf("swap_pager_io: wait on swbuf for %x (%d)\n", 64345749Smckusick m, flags); 64445749Smckusick #endif 64545749Smckusick bswlist.b_flags |= B_WANTED; 646*65682Shibler tsleep((caddr_t)&bswlist, PSWP+1, "swpgiobuf", 0); 64745749Smckusick } 64856393Smckusick bp = bswlist.b_actf; 64956393Smckusick bswlist.b_actf = bp->b_actf; 65045749Smckusick splx(s); 65145749Smckusick bp->b_flags = B_BUSY | (flags & B_READ); 65248386Skarels bp->b_proc = &proc0; /* XXX (but without B_PHYS set this is ok) */ 65364546Sbostic bp->b_data = (caddr_t)kva; 65445749Smckusick bp->b_blkno = swb->swb_block + btodb(off); 65545749Smckusick VHOLD(swapdev_vp); 65645749Smckusick bp->b_vp = swapdev_vp; 65746985Smckusick if (swapdev_vp->v_type == VBLK) 65846985Smckusick bp->b_dev = swapdev_vp->v_rdev; 659*65682Shibler bp->b_bcount = npages * PAGE_SIZE; 660*65682Shibler 661*65682Shibler /* 662*65682Shibler * For writes we set up additional buffer fields, record a pageout 663*65682Shibler * in progress and mark that these swap blocks are now allocated. 664*65682Shibler */ 66553213Smckusick if ((bp->b_flags & B_READ) == 0) { 66653213Smckusick bp->b_dirtyoff = 0; 667*65682Shibler bp->b_dirtyend = npages * PAGE_SIZE; 66845749Smckusick swapdev_vp->v_numoutput++; 669*65682Shibler s = splbio(); 670*65682Shibler swp->sw_poip++; 671*65682Shibler splx(s); 672*65682Shibler mask = (~(~0 << npages)) << atop(off); 673*65682Shibler #ifdef DEBUG 674*65682Shibler swap_pager_poip++; 675*65682Shibler if (swpagerdebug & SDB_WRITE) 676*65682Shibler printf("swpg_io: write: bp=%x swp=%x poip=%d\n", 677*65682Shibler bp, swp, swp->sw_poip); 678*65682Shibler if ((swpagerdebug & SDB_ALLOCBLK) && 679*65682Shibler (swb->swb_mask & mask) != mask) 680*65682Shibler printf("swpg_io: %x write %d pages at %x+%x\n", 681*65682Shibler swp->sw_blocks, npages, swb->swb_block, 682*65682Shibler atop(off)); 683*65682Shibler if (swpagerdebug & SDB_CLUSTER) 684*65682Shibler printf("swpg_io: off=%x, npg=%x, mask=%x, bmask=%x\n", 685*65682Shibler off, npages, mask, swb->swb_mask); 686*65682Shibler #endif 687*65682Shibler swb->swb_mask |= mask; 68853213Smckusick } 68945749Smckusick /* 690*65682Shibler * If this is an async write we set up still more buffer fields 69145749Smckusick * and place a "cleaning" entry on the inuse queue. 69245749Smckusick */ 69345749Smckusick if ((flags & (B_READ|B_ASYNC)) == B_ASYNC) { 69445749Smckusick #ifdef DEBUG 69565231Smckusick if (swap_pager_free.tqh_first == NULL) 69645749Smckusick panic("swpg_io: lost spc"); 69745749Smckusick #endif 69865231Smckusick spc = swap_pager_free.tqh_first; 69965231Smckusick TAILQ_REMOVE(&swap_pager_free, spc, spc_list); 70045749Smckusick #ifdef DEBUG 70145749Smckusick if (spc->spc_flags != SPC_FREE) 70245749Smckusick panic("swpg_io: bad free spc"); 70345749Smckusick #endif 70445749Smckusick spc->spc_flags = SPC_BUSY; 70545749Smckusick spc->spc_bp = bp; 70645749Smckusick spc->spc_swp = swp; 70745749Smckusick spc->spc_kva = kva; 708*65682Shibler /* 709*65682Shibler * Record the first page. This allows swap_pager_finish 710*65682Shibler * to efficiently handle the common case of a single page. 711*65682Shibler * For clusters, it allows us to locate the object easily 712*65682Shibler * and we then reconstruct the rest of the mlist from spc_kva. 713*65682Shibler */ 71445749Smckusick spc->spc_m = m; 715*65682Shibler spc->spc_npages = npages; 71645749Smckusick bp->b_flags |= B_CALL; 71745749Smckusick bp->b_iodone = swap_pager_iodone; 71845749Smckusick s = splbio(); 71965231Smckusick TAILQ_INSERT_TAIL(&swap_pager_inuse, spc, spc_list); 72045749Smckusick splx(s); 72145749Smckusick } 722*65682Shibler 723*65682Shibler /* 724*65682Shibler * Finally, start the IO operation. 725*65682Shibler * If it is async we are all done, otherwise we must wait for 726*65682Shibler * completion and cleanup afterwards. 727*65682Shibler */ 72845749Smckusick #ifdef DEBUG 72945749Smckusick if (swpagerdebug & SDB_IO) 73045749Smckusick printf("swpg_io: IO start: bp %x, db %x, va %x, pa %x\n", 73145749Smckusick bp, swb->swb_block+btodb(off), kva, VM_PAGE_TO_PHYS(m)); 73245749Smckusick #endif 73345749Smckusick VOP_STRATEGY(bp); 73445749Smckusick if ((flags & (B_READ|B_ASYNC)) == B_ASYNC) { 73545749Smckusick #ifdef DEBUG 73645749Smckusick if (swpagerdebug & SDB_IO) 73745749Smckusick printf("swpg_io: IO started: bp %x\n", bp); 73845749Smckusick #endif 73945749Smckusick return(VM_PAGER_PEND); 74045749Smckusick } 74145749Smckusick s = splbio(); 74245749Smckusick #ifdef DEBUG 74345749Smckusick if (flags & B_READ) 74445749Smckusick swap_pager_piip++; 74545749Smckusick else 74645749Smckusick swap_pager_poip++; 74745749Smckusick #endif 748*65682Shibler while ((bp->b_flags & B_DONE) == 0) 749*65682Shibler (void) tsleep(bp, PVM, "swpgio", 0); 750*65682Shibler if ((flags & B_READ) == 0) 751*65682Shibler --swp->sw_poip; 75245749Smckusick #ifdef DEBUG 75345749Smckusick if (flags & B_READ) 75445749Smckusick --swap_pager_piip; 75545749Smckusick else 75645749Smckusick --swap_pager_poip; 75745749Smckusick #endif 75856320Shibler rv = (bp->b_flags & B_ERROR) ? VM_PAGER_ERROR : VM_PAGER_OK; 75945749Smckusick bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY); 76056393Smckusick bp->b_actf = bswlist.b_actf; 76156393Smckusick bswlist.b_actf = bp; 76245749Smckusick if (bp->b_vp) 76345749Smckusick brelvp(bp); 76445749Smckusick if (bswlist.b_flags & B_WANTED) { 76545749Smckusick bswlist.b_flags &= ~B_WANTED; 766*65682Shibler wakeup(&bswlist); 76745749Smckusick } 76845749Smckusick if ((flags & B_READ) == 0 && rv == VM_PAGER_OK) { 76956382Smckusick m->flags |= PG_CLEAN; 77045749Smckusick pmap_clear_modify(VM_PAGE_TO_PHYS(m)); 77145749Smckusick } 77245749Smckusick splx(s); 77345749Smckusick #ifdef DEBUG 77445749Smckusick if (swpagerdebug & SDB_IO) 77545749Smckusick printf("swpg_io: IO done: bp %x, rv %d\n", bp, rv); 77656320Shibler if ((swpagerdebug & SDB_FAIL) && rv == VM_PAGER_ERROR) 77745749Smckusick printf("swpg_io: IO error\n"); 77845749Smckusick #endif 779*65682Shibler vm_pager_unmap_pages(kva, npages); 78045749Smckusick return(rv); 78145749Smckusick } 78245749Smckusick 783*65682Shibler static void 784*65682Shibler swap_pager_clean(rw) 78545749Smckusick int rw; 78645749Smckusick { 787*65682Shibler register swp_clean_t spc; 788*65682Shibler register int s, i; 789*65682Shibler vm_object_t object; 790*65682Shibler vm_page_t m; 79145749Smckusick 79245749Smckusick #ifdef DEBUG 79345749Smckusick /* save panic time state */ 79445749Smckusick if ((swpagerdebug & SDB_ANOMPANIC) && panicstr) 795*65682Shibler return; 79645749Smckusick if (swpagerdebug & SDB_FOLLOW) 797*65682Shibler printf("swpg_clean(%x)\n", rw); 79845749Smckusick #endif 799*65682Shibler 80045749Smckusick for (;;) { 80145749Smckusick /* 80245749Smckusick * Look up and removal from inuse list must be done 80345749Smckusick * at splbio() to avoid conflicts with swap_pager_iodone. 80445749Smckusick */ 80545749Smckusick s = splbio(); 80665231Smckusick for (spc = swap_pager_inuse.tqh_first; 80765231Smckusick spc != NULL; 80865231Smckusick spc = spc->spc_list.tqe_next) { 809*65682Shibler /* 810*65682Shibler * If the operation is done, remove it from the 811*65682Shibler * list and process it. 812*65682Shibler * 813*65682Shibler * XXX if we can't get the object lock we also 814*65682Shibler * leave it on the list and try again later. 815*65682Shibler * Is there something better we could do? 816*65682Shibler */ 81745749Smckusick if ((spc->spc_flags & SPC_DONE) && 818*65682Shibler vm_object_lock_try(spc->spc_m->object)) { 81965231Smckusick TAILQ_REMOVE(&swap_pager_inuse, spc, spc_list); 82045749Smckusick break; 82145749Smckusick } 82245749Smckusick } 82345749Smckusick 82445749Smckusick /* 82545749Smckusick * No operations done, thats all we can do for now. 82645749Smckusick */ 827*65682Shibler if (spc == NULL) { 828*65682Shibler splx(s); 82945749Smckusick break; 830*65682Shibler } 83145749Smckusick splx(s); 83245749Smckusick 83345749Smckusick /* 834*65682Shibler * Found a completed operation so finish it off. 835*65682Shibler * Note: no longer at splbio since entry is off the list. 83645749Smckusick */ 837*65682Shibler m = spc->spc_m; 838*65682Shibler object = m->object; 839*65682Shibler 840*65682Shibler /* 841*65682Shibler * Process each page in the cluster. 842*65682Shibler * The first page is explicitly kept in the cleaning 843*65682Shibler * entry, others must be reconstructed from the KVA. 844*65682Shibler */ 845*65682Shibler for (i = 0; i < spc->spc_npages; i++) { 846*65682Shibler if (i) 847*65682Shibler m = vm_pager_atop(spc->spc_kva + ptoa(i)); 848*65682Shibler /* 849*65682Shibler * If no error mark as clean and inform the pmap 850*65682Shibler * system. If there was an error, mark as dirty 851*65682Shibler * so we will try again. 852*65682Shibler * 853*65682Shibler * XXX could get stuck doing this, should give up 854*65682Shibler * after awhile. 855*65682Shibler */ 856*65682Shibler if (spc->spc_flags & SPC_ERROR) { 857*65682Shibler printf("%s: clean of page %x failed\n", 858*65682Shibler "swap_pager_clean", 859*65682Shibler VM_PAGE_TO_PHYS(m)); 860*65682Shibler m->flags |= PG_LAUNDRY; 861*65682Shibler } else { 862*65682Shibler m->flags |= PG_CLEAN; 863*65682Shibler pmap_clear_modify(VM_PAGE_TO_PHYS(m)); 864*65682Shibler } 865*65682Shibler m->flags &= ~PG_BUSY; 866*65682Shibler PAGE_WAKEUP(m); 86745749Smckusick } 868*65682Shibler 869*65682Shibler /* 870*65682Shibler * Done with the object, decrement the paging count 871*65682Shibler * and unlock it. 872*65682Shibler */ 873*65682Shibler if (--object->paging_in_progress == 0) 874*65682Shibler wakeup(object); 875*65682Shibler vm_object_unlock(object); 876*65682Shibler 877*65682Shibler /* 878*65682Shibler * Free up KVM used and put the entry back on the list. 879*65682Shibler */ 880*65682Shibler vm_pager_unmap_pages(spc->spc_kva, spc->spc_npages); 88145749Smckusick spc->spc_flags = SPC_FREE; 88265231Smckusick TAILQ_INSERT_TAIL(&swap_pager_free, spc, spc_list); 88345749Smckusick #ifdef DEBUG 88445749Smckusick if (swpagerdebug & SDB_WRITE) 88545749Smckusick printf("swpg_clean: free spc %x\n", spc); 88645749Smckusick #endif 88745749Smckusick } 888*65682Shibler } 88945749Smckusick 89045749Smckusick #ifdef DEBUG 891*65682Shibler static void 892*65682Shibler swap_pager_clean_check(mlist, npages, rw) 893*65682Shibler vm_page_t *mlist; 894*65682Shibler int npages; 895*65682Shibler int rw; 896*65682Shibler { 89745749Smckusick register swp_clean_t spc; 898*65682Shibler boolean_t bad; 899*65682Shibler int i, j, s; 900*65682Shibler vm_page_t m; 90145749Smckusick 902*65682Shibler if (panicstr) 903*65682Shibler return; 90445749Smckusick 905*65682Shibler bad = FALSE; 906*65682Shibler s = splbio(); 907*65682Shibler for (spc = swap_pager_inuse.tqh_first; 908*65682Shibler spc != NULL; 909*65682Shibler spc = spc->spc_list.tqe_next) { 910*65682Shibler for (j = 0; j < spc->spc_npages; j++) { 911*65682Shibler m = vm_pager_atop(spc->spc_kva + ptoa(j)); 912*65682Shibler for (i = 0; i < npages; i++) 913*65682Shibler if (m == mlist[i]) { 914*65682Shibler if (swpagerdebug & SDB_ANOM) 915*65682Shibler printf( 916*65682Shibler "swpg_clean_check: %s: page %x on list, flags %x\n", 917*65682Shibler rw == B_WRITE ? "write" : "read", mlist[i], spc->spc_flags); 918*65682Shibler bad = TRUE; 919*65682Shibler } 920*65682Shibler } 92145749Smckusick } 922*65682Shibler splx(s); 923*65682Shibler if (bad) 924*65682Shibler panic("swpg_clean_check"); 925*65682Shibler } 92649289Shibler #endif 92745749Smckusick 92853341Sbostic static void 92945749Smckusick swap_pager_iodone(bp) 93045749Smckusick register struct buf *bp; 93145749Smckusick { 93245749Smckusick register swp_clean_t spc; 93345749Smckusick daddr_t blk; 93445749Smckusick int s; 93545749Smckusick 93645749Smckusick #ifdef DEBUG 93745749Smckusick /* save panic time state */ 93845749Smckusick if ((swpagerdebug & SDB_ANOMPANIC) && panicstr) 93945749Smckusick return; 94045749Smckusick if (swpagerdebug & SDB_FOLLOW) 94145749Smckusick printf("swpg_iodone(%x)\n", bp); 94245749Smckusick #endif 94345749Smckusick s = splbio(); 94465231Smckusick for (spc = swap_pager_inuse.tqh_first; 94565231Smckusick spc != NULL; 94665231Smckusick spc = spc->spc_list.tqe_next) 94745749Smckusick if (spc->spc_bp == bp) 94845749Smckusick break; 94945749Smckusick #ifdef DEBUG 95065231Smckusick if (spc == NULL) 95149289Shibler panic("swap_pager_iodone: bp not found"); 95245749Smckusick #endif 95345749Smckusick 95445749Smckusick spc->spc_flags &= ~SPC_BUSY; 95545749Smckusick spc->spc_flags |= SPC_DONE; 95645749Smckusick if (bp->b_flags & B_ERROR) 95745749Smckusick spc->spc_flags |= SPC_ERROR; 95845749Smckusick spc->spc_bp = NULL; 95945749Smckusick blk = bp->b_blkno; 96045749Smckusick 96145749Smckusick #ifdef DEBUG 96245749Smckusick --swap_pager_poip; 96345749Smckusick if (swpagerdebug & SDB_WRITE) 96445749Smckusick printf("swpg_iodone: bp=%x swp=%x flags=%x spc=%x poip=%x\n", 96545749Smckusick bp, spc->spc_swp, spc->spc_swp->sw_flags, 96645749Smckusick spc, spc->spc_swp->sw_poip); 96745749Smckusick #endif 96845749Smckusick 96945749Smckusick spc->spc_swp->sw_poip--; 97045749Smckusick if (spc->spc_swp->sw_flags & SW_WANTED) { 97145749Smckusick spc->spc_swp->sw_flags &= ~SW_WANTED; 972*65682Shibler wakeup(spc->spc_swp); 97345749Smckusick } 97445749Smckusick 97545749Smckusick bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY); 97656393Smckusick bp->b_actf = bswlist.b_actf; 97756393Smckusick bswlist.b_actf = bp; 97845749Smckusick if (bp->b_vp) 97945749Smckusick brelvp(bp); 98045749Smckusick if (bswlist.b_flags & B_WANTED) { 98145749Smckusick bswlist.b_flags &= ~B_WANTED; 982*65682Shibler wakeup(&bswlist); 98345749Smckusick } 984*65682Shibler wakeup(&vm_pages_needed); 98545749Smckusick splx(s); 98645749Smckusick } 987