Deleted Added
full compact
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 ---