swap_pager.c (8876) | swap_pager.c (9507) |
---|---|
1/* 2 * Copyright (c) 1994 John S. Dyson 3 * Copyright (c) 1990 University of Utah. 4 * Copyright (c) 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * the Systems Programming Group of the University of Utah Computer --- 25 unchanged lines hidden (view full) --- 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * from: Utah $Hdr: swap_pager.c 1.4 91/04/30$ 40 * 41 * @(#)swap_pager.c 8.9 (Berkeley) 3/21/94 | 1/* 2 * Copyright (c) 1994 John S. Dyson 3 * Copyright (c) 1990 University of Utah. 4 * Copyright (c) 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * the Systems Programming Group of the University of Utah Computer --- 25 unchanged lines hidden (view full) --- 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * from: Utah $Hdr: swap_pager.c 1.4 91/04/30$ 40 * 41 * @(#)swap_pager.c 8.9 (Berkeley) 3/21/94 |
42 * $Id: swap_pager.c,v 1.40 1995/05/18 02:59:20 davidg Exp $ | 42 * $Id: swap_pager.c,v 1.41 1995/05/30 08:15:55 rgrimes Exp $ |
43 */ 44 45/* 46 * Quick hack to page to dedicated partition(s). 47 * TODO: 48 * Add multiprocessor locks 49 * Deal with async writes in a better fashion 50 */ --- 15 unchanged lines hidden (view full) --- 66#include <vm/vm_pageout.h> 67#include <vm/swap_pager.h> 68#include <vm/vm_kern.h> 69 70#ifndef NPENDINGIO 71#define NPENDINGIO 10 72#endif 73 | 43 */ 44 45/* 46 * Quick hack to page to dedicated partition(s). 47 * TODO: 48 * Add multiprocessor locks 49 * Deal with async writes in a better fashion 50 */ --- 15 unchanged lines hidden (view full) --- 66#include <vm/vm_pageout.h> 67#include <vm/swap_pager.h> 68#include <vm/vm_kern.h> 69 70#ifndef NPENDINGIO 71#define NPENDINGIO 10 72#endif 73 |
74int swap_pager_input __P((sw_pager_t, vm_page_t *, int, int)); 75int swap_pager_output __P((sw_pager_t, vm_page_t *, int, int, int *)); 76 | |
77int nswiodone; 78int swap_pager_full; 79extern int vm_swap_size; 80int no_swap_space = 1; 81struct rlist *swaplist; 82int nswaplist; 83 84#define MAX_PAGEOUT_CLUSTER 8 --- 16 unchanged lines hidden (view full) --- 101/* spc_flags values */ 102#define SPC_ERROR 0x01 103 104#define SWB_EMPTY (-1) 105 106struct swpclean swap_pager_done; /* list of completed page cleans */ 107struct swpclean swap_pager_inuse; /* list of pending page cleans */ 108struct swpclean swap_pager_free; /* list of free pager clean structs */ | 74int nswiodone; 75int swap_pager_full; 76extern int vm_swap_size; 77int no_swap_space = 1; 78struct rlist *swaplist; 79int nswaplist; 80 81#define MAX_PAGEOUT_CLUSTER 8 --- 16 unchanged lines hidden (view full) --- 98/* spc_flags values */ 99#define SPC_ERROR 0x01 100 101#define SWB_EMPTY (-1) 102 103struct swpclean swap_pager_done; /* list of completed page cleans */ 104struct swpclean swap_pager_inuse; /* list of pending page cleans */ 105struct swpclean swap_pager_free; /* list of free pager clean structs */ |
109struct pagerlst swap_pager_list; /* list of "named" anon regions */ 110struct pagerlst swap_pager_un_list; /* list of "unnamed" anon pagers */ | 106struct pagerlst swap_pager_object_list; /* list of "named" anon region objects */ 107struct pagerlst swap_pager_un_object_list; /* list of "unnamed" anon region objects */ |
111 112#define SWAP_FREE_NEEDED 0x1 /* need a swap block */ 113#define SWAP_FREE_NEEDED_BY_PAGEOUT 0x2 114int swap_pager_needflags; 115 116struct pagerlst *swp_qs[] = { | 108 109#define SWAP_FREE_NEEDED 0x1 /* need a swap block */ 110#define SWAP_FREE_NEEDED_BY_PAGEOUT 0x2 111int swap_pager_needflags; 112 113struct pagerlst *swp_qs[] = { |
117 &swap_pager_list, &swap_pager_un_list, (struct pagerlst *) 0 | 114 &swap_pager_object_list, &swap_pager_un_object_list, (struct pagerlst *) 0 |
118}; 119 | 115}; 116 |
120int swap_pager_putmulti(); 121 | 117/* 118 * pagerops for OBJT_SWAP - "swap pager". 119 */ |
122struct pagerops swappagerops = { 123 swap_pager_init, 124 swap_pager_alloc, 125 swap_pager_dealloc, | 120struct pagerops swappagerops = { 121 swap_pager_init, 122 swap_pager_alloc, 123 swap_pager_dealloc, |
126 swap_pager_getpage, 127 swap_pager_getmulti, 128 swap_pager_putpage, 129 swap_pager_putmulti, 130 swap_pager_haspage | 124 swap_pager_getpages, 125 swap_pager_putpages, 126 swap_pager_haspage, 127 swap_pager_sync |
131}; 132 133int npendingio = NPENDINGIO; | 128}; 129 130int npendingio = NPENDINGIO; |
134int require_swap_init; | |
135void swap_pager_finish(); 136int dmmin, dmmax; 137 | 131void swap_pager_finish(); 132int dmmin, dmmax; 133 |
134 |
|
138static inline void 139swapsizecheck() 140{ 141 if (vm_swap_size < 128 * btodb(PAGE_SIZE)) { 142 if (swap_pager_full == 0) 143 printf("swap_pager: out of space\n"); 144 swap_pager_full = 1; 145 } else if (vm_swap_size > 192 * btodb(PAGE_SIZE)) 146 swap_pager_full = 0; 147} 148 149void 150swap_pager_init() 151{ | 135static inline void 136swapsizecheck() 137{ 138 if (vm_swap_size < 128 * btodb(PAGE_SIZE)) { 139 if (swap_pager_full == 0) 140 printf("swap_pager: out of space\n"); 141 swap_pager_full = 1; 142 } else if (vm_swap_size > 192 * btodb(PAGE_SIZE)) 143 swap_pager_full = 0; 144} 145 146void 147swap_pager_init() 148{ |
152 dfltpagerops = &swappagerops; | 149 TAILQ_INIT(&swap_pager_object_list); 150 TAILQ_INIT(&swap_pager_un_object_list); |
153 | 151 |
154 TAILQ_INIT(&swap_pager_list); 155 TAILQ_INIT(&swap_pager_un_list); 156 | |
157 /* 158 * Initialize clean lists 159 */ 160 TAILQ_INIT(&swap_pager_inuse); 161 TAILQ_INIT(&swap_pager_done); 162 TAILQ_INIT(&swap_pager_free); 163 | 152 /* 153 * Initialize clean lists 154 */ 155 TAILQ_INIT(&swap_pager_inuse); 156 TAILQ_INIT(&swap_pager_done); 157 TAILQ_INIT(&swap_pager_free); 158 |
164 require_swap_init = 1; 165 | |
166 /* 167 * Calculate the swap allocation constants. 168 */ 169 170 dmmin = CLBYTES / DEV_BSIZE; 171 dmmax = btodb(SWB_NPAGES * PAGE_SIZE) * 2; 172 173} 174 | 159 /* 160 * Calculate the swap allocation constants. 161 */ 162 163 dmmin = CLBYTES / DEV_BSIZE; 164 dmmax = btodb(SWB_NPAGES * PAGE_SIZE) * 2; 165 166} 167 |
175/* 176 * Allocate a pager structure and associated resources. 177 * Note that if we are called from the pageout daemon (handle == NULL) 178 * we should not wait for memory as it could resulting in deadlock. 179 */ 180vm_pager_t 181swap_pager_alloc(handle, size, prot, offset) 182 void *handle; 183 register vm_size_t size; 184 vm_prot_t prot; 185 vm_offset_t offset; | 168void 169swap_pager_swap_init() |
186{ | 170{ |
187 register vm_pager_t pager; 188 register sw_pager_t swp; 189 int waitok; 190 int i, j; | 171 swp_clean_t spc; 172 struct buf *bp; 173 int i; |
191 | 174 |
192 if (require_swap_init) { 193 swp_clean_t spc; 194 struct buf *bp; 195 196 /* 197 * kva's are allocated here so that we dont need to keep doing 198 * kmem_alloc pageables at runtime 199 */ 200 for (i = 0, spc = swcleanlist; i < npendingio; i++, spc++) { 201 spc->spc_kva = kmem_alloc_pageable(pager_map, PAGE_SIZE * MAX_PAGEOUT_CLUSTER); 202 if (!spc->spc_kva) { 203 break; 204 } 205 spc->spc_bp = malloc(sizeof(*bp), M_TEMP, M_KERNEL); 206 if (!spc->spc_bp) { 207 kmem_free_wakeup(pager_map, spc->spc_kva, PAGE_SIZE); 208 break; 209 } 210 spc->spc_flags = 0; 211 TAILQ_INSERT_TAIL(&swap_pager_free, spc, spc_list); 212 } 213 require_swap_init = 0; 214 if (size == 0) 215 return (NULL); 216 } | |
217 /* | 175 /* |
218 * If this is a "named" anonymous region, look it up and return the 219 * appropriate pager if it exists. | 176 * kva's are allocated here so that we dont need to keep doing 177 * kmem_alloc pageables at runtime |
220 */ | 178 */ |
221 if (handle) { 222 pager = vm_pager_lookup(&swap_pager_list, handle); 223 if (pager != NULL) { 224 /* 225 * Use vm_object_lookup to gain a reference to the 226 * object and also to remove from the object cache. 227 */ 228 if (vm_object_lookup(pager) == NULL) 229 panic("swap_pager_alloc: bad object"); 230 return (pager); | 179 for (i = 0, spc = swcleanlist; i < npendingio; i++, spc++) { 180 spc->spc_kva = kmem_alloc_pageable(pager_map, PAGE_SIZE * MAX_PAGEOUT_CLUSTER); 181 if (!spc->spc_kva) { 182 break; |
231 } | 183 } |
184 spc->spc_bp = malloc(sizeof(*bp), M_TEMP, M_KERNEL); 185 if (!spc->spc_bp) { 186 kmem_free_wakeup(pager_map, spc->spc_kva, PAGE_SIZE); 187 break; 188 } 189 spc->spc_flags = 0; 190 TAILQ_INSERT_TAIL(&swap_pager_free, spc, spc_list); |
|
232 } | 191 } |
233 /* 234 * Pager doesn't exist, allocate swap management resources and 235 * initialize. 236 */ 237 waitok = handle ? M_WAITOK : M_KERNEL; 238 pager = (vm_pager_t) malloc(sizeof *pager, M_VMPAGER, waitok); 239 if (pager == NULL) 240 return (NULL); 241 swp = (sw_pager_t) malloc(sizeof *swp, M_VMPGDATA, waitok); | 192} 193 194int 195swap_pager_swp_alloc(object, wait) 196 vm_object_t object; 197 int wait; 198{ 199 register sw_pager_t swp; 200 int i, j; 201 202 if (object->pg_data != NULL) 203 panic("swap_pager_swp_alloc: swp already allocated"); 204 205 swp = (sw_pager_t) malloc(sizeof *swp, M_VMPGDATA, wait); |
242 if (swp == NULL) { | 206 if (swp == NULL) { |
243 free((caddr_t) pager, M_VMPAGER); 244 return (NULL); | 207 return 1; |
245 } | 208 } |
246 size = round_page(size); 247 swp->sw_osize = size; 248 swp->sw_nblocks = (btodb(size) + btodb(SWB_NPAGES * PAGE_SIZE) - 1) / btodb(SWB_NPAGES * PAGE_SIZE); 249 swp->sw_blocks = (sw_blk_t) 250 malloc(swp->sw_nblocks * sizeof(*swp->sw_blocks), 251 M_VMPGDATA, waitok); | 209 210 swp->sw_nblocks = (btodb(object->size) + btodb(SWB_NPAGES * PAGE_SIZE) - 1) / btodb(SWB_NPAGES * PAGE_SIZE); 211 212 swp->sw_blocks = (sw_blk_t) malloc(swp->sw_nblocks * sizeof(*swp->sw_blocks), M_VMPGDATA, wait); |
252 if (swp->sw_blocks == NULL) { 253 free((caddr_t) swp, M_VMPGDATA); | 213 if (swp->sw_blocks == NULL) { 214 free((caddr_t) swp, M_VMPGDATA); |
254 free((caddr_t) pager, M_VMPAGER); 255 return (NULL); | 215 return 1; |
256 } | 216 } |
217 |
|
257 for (i = 0; i < swp->sw_nblocks; i++) { 258 swp->sw_blocks[i].swb_valid = 0; 259 swp->sw_blocks[i].swb_locked = 0; 260 for (j = 0; j < SWB_NPAGES; j++) 261 swp->sw_blocks[i].swb_block[j] = SWB_EMPTY; 262 } 263 264 swp->sw_poip = 0; 265 swp->sw_allocsize = 0; | 218 for (i = 0; i < swp->sw_nblocks; i++) { 219 swp->sw_blocks[i].swb_valid = 0; 220 swp->sw_blocks[i].swb_locked = 0; 221 for (j = 0; j < SWB_NPAGES; j++) 222 swp->sw_blocks[i].swb_block[j] = SWB_EMPTY; 223 } 224 225 swp->sw_poip = 0; 226 swp->sw_allocsize = 0; |
266 if (handle) { 267 vm_object_t object; | |
268 | 227 |
269 swp->sw_flags = SW_NAMED; 270 TAILQ_INSERT_TAIL(&swap_pager_list, pager, pg_list); 271 /* 272 * Consistant with other pagers: return with object 273 * referenced. Can't do this with handle == NULL since it 274 * might be the pageout daemon calling. 275 */ 276 object = vm_object_allocate(offset + size); 277 object->flags &= ~OBJ_INTERNAL; 278 vm_object_enter(object, pager); 279 object->pager = pager; | 228 object->pg_data = swp; 229 230 if (object->handle != NULL) { 231 TAILQ_INSERT_TAIL(&swap_pager_object_list, object, pager_object_list); |
280 } else { | 232 } else { |
281 swp->sw_flags = 0; 282 TAILQ_INSERT_TAIL(&swap_pager_un_list, pager, pg_list); | 233 TAILQ_INSERT_TAIL(&swap_pager_un_object_list, object, pager_object_list); |
283 } | 234 } |
284 pager->pg_handle = handle; 285 pager->pg_ops = &swappagerops; 286 pager->pg_type = PG_SWAP; 287 pager->pg_data = (caddr_t) swp; | |
288 | 235 |
289 return (pager); | 236 return 0; |
290} 291 292/* | 237} 238 239/* |
240 * Allocate a pager structure and associated resources. 241 * Note that if we are called from the pageout daemon (handle == NULL) 242 * we should not wait for memory as it could resulting in deadlock. 243 */ 244vm_object_t 245swap_pager_alloc(handle, size, prot, offset) 246 void *handle; 247 register vm_size_t size; 248 vm_prot_t prot; 249 vm_offset_t offset; 250{ 251 vm_object_t object; 252 int i; 253 254 /* 255 * If this is a "named" anonymous region, look it up and use the 256 * object if it exists, otherwise allocate a new one. 257 */ 258 if (handle) { 259 object = vm_pager_object_lookup(&swap_pager_object_list, handle); 260 if (object != NULL) { 261 vm_object_reference(object); 262 } else { 263 /* 264 * XXX - there is a race condition here. Two processes 265 * can request the same named object simultaneuously, 266 * and if one blocks for memory, the result is a disaster. 267 * Probably quite rare, but is yet another reason to just 268 * rip support of "named anonymous regions" out altogether. 269 */ 270 object = vm_object_allocate(OBJT_SWAP, offset + size); 271 object->handle = handle; 272 (void) swap_pager_swp_alloc(object, M_WAITOK); 273 } 274 } else { 275 object = vm_object_allocate(OBJT_SWAP, offset + size); 276 (void) swap_pager_swp_alloc(object, M_WAITOK); 277 } 278 279 return (object); 280} 281 282/* |
|
293 * returns disk block associated with pager and offset 294 * additionally, as a side effect returns a flag indicating 295 * if the block has been written 296 */ 297 298inline static int * | 283 * returns disk block associated with pager and offset 284 * additionally, as a side effect returns a flag indicating 285 * if the block has been written 286 */ 287 288inline static int * |
299swap_pager_diskaddr(swp, offset, valid) 300 sw_pager_t swp; | 289swap_pager_diskaddr(object, offset, valid) 290 vm_object_t object; |
301 vm_offset_t offset; 302 int *valid; 303{ | 291 vm_offset_t offset; 292 int *valid; 293{ |
294 sw_pager_t swp = object->pg_data; |
|
304 register sw_blk_t swb; 305 int ix; 306 307 if (valid) 308 *valid = 0; 309 ix = offset / (SWB_NPAGES * PAGE_SIZE); 310 if ((swp->sw_blocks == NULL) || (ix >= swp->sw_nblocks) || | 295 register sw_blk_t swb; 296 int ix; 297 298 if (valid) 299 *valid = 0; 300 ix = offset / (SWB_NPAGES * PAGE_SIZE); 301 if ((swp->sw_blocks == NULL) || (ix >= swp->sw_nblocks) || |
311 (offset >= swp->sw_osize)) { | 302 (offset >= object->size)) { |
312 return (FALSE); 313 } 314 swb = &swp->sw_blocks[ix]; 315 ix = (offset % (SWB_NPAGES * PAGE_SIZE)) / PAGE_SIZE; 316 if (valid) 317 *valid = swb->swb_valid & (1 << ix); 318 return &swb->swb_block[ix]; 319} --- 53 unchanged lines hidden (view full) --- 373 vm_swap_size += (to - from) + 1; 374 swp->sw_allocsize -= (to - from) + 1; 375 swapsizecheck(); 376} 377/* 378 * this routine frees swap blocks from a specified pager 379 */ 380void | 303 return (FALSE); 304 } 305 swb = &swp->sw_blocks[ix]; 306 ix = (offset % (SWB_NPAGES * PAGE_SIZE)) / PAGE_SIZE; 307 if (valid) 308 *valid = swb->swb_valid & (1 << ix); 309 return &swb->swb_block[ix]; 310} --- 53 unchanged lines hidden (view full) --- 364 vm_swap_size += (to - from) + 1; 365 swp->sw_allocsize -= (to - from) + 1; 366 swapsizecheck(); 367} 368/* 369 * this routine frees swap blocks from a specified pager 370 */ 371void |
381_swap_pager_freespace(swp, start, size) 382 sw_pager_t swp; | 372swap_pager_freespace(object, start, size) 373 vm_object_t object; |
383 vm_offset_t start; 384 vm_offset_t size; 385{ | 374 vm_offset_t start; 375 vm_offset_t size; 376{ |
377 sw_pager_t swp = object->pg_data; |
|
386 vm_offset_t i; 387 int s; 388 389 s = splbio(); 390 for (i = start; i < round_page(start + size); i += PAGE_SIZE) { 391 int valid; | 378 vm_offset_t i; 379 int s; 380 381 s = splbio(); 382 for (i = start; i < round_page(start + size); i += PAGE_SIZE) { 383 int valid; |
392 int *addr = swap_pager_diskaddr(swp, i, &valid); | 384 int *addr = swap_pager_diskaddr(object, i, &valid); |
393 394 if (addr && *addr != SWB_EMPTY) { 395 swap_pager_freeswapspace(swp, *addr, *addr + btodb(PAGE_SIZE) - 1); 396 if (valid) { 397 swap_pager_setvalid(swp, i, 0); 398 } 399 *addr = SWB_EMPTY; 400 } 401 } 402 splx(s); 403} 404 | 385 386 if (addr && *addr != SWB_EMPTY) { 387 swap_pager_freeswapspace(swp, *addr, *addr + btodb(PAGE_SIZE) - 1); 388 if (valid) { 389 swap_pager_setvalid(swp, i, 0); 390 } 391 *addr = SWB_EMPTY; 392 } 393 } 394 splx(s); 395} 396 |
405void 406swap_pager_freespace(pager, start, size) 407 vm_pager_t pager; 408 vm_offset_t start; 409 vm_offset_t size; 410{ 411 _swap_pager_freespace((sw_pager_t) pager->pg_data, start, size); 412} 413 | |
414static void 415swap_pager_free_swap(swp) 416 sw_pager_t swp; 417{ 418 register int i, j; 419 register sw_blk_t bp; 420 int first_block=0, block_count=0; 421 int s; --- 50 unchanged lines hidden (view full) --- 472/* 473 * Maximum number of blocks (pages) to reclaim per pass 474 */ 475#define MAXRECLAIM 128 476 477void 478swap_pager_reclaim() 479{ | 397static void 398swap_pager_free_swap(swp) 399 sw_pager_t swp; 400{ 401 register int i, j; 402 register sw_blk_t bp; 403 int first_block=0, block_count=0; 404 int s; --- 50 unchanged lines hidden (view full) --- 455/* 456 * Maximum number of blocks (pages) to reclaim per pass 457 */ 458#define MAXRECLAIM 128 459 460void 461swap_pager_reclaim() 462{ |
480 vm_pager_t p; | 463 vm_object_t object; |
481 sw_pager_t swp; 482 int i, j, k; 483 int s; 484 int reclaimcount; 485 static struct { 486 int address; 487 sw_pager_t pager; 488 } reclaims[MAXRECLAIM]; 489 static int in_reclaim; 490 491 /* 492 * allow only one process to be in the swap_pager_reclaim subroutine 493 */ 494 s = splbio(); 495 if (in_reclaim) { | 464 sw_pager_t swp; 465 int i, j, k; 466 int s; 467 int reclaimcount; 468 static struct { 469 int address; 470 sw_pager_t pager; 471 } reclaims[MAXRECLAIM]; 472 static int in_reclaim; 473 474 /* 475 * allow only one process to be in the swap_pager_reclaim subroutine 476 */ 477 s = splbio(); 478 if (in_reclaim) { |
496 tsleep((caddr_t) &in_reclaim, PSWP, "swrclm", 0); | 479 tsleep(&in_reclaim, PSWP, "swrclm", 0); |
497 splx(s); 498 return; 499 } 500 in_reclaim = 1; 501 reclaimcount = 0; 502 503 /* for each pager queue */ 504 for (k = 0; swp_qs[k]; k++) { 505 | 480 splx(s); 481 return; 482 } 483 in_reclaim = 1; 484 reclaimcount = 0; 485 486 /* for each pager queue */ 487 for (k = 0; swp_qs[k]; k++) { 488 |
506 p = swp_qs[k]->tqh_first; 507 while (p && (reclaimcount < MAXRECLAIM)) { | 489 object = swp_qs[k]->tqh_first; 490 while (object && (reclaimcount < MAXRECLAIM)) { |
508 509 /* 510 * see if any blocks associated with a pager has been 511 * allocated but not used (written) 512 */ | 491 492 /* 493 * see if any blocks associated with a pager has been 494 * allocated but not used (written) 495 */ |
513 swp = (sw_pager_t) p->pg_data; | 496 swp = (sw_pager_t) object->pg_data; |
514 for (i = 0; i < swp->sw_nblocks; i++) { 515 sw_blk_t swb = &swp->sw_blocks[i]; 516 517 if (swb->swb_locked) 518 continue; 519 for (j = 0; j < SWB_NPAGES; j++) { 520 if (swb->swb_block[j] != SWB_EMPTY && 521 (swb->swb_valid & (1 << j)) == 0) { 522 reclaims[reclaimcount].address = swb->swb_block[j]; 523 reclaims[reclaimcount++].pager = swp; 524 swb->swb_block[j] = SWB_EMPTY; 525 if (reclaimcount >= MAXRECLAIM) 526 goto rfinished; 527 } 528 } 529 } | 497 for (i = 0; i < swp->sw_nblocks; i++) { 498 sw_blk_t swb = &swp->sw_blocks[i]; 499 500 if (swb->swb_locked) 501 continue; 502 for (j = 0; j < SWB_NPAGES; j++) { 503 if (swb->swb_block[j] != SWB_EMPTY && 504 (swb->swb_valid & (1 << j)) == 0) { 505 reclaims[reclaimcount].address = swb->swb_block[j]; 506 reclaims[reclaimcount++].pager = swp; 507 swb->swb_block[j] = SWB_EMPTY; 508 if (reclaimcount >= MAXRECLAIM) 509 goto rfinished; 510 } 511 } 512 } |
530 p = p->pg_list.tqe_next; | 513 object = object->pager_object_list.tqe_next; |
531 } 532 } 533 534rfinished: 535 536 /* 537 * free the blocks that have been added to the reclaim list 538 */ 539 for (i = 0; i < reclaimcount; i++) { 540 swap_pager_freeswapspace(reclaims[i].pager, reclaims[i].address, reclaims[i].address + btodb(PAGE_SIZE) - 1); 541 } 542 splx(s); 543 in_reclaim = 0; | 514 } 515 } 516 517rfinished: 518 519 /* 520 * free the blocks that have been added to the reclaim list 521 */ 522 for (i = 0; i < reclaimcount; i++) { 523 swap_pager_freeswapspace(reclaims[i].pager, reclaims[i].address, reclaims[i].address + btodb(PAGE_SIZE) - 1); 524 } 525 splx(s); 526 in_reclaim = 0; |
544 wakeup((caddr_t) &in_reclaim); | 527 wakeup(&in_reclaim); |
545} 546 547 548/* 549 * swap_pager_copy copies blocks from one pager to another and 550 * destroys the source pager 551 */ 552 553void | 528} 529 530 531/* 532 * swap_pager_copy copies blocks from one pager to another and 533 * destroys the source pager 534 */ 535 536void |
554swap_pager_copy(srcpager, srcoffset, dstpager, dstoffset, offset) 555 vm_pager_t srcpager; | 537swap_pager_copy(srcobject, srcoffset, dstobject, dstoffset, offset) 538 vm_object_t srcobject; |
556 vm_offset_t srcoffset; | 539 vm_offset_t srcoffset; |
557 vm_pager_t dstpager; | 540 vm_object_t dstobject; |
558 vm_offset_t dstoffset; 559 vm_offset_t offset; 560{ 561 sw_pager_t srcswp, dstswp; 562 vm_offset_t i; 563 int origsize; 564 int s; 565 566 if (vm_swap_size) 567 no_swap_space = 0; 568 | 541 vm_offset_t dstoffset; 542 vm_offset_t offset; 543{ 544 sw_pager_t srcswp, dstswp; 545 vm_offset_t i; 546 int origsize; 547 int s; 548 549 if (vm_swap_size) 550 no_swap_space = 0; 551 |
569 if (no_swap_space) 570 return; 571 572 srcswp = (sw_pager_t) srcpager->pg_data; | 552 srcswp = (sw_pager_t) srcobject->pg_data; |
573 origsize = srcswp->sw_allocsize; | 553 origsize = srcswp->sw_allocsize; |
574 dstswp = (sw_pager_t) dstpager->pg_data; | 554 dstswp = (sw_pager_t) dstobject->pg_data; |
575 576 /* | 555 556 /* |
577 * remove the source pager from the swap_pager internal queue | 557 * remove the source object from the swap_pager internal queue |
578 */ | 558 */ |
579 s = splbio(); 580 if (srcswp->sw_flags & SW_NAMED) { 581 TAILQ_REMOVE(&swap_pager_list, srcpager, pg_list); 582 srcswp->sw_flags &= ~SW_NAMED; | 559 if (srcobject->handle == NULL) { 560 TAILQ_REMOVE(&swap_pager_un_object_list, srcobject, pager_object_list); |
583 } else { | 561 } else { |
584 TAILQ_REMOVE(&swap_pager_un_list, srcpager, pg_list); | 562 TAILQ_REMOVE(&swap_pager_object_list, srcobject, pager_object_list); |
585 } 586 | 563 } 564 |
565 s = splbio(); |
|
587 while (srcswp->sw_poip) { | 566 while (srcswp->sw_poip) { |
588 tsleep((caddr_t) srcswp, PVM, "spgout", 0); | 567 tsleep(srcswp, PVM, "spgout", 0); |
589 } 590 splx(s); 591 592 /* 593 * clean all of the pages that are currently active and finished 594 */ | 568 } 569 splx(s); 570 571 /* 572 * clean all of the pages that are currently active and finished 573 */ |
595 (void) swap_pager_clean(); | 574 swap_pager_sync(); |
596 597 s = splbio(); 598 /* 599 * transfer source to destination 600 */ | 575 576 s = splbio(); 577 /* 578 * transfer source to destination 579 */ |
601 for (i = 0; i < dstswp->sw_osize; i += PAGE_SIZE) { | 580 for (i = 0; i < dstobject->size; i += PAGE_SIZE) { |
602 int srcvalid, dstvalid; | 581 int srcvalid, dstvalid; |
603 int *srcaddrp = swap_pager_diskaddr(srcswp, i + offset + srcoffset, | 582 int *srcaddrp = swap_pager_diskaddr(srcobject, i + offset + srcoffset, |
604 &srcvalid); 605 int *dstaddrp; 606 607 /* 608 * see if the source has space allocated 609 */ 610 if (srcaddrp && *srcaddrp != SWB_EMPTY) { 611 /* 612 * if the source is valid and the dest has no space, 613 * then copy the allocation from the srouce to the 614 * dest. 615 */ 616 if (srcvalid) { | 583 &srcvalid); 584 int *dstaddrp; 585 586 /* 587 * see if the source has space allocated 588 */ 589 if (srcaddrp && *srcaddrp != SWB_EMPTY) { 590 /* 591 * if the source is valid and the dest has no space, 592 * then copy the allocation from the srouce to the 593 * dest. 594 */ 595 if (srcvalid) { |
617 dstaddrp = swap_pager_diskaddr(dstswp, i + dstoffset, | 596 dstaddrp = swap_pager_diskaddr(dstobject, i + dstoffset, |
618 &dstvalid); 619 /* 620 * if the dest already has a valid block, 621 * deallocate the source block without 622 * copying. 623 */ 624 if (!dstvalid && dstaddrp && *dstaddrp != SWB_EMPTY) { 625 swap_pager_freeswapspace(dstswp, *dstaddrp, --- 26 unchanged lines hidden (view full) --- 652 */ 653 swap_pager_free_swap(srcswp); 654 655 if( srcswp->sw_allocsize) 656 printf("swap_pager_copy: *warning* pager with %d blocks (orig: %d)\n", srcswp->sw_allocsize, origsize); 657 free((caddr_t) srcswp->sw_blocks, M_VMPGDATA); 658 srcswp->sw_blocks = 0; 659 free((caddr_t) srcswp, M_VMPGDATA); | 597 &dstvalid); 598 /* 599 * if the dest already has a valid block, 600 * deallocate the source block without 601 * copying. 602 */ 603 if (!dstvalid && dstaddrp && *dstaddrp != SWB_EMPTY) { 604 swap_pager_freeswapspace(dstswp, *dstaddrp, --- 26 unchanged lines hidden (view full) --- 631 */ 632 swap_pager_free_swap(srcswp); 633 634 if( srcswp->sw_allocsize) 635 printf("swap_pager_copy: *warning* pager with %d blocks (orig: %d)\n", srcswp->sw_allocsize, origsize); 636 free((caddr_t) srcswp->sw_blocks, M_VMPGDATA); 637 srcswp->sw_blocks = 0; 638 free((caddr_t) srcswp, M_VMPGDATA); |
660 srcpager->pg_data = 0; 661 free((caddr_t) srcpager, M_VMPAGER); | 639 srcobject->pg_data = NULL; |
662 663 return; 664} 665 666void | 640 641 return; 642} 643 644void |
667swap_pager_dealloc(pager) 668 vm_pager_t pager; | 645swap_pager_dealloc(object) 646 vm_object_t object; |
669{ 670 register sw_pager_t swp; 671 int s; 672 | 647{ 648 register sw_pager_t swp; 649 int s; 650 |
651 swp = (sw_pager_t) object->pg_data; 652 653 /* "Can't" happen. */ 654 if (swp == NULL) 655 panic("swap_pager_dealloc: no swp data"); 656 |
|
673 /* 674 * Remove from list right away so lookups will fail if we block for 675 * pageout completion. 676 */ | 657 /* 658 * Remove from list right away so lookups will fail if we block for 659 * pageout completion. 660 */ |
677 s = splbio(); 678 swp = (sw_pager_t) pager->pg_data; 679 if (swp->sw_flags & SW_NAMED) { 680 TAILQ_REMOVE(&swap_pager_list, pager, pg_list); 681 swp->sw_flags &= ~SW_NAMED; | 661 if (object->handle == NULL) { 662 TAILQ_REMOVE(&swap_pager_un_object_list, object, pager_object_list); |
682 } else { | 663 } else { |
683 TAILQ_REMOVE(&swap_pager_un_list, pager, pg_list); | 664 TAILQ_REMOVE(&swap_pager_object_list, object, pager_object_list); |
684 } | 665 } |
666 |
|
685 /* 686 * Wait for all pageouts to finish and remove all entries from 687 * cleaning list. 688 */ 689 | 667 /* 668 * Wait for all pageouts to finish and remove all entries from 669 * cleaning list. 670 */ 671 |
672 s = splbio(); |
|
690 while (swp->sw_poip) { | 673 while (swp->sw_poip) { |
691 tsleep((caddr_t) swp, PVM, "swpout", 0); | 674 tsleep(swp, PVM, "swpout", 0); |
692 } 693 splx(s); 694 695 | 675 } 676 splx(s); 677 678 |
696 (void) swap_pager_clean(); | 679 swap_pager_sync(); |
697 698 /* 699 * Free left over swap blocks 700 */ 701 swap_pager_free_swap(swp); 702 703 if( swp->sw_allocsize) 704 printf("swap_pager_dealloc: *warning* freeing pager with %d blocks\n", swp->sw_allocsize); 705 /* 706 * Free swap management resources 707 */ 708 free((caddr_t) swp->sw_blocks, M_VMPGDATA); 709 swp->sw_blocks = 0; 710 free((caddr_t) swp, M_VMPGDATA); | 680 681 /* 682 * Free left over swap blocks 683 */ 684 swap_pager_free_swap(swp); 685 686 if( swp->sw_allocsize) 687 printf("swap_pager_dealloc: *warning* freeing pager with %d blocks\n", swp->sw_allocsize); 688 /* 689 * Free swap management resources 690 */ 691 free((caddr_t) swp->sw_blocks, M_VMPGDATA); 692 swp->sw_blocks = 0; 693 free((caddr_t) swp, M_VMPGDATA); |
711 pager->pg_data = 0; 712 free((caddr_t) pager, M_VMPAGER); | 694 object->pg_data = 0; |
713} 714 | 695} 696 |
715/* 716 * swap_pager_getmulti can get multiple pages. 717 */ 718int 719swap_pager_getmulti(pager, m, count, reqpage, sync) 720 vm_pager_t pager; 721 vm_page_t *m; 722 int count; 723 int reqpage; 724 boolean_t sync; 725{ 726 if (reqpage >= count) 727 panic("swap_pager_getmulti: reqpage >= count"); 728 return swap_pager_input((sw_pager_t) pager->pg_data, m, count, reqpage); 729} 730 731/* 732 * swap_pager_getpage gets individual pages 733 */ 734int 735swap_pager_getpage(pager, m, sync) 736 vm_pager_t pager; 737 vm_page_t m; 738 boolean_t sync; 739{ 740 vm_page_t marray[1]; 741 742 marray[0] = m; 743 return swap_pager_input((sw_pager_t) pager->pg_data, marray, 1, 0); 744} 745 746int 747swap_pager_putmulti(pager, m, c, sync, rtvals) 748 vm_pager_t pager; 749 vm_page_t *m; 750 int c; 751 boolean_t sync; 752 int *rtvals; 753{ 754 int flags; 755 756 if (pager == NULL) { 757 (void) swap_pager_clean(); 758 return VM_PAGER_OK; 759 } 760 flags = B_WRITE; 761 if (!sync) 762 flags |= B_ASYNC; 763 764 return swap_pager_output((sw_pager_t) pager->pg_data, m, c, flags, rtvals); 765} 766 767/* 768 * swap_pager_putpage writes individual pages 769 */ 770int 771swap_pager_putpage(pager, m, sync) 772 vm_pager_t pager; 773 vm_page_t m; 774 boolean_t sync; 775{ 776 int flags; 777 vm_page_t marray[1]; 778 int rtvals[1]; 779 780 781 if (pager == NULL) { 782 (void) swap_pager_clean(); 783 return VM_PAGER_OK; 784 } 785 marray[0] = m; 786 flags = B_WRITE; 787 if (!sync) 788 flags |= B_ASYNC; 789 790 swap_pager_output((sw_pager_t) pager->pg_data, marray, 1, flags, rtvals); 791 792 return rtvals[0]; 793} 794 | |
795static inline int 796const 797swap_pager_block_index(swp, offset) 798 sw_pager_t swp; 799 vm_offset_t offset; 800{ 801 return (offset / (SWB_NPAGES * PAGE_SIZE)); 802} 803 804static inline int 805const 806swap_pager_block_offset(swp, offset) 807 sw_pager_t swp; 808 vm_offset_t offset; 809{ 810 return ((offset % (PAGE_SIZE * SWB_NPAGES)) / PAGE_SIZE); 811} 812 813/* | 697static inline int 698const 699swap_pager_block_index(swp, offset) 700 sw_pager_t swp; 701 vm_offset_t offset; 702{ 703 return (offset / (SWB_NPAGES * PAGE_SIZE)); 704} 705 706static inline int 707const 708swap_pager_block_offset(swp, offset) 709 sw_pager_t swp; 710 vm_offset_t offset; 711{ 712 return ((offset % (PAGE_SIZE * SWB_NPAGES)) / PAGE_SIZE); 713} 714 715/* |
814 * _swap_pager_haspage returns TRUE if the pager has data that has | 716 * swap_pager_haspage returns TRUE if the pager has data that has |
815 * been written out. 816 */ | 717 * been written out. 718 */ |
817static boolean_t 818_swap_pager_haspage(swp, offset) 819 sw_pager_t swp; | 719boolean_t 720swap_pager_haspage(object, offset, before, after) 721 vm_object_t object; |
820 vm_offset_t offset; | 722 vm_offset_t offset; |
723 int *before; 724 int *after; |
|
821{ | 725{ |
726 sw_pager_t swp = object->pg_data; |
|
822 register sw_blk_t swb; 823 int ix; 824 | 727 register sw_blk_t swb; 728 int ix; 729 |
730 if (before != NULL) 731 *before = 0; 732 if (after != NULL) 733 *after = 0; |
|
825 ix = offset / (SWB_NPAGES * PAGE_SIZE); 826 if (swp->sw_blocks == NULL || ix >= swp->sw_nblocks) { 827 return (FALSE); 828 } 829 swb = &swp->sw_blocks[ix]; 830 ix = (offset % (SWB_NPAGES * PAGE_SIZE)) / PAGE_SIZE; 831 if (swb->swb_block[ix] != SWB_EMPTY) { 832 if (swb->swb_valid & (1 << ix)) 833 return TRUE; 834 } 835 return (FALSE); 836} 837 838/* | 734 ix = offset / (SWB_NPAGES * PAGE_SIZE); 735 if (swp->sw_blocks == NULL || ix >= swp->sw_nblocks) { 736 return (FALSE); 737 } 738 swb = &swp->sw_blocks[ix]; 739 ix = (offset % (SWB_NPAGES * PAGE_SIZE)) / PAGE_SIZE; 740 if (swb->swb_block[ix] != SWB_EMPTY) { 741 if (swb->swb_valid & (1 << ix)) 742 return TRUE; 743 } 744 return (FALSE); 745} 746 747/* |
839 * swap_pager_haspage is the externally accessible version of 840 * _swap_pager_haspage above. this routine takes a vm_pager_t 841 * for an argument instead of sw_pager_t. 842 */ 843boolean_t 844swap_pager_haspage(pager, offset) 845 vm_pager_t pager; 846 vm_offset_t offset; 847{ 848 return _swap_pager_haspage((sw_pager_t) pager->pg_data, offset); 849} 850 851/* | |
852 * swap_pager_freepage is a convienience routine that clears the busy 853 * bit and deallocates a page. 854 */ 855static void 856swap_pager_freepage(m) 857 vm_page_t m; 858{ 859 PAGE_WAKEUP(m); --- 22 unchanged lines hidden (view full) --- 882 * swap_pager_iodone1 is the completion routine for both reads and async writes 883 */ 884void 885swap_pager_iodone1(bp) 886 struct buf *bp; 887{ 888 bp->b_flags |= B_DONE; 889 bp->b_flags &= ~B_ASYNC; | 748 * swap_pager_freepage is a convienience routine that clears the busy 749 * bit and deallocates a page. 750 */ 751static void 752swap_pager_freepage(m) 753 vm_page_t m; 754{ 755 PAGE_WAKEUP(m); --- 22 unchanged lines hidden (view full) --- 778 * swap_pager_iodone1 is the completion routine for both reads and async writes 779 */ 780void 781swap_pager_iodone1(bp) 782 struct buf *bp; 783{ 784 bp->b_flags |= B_DONE; 785 bp->b_flags &= ~B_ASYNC; |
890 wakeup((caddr_t) bp); | 786 wakeup(bp); |
891} 892 893 894int | 787} 788 789 790int |
895swap_pager_input(swp, m, count, reqpage) 896 register sw_pager_t swp; | 791swap_pager_getpages(object, m, count, reqpage) 792 vm_object_t object; |
897 vm_page_t *m; 898 int count, reqpage; 899{ | 793 vm_page_t *m; 794 int count, reqpage; 795{ |
796 register sw_pager_t swp = object->pg_data; |
|
900 register struct buf *bp; 901 sw_blk_t swb[count]; 902 register int s; 903 int i; 904 boolean_t rv; 905 vm_offset_t kva, off[count]; 906 swp_clean_t spc; 907 vm_offset_t paging_offset; | 797 register struct buf *bp; 798 sw_blk_t swb[count]; 799 register int s; 800 int i; 801 boolean_t rv; 802 vm_offset_t kva, off[count]; 803 swp_clean_t spc; 804 vm_offset_t paging_offset; |
908 vm_object_t object; | |
909 int reqaddr[count]; 910 int sequential; 911 912 int first, last; 913 int failed; 914 int reqdskregion; 915 916 object = m[reqpage]->object; --- 107 unchanged lines hidden (view full) --- 1024 reqpage = 0; 1025 /* 1026 * get a swap pager clean data structure, block until we get 1027 * it 1028 */ 1029 if (swap_pager_free.tqh_first == NULL) { 1030 s = splbio(); 1031 if (curproc == pageproc) | 805 int reqaddr[count]; 806 int sequential; 807 808 int first, last; 809 int failed; 810 int reqdskregion; 811 812 object = m[reqpage]->object; --- 107 unchanged lines hidden (view full) --- 920 reqpage = 0; 921 /* 922 * get a swap pager clean data structure, block until we get 923 * it 924 */ 925 if (swap_pager_free.tqh_first == NULL) { 926 s = splbio(); 927 if (curproc == pageproc) |
1032 (void) swap_pager_clean(); | 928 swap_pager_sync(); |
1033 else 1034 pagedaemon_wakeup(); 1035 while (swap_pager_free.tqh_first == NULL) { 1036 swap_pager_needflags |= SWAP_FREE_NEEDED; 1037 if (curproc == pageproc) 1038 swap_pager_needflags |= SWAP_FREE_NEEDED_BY_PAGEOUT; | 929 else 930 pagedaemon_wakeup(); 931 while (swap_pager_free.tqh_first == NULL) { 932 swap_pager_needflags |= SWAP_FREE_NEEDED; 933 if (curproc == pageproc) 934 swap_pager_needflags |= SWAP_FREE_NEEDED_BY_PAGEOUT; |
1039 tsleep((caddr_t) &swap_pager_free, | 935 tsleep(&swap_pager_free, |
1040 PVM, "swpfre", 0); 1041 if (curproc == pageproc) | 936 PVM, "swpfre", 0); 937 if (curproc == pageproc) |
1042 (void) swap_pager_clean(); | 938 swap_pager_sync(); |
1043 else 1044 pagedaemon_wakeup(); 1045 } 1046 splx(s); 1047 } 1048 spc = swap_pager_free.tqh_first; 1049 TAILQ_REMOVE(&swap_pager_free, spc, spc_list); 1050 kva = spc->spc_kva; --- 35 unchanged lines hidden (view full) --- 1086 */ 1087 VOP_STRATEGY(bp); 1088 1089 /* 1090 * wait for the sync I/O to complete 1091 */ 1092 s = splbio(); 1093 while ((bp->b_flags & B_DONE) == 0) { | 939 else 940 pagedaemon_wakeup(); 941 } 942 splx(s); 943 } 944 spc = swap_pager_free.tqh_first; 945 TAILQ_REMOVE(&swap_pager_free, spc, spc_list); 946 kva = spc->spc_kva; --- 35 unchanged lines hidden (view full) --- 982 */ 983 VOP_STRATEGY(bp); 984 985 /* 986 * wait for the sync I/O to complete 987 */ 988 s = splbio(); 989 while ((bp->b_flags & B_DONE) == 0) { |
1094 tsleep((caddr_t) bp, PVM, "swread", 0); | 990 tsleep(bp, PVM, "swread", 0); |
1095 } 1096 1097 if (bp->b_flags & B_ERROR) { 1098 printf("swap_pager: I/O error - pagein failed; blkno %d, size %d, error %d\n", 1099 bp->b_blkno, bp->b_bcount, bp->b_error); 1100 rv = VM_PAGER_ERROR; 1101 } else { 1102 rv = VM_PAGER_OK; 1103 } 1104 1105 --swp->sw_piip; 1106 if (swp->sw_piip == 0) | 991 } 992 993 if (bp->b_flags & B_ERROR) { 994 printf("swap_pager: I/O error - pagein failed; blkno %d, size %d, error %d\n", 995 bp->b_blkno, bp->b_bcount, bp->b_error); 996 rv = VM_PAGER_ERROR; 997 } else { 998 rv = VM_PAGER_OK; 999 } 1000 1001 --swp->sw_piip; 1002 if (swp->sw_piip == 0) |
1107 wakeup((caddr_t) swp); | 1003 wakeup(swp); |
1108 1109 1110 /* 1111 * relpbuf does this, but we maintain our own buffer list also... 1112 */ 1113 if (bp->b_vp) 1114 pbrelvp(bp); 1115 1116 splx(s); 1117 --swb[reqpage]->swb_locked; 1118 1119 /* 1120 * remove the mapping for kernel virtual 1121 */ 1122 pmap_qremove(kva, count); 1123 1124 if (spc) { 1125 m[reqpage]->object->last_read = m[reqpage]->offset; 1126 if (bp->b_flags & B_WANTED) | 1004 1005 1006 /* 1007 * relpbuf does this, but we maintain our own buffer list also... 1008 */ 1009 if (bp->b_vp) 1010 pbrelvp(bp); 1011 1012 splx(s); 1013 --swb[reqpage]->swb_locked; 1014 1015 /* 1016 * remove the mapping for kernel virtual 1017 */ 1018 pmap_qremove(kva, count); 1019 1020 if (spc) { 1021 m[reqpage]->object->last_read = m[reqpage]->offset; 1022 if (bp->b_flags & B_WANTED) |
1127 wakeup((caddr_t) bp); | 1023 wakeup(bp); |
1128 /* 1129 * if we have used an spc, we need to free it. 1130 */ 1131 if (bp->b_rcred != NOCRED) 1132 crfree(bp->b_rcred); 1133 if (bp->b_wcred != NOCRED) 1134 crfree(bp->b_wcred); 1135 TAILQ_INSERT_TAIL(&swap_pager_free, spc, spc_list); 1136 if (swap_pager_needflags & SWAP_FREE_NEEDED) { | 1024 /* 1025 * if we have used an spc, we need to free it. 1026 */ 1027 if (bp->b_rcred != NOCRED) 1028 crfree(bp->b_rcred); 1029 if (bp->b_wcred != NOCRED) 1030 crfree(bp->b_wcred); 1031 TAILQ_INSERT_TAIL(&swap_pager_free, spc, spc_list); 1032 if (swap_pager_needflags & SWAP_FREE_NEEDED) { |
1137 wakeup((caddr_t) &swap_pager_free); | 1033 wakeup(&swap_pager_free); |
1138 } 1139 if( swap_pager_needflags & SWAP_FREE_NEEDED_BY_PAGEOUT) 1140 pagedaemon_wakeup(); 1141 swap_pager_needflags &= ~(SWAP_FREE_NEEDED|SWAP_FREE_NEEDED_BY_PAGEOUT); 1142 } else { 1143 /* 1144 * release the physical I/O buffer 1145 */ --- 34 unchanged lines hidden (view full) --- 1180 * some whenever pages are brought in. We must clear 1181 * the clean flag so that the page contents will be 1182 * preserved. 1183 */ 1184 if (swap_pager_full) { 1185 for (i = 0; i < count; i++) { 1186 m[i]->dirty = VM_PAGE_BITS_ALL; 1187 } | 1034 } 1035 if( swap_pager_needflags & SWAP_FREE_NEEDED_BY_PAGEOUT) 1036 pagedaemon_wakeup(); 1037 swap_pager_needflags &= ~(SWAP_FREE_NEEDED|SWAP_FREE_NEEDED_BY_PAGEOUT); 1038 } else { 1039 /* 1040 * release the physical I/O buffer 1041 */ --- 34 unchanged lines hidden (view full) --- 1076 * some whenever pages are brought in. We must clear 1077 * the clean flag so that the page contents will be 1078 * preserved. 1079 */ 1080 if (swap_pager_full) { 1081 for (i = 0; i < count; i++) { 1082 m[i]->dirty = VM_PAGE_BITS_ALL; 1083 } |
1188 _swap_pager_freespace(swp, m[0]->offset + paging_offset, count * PAGE_SIZE); | 1084 swap_pager_freespace(object, m[0]->offset + paging_offset, count * PAGE_SIZE); |
1189 } 1190 } else { 1191 swap_pager_ridpages(m, count, reqpage); 1192 } 1193 } 1194 return (rv); 1195} 1196 1197int | 1085 } 1086 } else { 1087 swap_pager_ridpages(m, count, reqpage); 1088 } 1089 } 1090 return (rv); 1091} 1092 1093int |
1198swap_pager_output(swp, m, count, flags, rtvals) 1199 register sw_pager_t swp; | 1094swap_pager_putpages(object, m, count, sync, rtvals) 1095 vm_object_t object; |
1200 vm_page_t *m; 1201 int count; | 1096 vm_page_t *m; 1097 int count; |
1202 int flags; | 1098 boolean_t sync; |
1203 int *rtvals; 1204{ | 1099 int *rtvals; 1100{ |
1101 register sw_pager_t swp = object->pg_data; |
|
1205 register struct buf *bp; 1206 sw_blk_t swb[count]; 1207 register int s; 1208 int i, j, ix; 1209 boolean_t rv; 1210 vm_offset_t kva, off, foff; 1211 swp_clean_t spc; 1212 vm_offset_t paging_offset; | 1102 register struct buf *bp; 1103 sw_blk_t swb[count]; 1104 register int s; 1105 int i, j, ix; 1106 boolean_t rv; 1107 vm_offset_t kva, off, foff; 1108 swp_clean_t spc; 1109 vm_offset_t paging_offset; |
1213 vm_object_t object; | |
1214 int reqaddr[count]; 1215 int failed; 1216 1217 if (vm_swap_size) 1218 no_swap_space = 0; 1219 if (no_swap_space) { 1220 for (i = 0; i < count; i++) 1221 rtvals[i] = VM_PAGER_FAIL; --- 114 unchanged lines hidden (view full) --- 1336 for (i = 0; i < count; i++) { 1337 if (reqaddr[i] == SWB_EMPTY) 1338 printf("I/O to empty block????\n"); 1339 } 1340 1341 /* 1342 * For synchronous writes, we clean up all completed async pageouts. 1343 */ | 1110 int reqaddr[count]; 1111 int failed; 1112 1113 if (vm_swap_size) 1114 no_swap_space = 0; 1115 if (no_swap_space) { 1116 for (i = 0; i < count; i++) 1117 rtvals[i] = VM_PAGER_FAIL; --- 114 unchanged lines hidden (view full) --- 1232 for (i = 0; i < count; i++) { 1233 if (reqaddr[i] == SWB_EMPTY) 1234 printf("I/O to empty block????\n"); 1235 } 1236 1237 /* 1238 * For synchronous writes, we clean up all completed async pageouts. 1239 */ |
1344 if ((flags & B_ASYNC) == 0) { 1345 swap_pager_clean(); | 1240 if (sync == TRUE) { 1241 swap_pager_sync(); |
1346 } 1347 kva = 0; 1348 1349 /* 1350 * get a swap pager clean data structure, block until we get it 1351 */ 1352 if (swap_pager_free.tqh_first == NULL || 1353 swap_pager_free.tqh_first->spc_list.tqe_next == NULL || 1354 swap_pager_free.tqh_first->spc_list.tqe_next->spc_list.tqe_next == NULL) { 1355 s = splbio(); 1356 if (curproc == pageproc) { | 1242 } 1243 kva = 0; 1244 1245 /* 1246 * get a swap pager clean data structure, block until we get it 1247 */ 1248 if (swap_pager_free.tqh_first == NULL || 1249 swap_pager_free.tqh_first->spc_list.tqe_next == NULL || 1250 swap_pager_free.tqh_first->spc_list.tqe_next->spc_list.tqe_next == NULL) { 1251 s = splbio(); 1252 if (curproc == pageproc) { |
1357 (void) swap_pager_clean(); | 1253 swap_pager_sync(); |
1358#if 0 1359 splx(s); 1360 return VM_PAGER_AGAIN; 1361#endif 1362 } else 1363 pagedaemon_wakeup(); 1364 while (swap_pager_free.tqh_first == NULL || 1365 swap_pager_free.tqh_first->spc_list.tqe_next == NULL || 1366 swap_pager_free.tqh_first->spc_list.tqe_next->spc_list.tqe_next == NULL) { 1367 if (curproc == pageproc) { 1368 swap_pager_needflags |= SWAP_FREE_NEEDED_BY_PAGEOUT; 1369 if((cnt.v_free_count + cnt.v_cache_count) > cnt.v_free_reserved) | 1254#if 0 1255 splx(s); 1256 return VM_PAGER_AGAIN; 1257#endif 1258 } else 1259 pagedaemon_wakeup(); 1260 while (swap_pager_free.tqh_first == NULL || 1261 swap_pager_free.tqh_first->spc_list.tqe_next == NULL || 1262 swap_pager_free.tqh_first->spc_list.tqe_next->spc_list.tqe_next == NULL) { 1263 if (curproc == pageproc) { 1264 swap_pager_needflags |= SWAP_FREE_NEEDED_BY_PAGEOUT; 1265 if((cnt.v_free_count + cnt.v_cache_count) > cnt.v_free_reserved) |
1370 wakeup((caddr_t) &cnt.v_free_count); | 1266 wakeup(&cnt.v_free_count); |
1371 } 1372 1373 swap_pager_needflags |= SWAP_FREE_NEEDED; | 1267 } 1268 1269 swap_pager_needflags |= SWAP_FREE_NEEDED; |
1374 tsleep((caddr_t) &swap_pager_free, 1375 PVM, "swpfre", 0); | 1270 tsleep(&swap_pager_free, PVM, "swpfre", 0); |
1376 if (curproc == pageproc) | 1271 if (curproc == pageproc) |
1377 (void) swap_pager_clean(); | 1272 swap_pager_sync(); |
1378 else 1379 pagedaemon_wakeup(); 1380 } 1381 splx(s); 1382 } 1383 spc = swap_pager_free.tqh_first; 1384 TAILQ_REMOVE(&swap_pager_free, spc, spc_list); 1385 --- 43 unchanged lines hidden (view full) --- 1429 bp->b_bufsize = PAGE_SIZE * count; 1430 swapdev_vp->v_numoutput++; 1431 1432 /* 1433 * If this is an async write we set up additional buffer fields and 1434 * place a "cleaning" entry on the inuse queue. 1435 */ 1436 s = splbio(); | 1273 else 1274 pagedaemon_wakeup(); 1275 } 1276 splx(s); 1277 } 1278 spc = swap_pager_free.tqh_first; 1279 TAILQ_REMOVE(&swap_pager_free, spc, spc_list); 1280 --- 43 unchanged lines hidden (view full) --- 1324 bp->b_bufsize = PAGE_SIZE * count; 1325 swapdev_vp->v_numoutput++; 1326 1327 /* 1328 * If this is an async write we set up additional buffer fields and 1329 * place a "cleaning" entry on the inuse queue. 1330 */ 1331 s = splbio(); |
1437 if (flags & B_ASYNC) { | 1332 if (sync == FALSE) { |
1438 spc->spc_flags = 0; 1439 spc->spc_swp = swp; 1440 for (i = 0; i < count; i++) 1441 spc->spc_m[i] = m[i]; 1442 spc->spc_count = count; 1443 /* 1444 * the completion routine for async writes 1445 */ --- 10 unchanged lines hidden (view full) --- 1456 } 1457 1458 cnt.v_swapout++; 1459 cnt.v_swappgsout += count; 1460 /* 1461 * perform the I/O 1462 */ 1463 VOP_STRATEGY(bp); | 1333 spc->spc_flags = 0; 1334 spc->spc_swp = swp; 1335 for (i = 0; i < count; i++) 1336 spc->spc_m[i] = m[i]; 1337 spc->spc_count = count; 1338 /* 1339 * the completion routine for async writes 1340 */ --- 10 unchanged lines hidden (view full) --- 1351 } 1352 1353 cnt.v_swapout++; 1354 cnt.v_swappgsout += count; 1355 /* 1356 * perform the I/O 1357 */ 1358 VOP_STRATEGY(bp); |
1464 if ((flags & (B_READ | B_ASYNC)) == B_ASYNC) { | 1359 if (sync == FALSE) { |
1465 if ((bp->b_flags & B_DONE) == B_DONE) { | 1360 if ((bp->b_flags & B_DONE) == B_DONE) { |
1466 swap_pager_clean(); | 1361 swap_pager_sync(); |
1467 } 1468 splx(s); 1469 for (i = 0; i < count; i++) { 1470 rtvals[i] = VM_PAGER_PEND; 1471 } 1472 return VM_PAGER_PEND; 1473 } 1474 /* 1475 * wait for the sync I/O to complete 1476 */ 1477 while ((bp->b_flags & B_DONE) == 0) { | 1362 } 1363 splx(s); 1364 for (i = 0; i < count; i++) { 1365 rtvals[i] = VM_PAGER_PEND; 1366 } 1367 return VM_PAGER_PEND; 1368 } 1369 /* 1370 * wait for the sync I/O to complete 1371 */ 1372 while ((bp->b_flags & B_DONE) == 0) { |
1478 tsleep((caddr_t) bp, PVM, "swwrt", 0); | 1373 tsleep(bp, PVM, "swwrt", 0); |
1479 } 1480 if (bp->b_flags & B_ERROR) { 1481 printf("swap_pager: I/O error - pageout failed; blkno %d, size %d, error %d\n", 1482 bp->b_blkno, bp->b_bcount, bp->b_error); 1483 rv = VM_PAGER_ERROR; 1484 } else { 1485 rv = VM_PAGER_OK; 1486 } 1487 1488 --swp->sw_poip; 1489 if (swp->sw_poip == 0) | 1374 } 1375 if (bp->b_flags & B_ERROR) { 1376 printf("swap_pager: I/O error - pageout failed; blkno %d, size %d, error %d\n", 1377 bp->b_blkno, bp->b_bcount, bp->b_error); 1378 rv = VM_PAGER_ERROR; 1379 } else { 1380 rv = VM_PAGER_OK; 1381 } 1382 1383 --swp->sw_poip; 1384 if (swp->sw_poip == 0) |
1490 wakeup((caddr_t) swp); | 1385 wakeup(swp); |
1491 1492 if (bp->b_vp) 1493 pbrelvp(bp); 1494 if (bp->b_flags & B_WANTED) | 1386 1387 if (bp->b_vp) 1388 pbrelvp(bp); 1389 if (bp->b_flags & B_WANTED) |
1495 wakeup((caddr_t) bp); | 1390 wakeup(bp); |
1496 1497 splx(s); 1498 1499 /* 1500 * remove the mapping for kernel virtual 1501 */ 1502 pmap_qremove(kva, count); 1503 --- 23 unchanged lines hidden (view full) --- 1527 } 1528 1529 if (bp->b_rcred != NOCRED) 1530 crfree(bp->b_rcred); 1531 if (bp->b_wcred != NOCRED) 1532 crfree(bp->b_wcred); 1533 TAILQ_INSERT_TAIL(&swap_pager_free, spc, spc_list); 1534 if (swap_pager_needflags & SWAP_FREE_NEEDED) { | 1391 1392 splx(s); 1393 1394 /* 1395 * remove the mapping for kernel virtual 1396 */ 1397 pmap_qremove(kva, count); 1398 --- 23 unchanged lines hidden (view full) --- 1422 } 1423 1424 if (bp->b_rcred != NOCRED) 1425 crfree(bp->b_rcred); 1426 if (bp->b_wcred != NOCRED) 1427 crfree(bp->b_wcred); 1428 TAILQ_INSERT_TAIL(&swap_pager_free, spc, spc_list); 1429 if (swap_pager_needflags & SWAP_FREE_NEEDED) { |
1535 wakeup((caddr_t) &swap_pager_free); | 1430 wakeup(&swap_pager_free); |
1536 } 1537 if( swap_pager_needflags & SWAP_FREE_NEEDED_BY_PAGEOUT) 1538 pagedaemon_wakeup(); 1539 swap_pager_needflags &= ~(SWAP_FREE_NEEDED|SWAP_FREE_NEEDED_BY_PAGEOUT); 1540 return (rv); 1541} 1542 | 1431 } 1432 if( swap_pager_needflags & SWAP_FREE_NEEDED_BY_PAGEOUT) 1433 pagedaemon_wakeup(); 1434 swap_pager_needflags &= ~(SWAP_FREE_NEEDED|SWAP_FREE_NEEDED_BY_PAGEOUT); 1435 return (rv); 1436} 1437 |
1543boolean_t 1544swap_pager_clean() | 1438void 1439swap_pager_sync() |
1545{ 1546 register swp_clean_t spc, tspc; 1547 register int s; 1548 1549 tspc = NULL; 1550 if (swap_pager_done.tqh_first == NULL) | 1440{ 1441 register swp_clean_t spc, tspc; 1442 register int s; 1443 1444 tspc = NULL; 1445 if (swap_pager_done.tqh_first == NULL) |
1551 return FALSE; | 1446 return; |
1552 for (;;) { 1553 s = splbio(); 1554 /* 1555 * Look up and removal from done list must be done at splbio() 1556 * to avoid conflicts with swap_pager_iodone. 1557 */ 1558 while ((spc = swap_pager_done.tqh_first) != 0) { 1559 pmap_qremove(spc->spc_kva, spc->spc_count); --- 15 unchanged lines hidden (view full) --- 1575 */ 1576doclean: 1577 if (tspc && tspc == spc) { 1578 tspc = NULL; 1579 } 1580 spc->spc_flags = 0; 1581 TAILQ_INSERT_TAIL(&swap_pager_free, spc, spc_list); 1582 if (swap_pager_needflags & SWAP_FREE_NEEDED) { | 1447 for (;;) { 1448 s = splbio(); 1449 /* 1450 * Look up and removal from done list must be done at splbio() 1451 * to avoid conflicts with swap_pager_iodone. 1452 */ 1453 while ((spc = swap_pager_done.tqh_first) != 0) { 1454 pmap_qremove(spc->spc_kva, spc->spc_count); --- 15 unchanged lines hidden (view full) --- 1470 */ 1471doclean: 1472 if (tspc && tspc == spc) { 1473 tspc = NULL; 1474 } 1475 spc->spc_flags = 0; 1476 TAILQ_INSERT_TAIL(&swap_pager_free, spc, spc_list); 1477 if (swap_pager_needflags & SWAP_FREE_NEEDED) { |
1583 wakeup((caddr_t) &swap_pager_free); | 1478 wakeup(&swap_pager_free); |
1584 } 1585 if( swap_pager_needflags & SWAP_FREE_NEEDED_BY_PAGEOUT) 1586 pagedaemon_wakeup(); 1587 swap_pager_needflags &= ~(SWAP_FREE_NEEDED|SWAP_FREE_NEEDED_BY_PAGEOUT); 1588 splx(s); 1589 } 1590 | 1479 } 1480 if( swap_pager_needflags & SWAP_FREE_NEEDED_BY_PAGEOUT) 1481 pagedaemon_wakeup(); 1482 swap_pager_needflags &= ~(SWAP_FREE_NEEDED|SWAP_FREE_NEEDED_BY_PAGEOUT); 1483 splx(s); 1484 } 1485 |
1591 return (tspc ? TRUE : FALSE); | 1486 return; |
1592} 1593 1594void 1595swap_pager_finish(spc) 1596 register swp_clean_t spc; 1597{ 1598 vm_object_t object = spc->spc_m[0]->object; 1599 int i; 1600 1601 object->paging_in_progress -= spc->spc_count; 1602 if ((object->paging_in_progress == 0) && 1603 (object->flags & OBJ_PIPWNT)) { 1604 object->flags &= ~OBJ_PIPWNT; | 1487} 1488 1489void 1490swap_pager_finish(spc) 1491 register swp_clean_t spc; 1492{ 1493 vm_object_t object = spc->spc_m[0]->object; 1494 int i; 1495 1496 object->paging_in_progress -= spc->spc_count; 1497 if ((object->paging_in_progress == 0) && 1498 (object->flags & OBJ_PIPWNT)) { 1499 object->flags &= ~OBJ_PIPWNT; |
1605 thread_wakeup((int) object); | 1500 wakeup(object); |
1606 } 1607 1608 /* 1609 * If no error, mark as clean and inform the pmap system. If error, 1610 * mark as dirty so we will try again. (XXX could get stuck doing 1611 * this, should give up after awhile) 1612 */ 1613 if (spc->spc_flags & SPC_ERROR) { --- 43 unchanged lines hidden (view full) --- 1657 (bp->b_flags & B_READ) ? "pagein" : "pageout", 1658 (u_long) bp->b_blkno, bp->b_bcount, bp->b_error); 1659 } 1660 1661 if (bp->b_vp) 1662 pbrelvp(bp); 1663 1664 if (bp->b_flags & B_WANTED) | 1501 } 1502 1503 /* 1504 * If no error, mark as clean and inform the pmap system. If error, 1505 * mark as dirty so we will try again. (XXX could get stuck doing 1506 * this, should give up after awhile) 1507 */ 1508 if (spc->spc_flags & SPC_ERROR) { --- 43 unchanged lines hidden (view full) --- 1552 (bp->b_flags & B_READ) ? "pagein" : "pageout", 1553 (u_long) bp->b_blkno, bp->b_bcount, bp->b_error); 1554 } 1555 1556 if (bp->b_vp) 1557 pbrelvp(bp); 1558 1559 if (bp->b_flags & B_WANTED) |
1665 wakeup((caddr_t) bp); | 1560 wakeup(bp); |
1666 1667 if (bp->b_rcred != NOCRED) 1668 crfree(bp->b_rcred); 1669 if (bp->b_wcred != NOCRED) 1670 crfree(bp->b_wcred); 1671 1672 nswiodone += spc->spc_count; 1673 if (--spc->spc_swp->sw_poip == 0) { | 1561 1562 if (bp->b_rcred != NOCRED) 1563 crfree(bp->b_rcred); 1564 if (bp->b_wcred != NOCRED) 1565 crfree(bp->b_wcred); 1566 1567 nswiodone += spc->spc_count; 1568 if (--spc->spc_swp->sw_poip == 0) { |
1674 wakeup((caddr_t) spc->spc_swp); | 1569 wakeup(spc->spc_swp); |
1675 } 1676 if ((swap_pager_needflags & SWAP_FREE_NEEDED) || 1677 swap_pager_inuse.tqh_first == 0) { 1678 swap_pager_needflags &= ~SWAP_FREE_NEEDED; | 1570 } 1571 if ((swap_pager_needflags & SWAP_FREE_NEEDED) || 1572 swap_pager_inuse.tqh_first == 0) { 1573 swap_pager_needflags &= ~SWAP_FREE_NEEDED; |
1679 wakeup((caddr_t) &swap_pager_free); | 1574 wakeup(&swap_pager_free); |
1680 } 1681 1682 if( swap_pager_needflags & SWAP_FREE_NEEDED_BY_PAGEOUT) { 1683 swap_pager_needflags &= ~SWAP_FREE_NEEDED_BY_PAGEOUT; 1684 pagedaemon_wakeup(); 1685 } 1686 1687 if (vm_pageout_pages_needed) { | 1575 } 1576 1577 if( swap_pager_needflags & SWAP_FREE_NEEDED_BY_PAGEOUT) { 1578 swap_pager_needflags &= ~SWAP_FREE_NEEDED_BY_PAGEOUT; 1579 pagedaemon_wakeup(); 1580 } 1581 1582 if (vm_pageout_pages_needed) { |
1688 wakeup((caddr_t) &vm_pageout_pages_needed); | 1583 wakeup(&vm_pageout_pages_needed); |
1689 vm_pageout_pages_needed = 0; 1690 } 1691 if ((swap_pager_inuse.tqh_first == NULL) || 1692 ((cnt.v_free_count + cnt.v_cache_count) < cnt.v_free_min && 1693 nswiodone + cnt.v_free_count + cnt.v_cache_count >= cnt.v_free_min)) { 1694 pagedaemon_wakeup(); 1695 } 1696 splx(s); --- 13 unchanged lines hidden --- | 1584 vm_pageout_pages_needed = 0; 1585 } 1586 if ((swap_pager_inuse.tqh_first == NULL) || 1587 ((cnt.v_free_count + cnt.v_cache_count) < cnt.v_free_min && 1588 nswiodone + cnt.v_free_count + cnt.v_cache_count >= cnt.v_free_min)) { 1589 pagedaemon_wakeup(); 1590 } 1591 splx(s); --- 13 unchanged lines hidden --- |