xref: /freebsd/sys/vm/vm_pager.c (revision a481f20029a1bb881a69fbd1478149426a06c89d)
1df8bae1dSRodney W. Grimes /*
2df8bae1dSRodney W. Grimes  * Copyright (c) 1991, 1993
3df8bae1dSRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
4df8bae1dSRodney W. Grimes  *
5df8bae1dSRodney W. Grimes  * This code is derived from software contributed to Berkeley by
6df8bae1dSRodney W. Grimes  * The Mach Operating System project at Carnegie-Mellon University.
7df8bae1dSRodney W. Grimes  *
8df8bae1dSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
9df8bae1dSRodney W. Grimes  * modification, are permitted provided that the following conditions
10df8bae1dSRodney W. Grimes  * are met:
11df8bae1dSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
12df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
13df8bae1dSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
14df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
15df8bae1dSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
16df8bae1dSRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
17df8bae1dSRodney W. Grimes  *    must display the following acknowledgement:
18df8bae1dSRodney W. Grimes  *	This product includes software developed by the University of
19df8bae1dSRodney W. Grimes  *	California, Berkeley and its contributors.
20df8bae1dSRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
21df8bae1dSRodney W. Grimes  *    may be used to endorse or promote products derived from this software
22df8bae1dSRodney W. Grimes  *    without specific prior written permission.
23df8bae1dSRodney W. Grimes  *
24df8bae1dSRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25df8bae1dSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26df8bae1dSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27df8bae1dSRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28df8bae1dSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29df8bae1dSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30df8bae1dSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31df8bae1dSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32df8bae1dSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33df8bae1dSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34df8bae1dSRodney W. Grimes  * SUCH DAMAGE.
35df8bae1dSRodney W. Grimes  *
363c4dd356SDavid Greenman  *	from: @(#)vm_pager.c	8.6 (Berkeley) 1/12/94
37df8bae1dSRodney W. Grimes  *
38df8bae1dSRodney W. Grimes  *
39df8bae1dSRodney W. Grimes  * Copyright (c) 1987, 1990 Carnegie-Mellon University.
40df8bae1dSRodney W. Grimes  * All rights reserved.
41df8bae1dSRodney W. Grimes  *
42df8bae1dSRodney W. Grimes  * Authors: Avadis Tevanian, Jr., Michael Wayne Young
43df8bae1dSRodney W. Grimes  *
44df8bae1dSRodney W. Grimes  * Permission to use, copy, modify and distribute this software and
45df8bae1dSRodney W. Grimes  * its documentation is hereby granted, provided that both the copyright
46df8bae1dSRodney W. Grimes  * notice and this permission notice appear in all copies of the
47df8bae1dSRodney W. Grimes  * software, derivative works or modified versions, and any portions
48df8bae1dSRodney W. Grimes  * thereof, and that both notices appear in supporting documentation.
49df8bae1dSRodney W. Grimes  *
50df8bae1dSRodney W. Grimes  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
51df8bae1dSRodney W. Grimes  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
52df8bae1dSRodney W. Grimes  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
53df8bae1dSRodney W. Grimes  *
54df8bae1dSRodney W. Grimes  * Carnegie Mellon requests users of this software to return to
55df8bae1dSRodney W. Grimes  *
56df8bae1dSRodney W. Grimes  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
57df8bae1dSRodney W. Grimes  *  School of Computer Science
58df8bae1dSRodney W. Grimes  *  Carnegie Mellon University
59df8bae1dSRodney W. Grimes  *  Pittsburgh PA 15213-3890
60df8bae1dSRodney W. Grimes  *
61df8bae1dSRodney W. Grimes  * any improvements or extensions that they make and grant Carnegie the
62df8bae1dSRodney W. Grimes  * rights to redistribute these changes.
633c4dd356SDavid Greenman  *
64a481f200SDavid Greenman  * $Id: vm_pager.c,v 1.4 1994/08/06 09:15:40 davidg Exp $
65df8bae1dSRodney W. Grimes  */
66df8bae1dSRodney W. Grimes 
67df8bae1dSRodney W. Grimes /*
68df8bae1dSRodney W. Grimes  *	Paging space routine stubs.  Emulates a matchmaker-like interface
69df8bae1dSRodney W. Grimes  *	for builtin pagers.
70df8bae1dSRodney W. Grimes  */
71df8bae1dSRodney W. Grimes 
72df8bae1dSRodney W. Grimes #include <sys/param.h>
73df8bae1dSRodney W. Grimes #include <sys/systm.h>
74df8bae1dSRodney W. Grimes #include <sys/malloc.h>
7516f62314SDavid Greenman #include <sys/buf.h>
7616f62314SDavid Greenman #include <sys/ucred.h>
77df8bae1dSRodney W. Grimes 
78df8bae1dSRodney W. Grimes #include <vm/vm.h>
79df8bae1dSRodney W. Grimes #include <vm/vm_page.h>
80df8bae1dSRodney W. Grimes #include <vm/vm_kern.h>
81df8bae1dSRodney W. Grimes 
82df8bae1dSRodney W. Grimes extern struct pagerops swappagerops;
83df8bae1dSRodney W. Grimes extern struct pagerops vnodepagerops;
84df8bae1dSRodney W. Grimes extern struct pagerops devicepagerops;
85df8bae1dSRodney W. Grimes 
86df8bae1dSRodney W. Grimes struct pagerops *pagertab[] = {
87df8bae1dSRodney W. Grimes 	&swappagerops,		/* PG_SWAP */
88df8bae1dSRodney W. Grimes 	&vnodepagerops,		/* PG_VNODE */
89df8bae1dSRodney W. Grimes 	&devicepagerops,	/* PG_DEV */
90df8bae1dSRodney W. Grimes };
91df8bae1dSRodney W. Grimes int npagers = sizeof (pagertab) / sizeof (pagertab[0]);
92df8bae1dSRodney W. Grimes 
93df8bae1dSRodney W. Grimes struct pagerops *dfltpagerops = NULL;	/* default pager */
94df8bae1dSRodney W. Grimes 
95df8bae1dSRodney W. Grimes /*
96df8bae1dSRodney W. Grimes  * Kernel address space for mapping pages.
97df8bae1dSRodney W. Grimes  * Used by pagers where KVAs are needed for IO.
98df8bae1dSRodney W. Grimes  *
99df8bae1dSRodney W. Grimes  * XXX needs to be large enough to support the number of pending async
100df8bae1dSRodney W. Grimes  * cleaning requests (NPENDINGIO == 64) * the maximum swap cluster size
101df8bae1dSRodney W. Grimes  * (MAXPHYS == 64k) if you want to get the most efficiency.
102df8bae1dSRodney W. Grimes  */
10316f62314SDavid Greenman #define PAGER_MAP_SIZE	(8 * 1024 * 1024)
104df8bae1dSRodney W. Grimes 
10526f9a767SRodney W. Grimes int pager_map_size = PAGER_MAP_SIZE;
106df8bae1dSRodney W. Grimes vm_map_t pager_map;
107df8bae1dSRodney W. Grimes boolean_t pager_map_wanted;
108df8bae1dSRodney W. Grimes vm_offset_t pager_sva, pager_eva;
10916f62314SDavid Greenman int bswneeded;
11016f62314SDavid Greenman vm_offset_t swapbkva;		/* swap buffers kva */
111df8bae1dSRodney W. Grimes 
112df8bae1dSRodney W. Grimes void
113df8bae1dSRodney W. Grimes vm_pager_init()
114df8bae1dSRodney W. Grimes {
115df8bae1dSRodney W. Grimes 	struct pagerops **pgops;
116df8bae1dSRodney W. Grimes 
117df8bae1dSRodney W. Grimes 	/*
118df8bae1dSRodney W. Grimes 	 * Initialize known pagers
119df8bae1dSRodney W. Grimes 	 */
120df8bae1dSRodney W. Grimes 	for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++)
121df8bae1dSRodney W. Grimes 		if (pgops)
122df8bae1dSRodney W. Grimes 			(*(*pgops)->pgo_init)();
123df8bae1dSRodney W. Grimes 	if (dfltpagerops == NULL)
124df8bae1dSRodney W. Grimes 		panic("no default pager");
125df8bae1dSRodney W. Grimes }
126df8bae1dSRodney W. Grimes 
12716f62314SDavid Greenman void
12816f62314SDavid Greenman vm_pager_bufferinit()
12916f62314SDavid Greenman {
13016f62314SDavid Greenman 	struct buf *bp;
13116f62314SDavid Greenman 	int i;
13216f62314SDavid Greenman 	bp = swbuf;
13316f62314SDavid Greenman 	/*
13416f62314SDavid Greenman 	 * Now set up swap and physical I/O buffer headers.
13516f62314SDavid Greenman 	 */
13616f62314SDavid Greenman 	for (i = 0; i < nswbuf - 1; i++, bp++) {
13716f62314SDavid Greenman 		TAILQ_INSERT_HEAD(&bswlist, bp, b_freelist);
13816f62314SDavid Greenman 		bp->b_rcred = bp->b_wcred = NOCRED;
13916f62314SDavid Greenman 		bp->b_vnbufs.le_next = NOLIST;
14016f62314SDavid Greenman 	}
14116f62314SDavid Greenman 	bp->b_rcred = bp->b_wcred = NOCRED;
14216f62314SDavid Greenman 	bp->b_vnbufs.le_next = NOLIST;
14316f62314SDavid Greenman 	bp->b_actf = NULL;
14416f62314SDavid Greenman 
14516f62314SDavid Greenman 	swapbkva = kmem_alloc_pageable( pager_map, nswbuf * MAXPHYS);
14616f62314SDavid Greenman 	if( !swapbkva)
14716f62314SDavid Greenman 		panic("Not enough pager_map VM space for physical buffers");
14816f62314SDavid Greenman }
14916f62314SDavid Greenman 
150df8bae1dSRodney W. Grimes /*
151df8bae1dSRodney W. Grimes  * Allocate an instance of a pager of the given type.
152df8bae1dSRodney W. Grimes  * Size, protection and offset parameters are passed in for pagers that
153df8bae1dSRodney W. Grimes  * need to perform page-level validation (e.g. the device pager).
154df8bae1dSRodney W. Grimes  */
155df8bae1dSRodney W. Grimes vm_pager_t
156df8bae1dSRodney W. Grimes vm_pager_allocate(type, handle, size, prot, off)
157df8bae1dSRodney W. Grimes 	int type;
158df8bae1dSRodney W. Grimes 	caddr_t handle;
159df8bae1dSRodney W. Grimes 	vm_size_t size;
160df8bae1dSRodney W. Grimes 	vm_prot_t prot;
161df8bae1dSRodney W. Grimes 	vm_offset_t off;
162df8bae1dSRodney W. Grimes {
163df8bae1dSRodney W. Grimes 	struct pagerops *ops;
164df8bae1dSRodney W. Grimes 
165df8bae1dSRodney W. Grimes 	ops = (type == PG_DFLT) ? dfltpagerops : pagertab[type];
166df8bae1dSRodney W. Grimes 	if (ops)
167df8bae1dSRodney W. Grimes 		return ((*ops->pgo_alloc)(handle, size, prot, off));
168df8bae1dSRodney W. Grimes 	return (NULL);
169df8bae1dSRodney W. Grimes }
170df8bae1dSRodney W. Grimes 
171df8bae1dSRodney W. Grimes void
172df8bae1dSRodney W. Grimes vm_pager_deallocate(pager)
173df8bae1dSRodney W. Grimes 	vm_pager_t	pager;
174df8bae1dSRodney W. Grimes {
175df8bae1dSRodney W. Grimes 	if (pager == NULL)
176df8bae1dSRodney W. Grimes 		panic("vm_pager_deallocate: null pager");
177df8bae1dSRodney W. Grimes 
178df8bae1dSRodney W. Grimes 	(*pager->pg_ops->pgo_dealloc)(pager);
179df8bae1dSRodney W. Grimes }
180df8bae1dSRodney W. Grimes 
18126f9a767SRodney W. Grimes 
182df8bae1dSRodney W. Grimes int
18326f9a767SRodney W. Grimes vm_pager_get_pages(pager, m, count, reqpage, sync)
184df8bae1dSRodney W. Grimes 	vm_pager_t	pager;
18526f9a767SRodney W. Grimes 	vm_page_t	*m;
18626f9a767SRodney W. Grimes 	int		count;
18726f9a767SRodney W. Grimes 	int		reqpage;
188df8bae1dSRodney W. Grimes 	boolean_t	sync;
189df8bae1dSRodney W. Grimes {
19026f9a767SRodney W. Grimes 	extern boolean_t vm_page_zero_fill();
19126f9a767SRodney W. Grimes 	extern int vm_pageout_count;
19226f9a767SRodney W. Grimes 	int i;
193df8bae1dSRodney W. Grimes 
194df8bae1dSRodney W. Grimes 	if (pager == NULL) {
19526f9a767SRodney W. Grimes 		for (i=0;i<count;i++) {
19626f9a767SRodney W. Grimes 			if( i != reqpage) {
19726f9a767SRodney W. Grimes 				PAGE_WAKEUP(m[i]);
19826f9a767SRodney W. Grimes 				vm_page_free(m[i]);
199df8bae1dSRodney W. Grimes 			}
20026f9a767SRodney W. Grimes 		}
20126f9a767SRodney W. Grimes 		vm_page_zero_fill(m[reqpage]);
20226f9a767SRodney W. Grimes 		return VM_PAGER_OK;
20326f9a767SRodney W. Grimes 	}
20426f9a767SRodney W. Grimes 
20526f9a767SRodney W. Grimes 	if( pager->pg_ops->pgo_getpages == 0) {
20626f9a767SRodney W. Grimes 		for(i=0;i<count;i++) {
20726f9a767SRodney W. Grimes 			if( i != reqpage) {
20826f9a767SRodney W. Grimes 				PAGE_WAKEUP(m[i]);
20926f9a767SRodney W. Grimes 				vm_page_free(m[i]);
21026f9a767SRodney W. Grimes 			}
21126f9a767SRodney W. Grimes 		}
21226f9a767SRodney W. Grimes 		return(VM_PAGER_GET(pager, m[reqpage], sync));
21326f9a767SRodney W. Grimes 	} else {
21426f9a767SRodney W. Grimes 		return(VM_PAGER_GET_MULTI(pager, m, count, reqpage, sync));
21526f9a767SRodney W. Grimes 	}
216df8bae1dSRodney W. Grimes }
217df8bae1dSRodney W. Grimes 
218df8bae1dSRodney W. Grimes int
21926f9a767SRodney W. Grimes vm_pager_put_pages(pager, m, count, sync, rtvals)
220df8bae1dSRodney W. Grimes 	vm_pager_t	pager;
22126f9a767SRodney W. Grimes 	vm_page_t	*m;
22226f9a767SRodney W. Grimes 	int		count;
223df8bae1dSRodney W. Grimes 	boolean_t	sync;
22426f9a767SRodney W. Grimes 	int		*rtvals;
225df8bae1dSRodney W. Grimes {
22626f9a767SRodney W. Grimes 	int i;
22726f9a767SRodney W. Grimes 
22826f9a767SRodney W. Grimes 	if( pager->pg_ops->pgo_putpages)
22926f9a767SRodney W. Grimes 		return(VM_PAGER_PUT_MULTI(pager, m, count, sync, rtvals));
23026f9a767SRodney W. Grimes 	else {
23126f9a767SRodney W. Grimes 		for(i=0;i<count;i++) {
23226f9a767SRodney W. Grimes 			rtvals[i] = VM_PAGER_PUT( pager, m[i], sync);
23326f9a767SRodney W. Grimes 		}
23426f9a767SRodney W. Grimes 		return rtvals[0];
23526f9a767SRodney W. Grimes 	}
236df8bae1dSRodney W. Grimes }
237df8bae1dSRodney W. Grimes 
238df8bae1dSRodney W. Grimes boolean_t
239df8bae1dSRodney W. Grimes vm_pager_has_page(pager, offset)
240df8bae1dSRodney W. Grimes 	vm_pager_t	pager;
241df8bae1dSRodney W. Grimes 	vm_offset_t	offset;
242df8bae1dSRodney W. Grimes {
243df8bae1dSRodney W. Grimes 	if (pager == NULL)
244df8bae1dSRodney W. Grimes 		panic("vm_pager_has_page: null pager");
245df8bae1dSRodney W. Grimes 	return ((*pager->pg_ops->pgo_haspage)(pager, offset));
246df8bae1dSRodney W. Grimes }
247df8bae1dSRodney W. Grimes 
248df8bae1dSRodney W. Grimes /*
249df8bae1dSRodney W. Grimes  * Called by pageout daemon before going back to sleep.
250df8bae1dSRodney W. Grimes  * Gives pagers a chance to clean up any completed async pageing operations.
251df8bae1dSRodney W. Grimes  */
252df8bae1dSRodney W. Grimes void
253df8bae1dSRodney W. Grimes vm_pager_sync()
254df8bae1dSRodney W. Grimes {
255df8bae1dSRodney W. Grimes 	struct pagerops **pgops;
256df8bae1dSRodney W. Grimes 
257df8bae1dSRodney W. Grimes 	for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++)
258df8bae1dSRodney W. Grimes 		if (pgops)
25926f9a767SRodney W. Grimes 			(*(*pgops)->pgo_putpage)(NULL, NULL, 0);
260df8bae1dSRodney W. Grimes }
261df8bae1dSRodney W. Grimes 
26226f9a767SRodney W. Grimes #if 0
263df8bae1dSRodney W. Grimes void
264df8bae1dSRodney W. Grimes vm_pager_cluster(pager, offset, loff, hoff)
265df8bae1dSRodney W. Grimes 	vm_pager_t	pager;
266df8bae1dSRodney W. Grimes 	vm_offset_t	offset;
267df8bae1dSRodney W. Grimes 	vm_offset_t	*loff;
268df8bae1dSRodney W. Grimes 	vm_offset_t	*hoff;
269df8bae1dSRodney W. Grimes {
270df8bae1dSRodney W. Grimes 	if (pager == NULL)
271df8bae1dSRodney W. Grimes 		panic("vm_pager_cluster: null pager");
272df8bae1dSRodney W. Grimes 	return ((*pager->pg_ops->pgo_cluster)(pager, offset, loff, hoff));
273df8bae1dSRodney W. Grimes }
27426f9a767SRodney W. Grimes #endif
275df8bae1dSRodney W. Grimes 
276df8bae1dSRodney W. Grimes vm_offset_t
27726f9a767SRodney W. Grimes vm_pager_map_page(m)
278df8bae1dSRodney W. Grimes 	vm_page_t	m;
27926f9a767SRodney W. Grimes {
28026f9a767SRodney W. Grimes 	vm_offset_t kva;
281df8bae1dSRodney W. Grimes 
28226f9a767SRodney W. Grimes 	kva = kmem_alloc_wait(pager_map, PAGE_SIZE);
283a481f200SDavid Greenman 	pmap_kenter(kva, VM_PAGE_TO_PHYS(m));
284a481f200SDavid Greenman 	pmap_update();
285df8bae1dSRodney W. Grimes 	return(kva);
286df8bae1dSRodney W. Grimes }
287df8bae1dSRodney W. Grimes 
288df8bae1dSRodney W. Grimes void
28926f9a767SRodney W. Grimes vm_pager_unmap_page(kva)
290df8bae1dSRodney W. Grimes 	vm_offset_t	kva;
291df8bae1dSRodney W. Grimes {
292a481f200SDavid Greenman 	pmap_kremove(kva);
29326f9a767SRodney W. Grimes 	kmem_free_wakeup(pager_map, kva, PAGE_SIZE);
294df8bae1dSRodney W. Grimes }
295df8bae1dSRodney W. Grimes 
296df8bae1dSRodney W. Grimes vm_page_t
297df8bae1dSRodney W. Grimes vm_pager_atop(kva)
298df8bae1dSRodney W. Grimes 	vm_offset_t	kva;
299df8bae1dSRodney W. Grimes {
300df8bae1dSRodney W. Grimes 	vm_offset_t pa;
301df8bae1dSRodney W. Grimes 
302a481f200SDavid Greenman 	pa = pmap_kextract( kva);
303df8bae1dSRodney W. Grimes 	if (pa == 0)
304df8bae1dSRodney W. Grimes 		panic("vm_pager_atop");
305df8bae1dSRodney W. Grimes 	return (PHYS_TO_VM_PAGE(pa));
306df8bae1dSRodney W. Grimes }
307df8bae1dSRodney W. Grimes 
308df8bae1dSRodney W. Grimes vm_pager_t
309df8bae1dSRodney W. Grimes vm_pager_lookup(pglist, handle)
310df8bae1dSRodney W. Grimes 	register struct pagerlst *pglist;
311df8bae1dSRodney W. Grimes 	caddr_t handle;
312df8bae1dSRodney W. Grimes {
313df8bae1dSRodney W. Grimes 	register vm_pager_t pager;
314df8bae1dSRodney W. Grimes 
315df8bae1dSRodney W. Grimes 	for (pager = pglist->tqh_first; pager; pager = pager->pg_list.tqe_next)
316df8bae1dSRodney W. Grimes 		if (pager->pg_handle == handle)
317df8bae1dSRodney W. Grimes 			return (pager);
318df8bae1dSRodney W. Grimes 	return (NULL);
319df8bae1dSRodney W. Grimes }
320df8bae1dSRodney W. Grimes 
321df8bae1dSRodney W. Grimes /*
322df8bae1dSRodney W. Grimes  * This routine gains a reference to the object.
323df8bae1dSRodney W. Grimes  * Explicit deallocation is necessary.
324df8bae1dSRodney W. Grimes  */
325df8bae1dSRodney W. Grimes int
326df8bae1dSRodney W. Grimes pager_cache(object, should_cache)
327df8bae1dSRodney W. Grimes 	vm_object_t	object;
328df8bae1dSRodney W. Grimes 	boolean_t	should_cache;
329df8bae1dSRodney W. Grimes {
330df8bae1dSRodney W. Grimes 	if (object == NULL)
331df8bae1dSRodney W. Grimes 		return (KERN_INVALID_ARGUMENT);
332df8bae1dSRodney W. Grimes 
333df8bae1dSRodney W. Grimes 	vm_object_cache_lock();
334df8bae1dSRodney W. Grimes 	vm_object_lock(object);
335df8bae1dSRodney W. Grimes 	if (should_cache)
336df8bae1dSRodney W. Grimes 		object->flags |= OBJ_CANPERSIST;
337df8bae1dSRodney W. Grimes 	else
338df8bae1dSRodney W. Grimes 		object->flags &= ~OBJ_CANPERSIST;
339df8bae1dSRodney W. Grimes 	vm_object_unlock(object);
340df8bae1dSRodney W. Grimes 	vm_object_cache_unlock();
341df8bae1dSRodney W. Grimes 
342df8bae1dSRodney W. Grimes 	vm_object_deallocate(object);
343df8bae1dSRodney W. Grimes 
344df8bae1dSRodney W. Grimes 	return (KERN_SUCCESS);
345df8bae1dSRodney W. Grimes }
34616f62314SDavid Greenman 
34716f62314SDavid Greenman /*
34816f62314SDavid Greenman  * allocate a physical buffer
34916f62314SDavid Greenman  */
35016f62314SDavid Greenman struct buf *
35116f62314SDavid Greenman getpbuf() {
35216f62314SDavid Greenman 	int s;
35316f62314SDavid Greenman 	struct buf *bp;
35416f62314SDavid Greenman 
35516f62314SDavid Greenman 	s = splbio();
35616f62314SDavid Greenman 	/* get a bp from the swap buffer header pool */
35716f62314SDavid Greenman 	while ((bp = bswlist.tqh_first) == NULL) {
35816f62314SDavid Greenman 		bswneeded = 1;
35916f62314SDavid Greenman 		tsleep((caddr_t)&bswneeded, PVM, "wswbuf", 0);
36016f62314SDavid Greenman 	}
36116f62314SDavid Greenman 	TAILQ_REMOVE(&bswlist, bp, b_freelist);
36216f62314SDavid Greenman 	splx(s);
36316f62314SDavid Greenman 
36416f62314SDavid Greenman 	bzero(bp, sizeof *bp);
36516f62314SDavid Greenman 	bp->b_rcred = NOCRED;
36616f62314SDavid Greenman 	bp->b_wcred = NOCRED;
36716f62314SDavid Greenman 	bp->b_data = (caddr_t) (MAXPHYS * (bp-swbuf)) + swapbkva;
36816f62314SDavid Greenman 	return bp;
36916f62314SDavid Greenman }
37016f62314SDavid Greenman 
37116f62314SDavid Greenman /*
37216f62314SDavid Greenman  * allocate a physical buffer, if one is available
37316f62314SDavid Greenman  */
37416f62314SDavid Greenman struct buf *
37516f62314SDavid Greenman trypbuf() {
37616f62314SDavid Greenman 	int s;
37716f62314SDavid Greenman 	struct buf *bp;
37816f62314SDavid Greenman 
37916f62314SDavid Greenman 	s = splbio();
38016f62314SDavid Greenman 	if ((bp = bswlist.tqh_first) == NULL) {
38116f62314SDavid Greenman 		splx(s);
38216f62314SDavid Greenman 		return NULL;
38316f62314SDavid Greenman 	}
38416f62314SDavid Greenman 	TAILQ_REMOVE(&bswlist, bp, b_freelist);
38516f62314SDavid Greenman 	splx(s);
38616f62314SDavid Greenman 
38716f62314SDavid Greenman 	bzero(bp, sizeof *bp);
38816f62314SDavid Greenman 	bp->b_rcred = NOCRED;
38916f62314SDavid Greenman 	bp->b_wcred = NOCRED;
39016f62314SDavid Greenman 	bp->b_data = (caddr_t) (MAXPHYS * (bp-swbuf)) + swapbkva;
39116f62314SDavid Greenman 	return bp;
39216f62314SDavid Greenman }
39316f62314SDavid Greenman 
39416f62314SDavid Greenman /*
39516f62314SDavid Greenman  * release a physical buffer
39616f62314SDavid Greenman  */
39716f62314SDavid Greenman void
39816f62314SDavid Greenman relpbuf(bp)
39916f62314SDavid Greenman 	struct buf *bp;
40016f62314SDavid Greenman {
40116f62314SDavid Greenman 	int s;
40216f62314SDavid Greenman 
40316f62314SDavid Greenman 	s = splbio();
40416f62314SDavid Greenman 
40516f62314SDavid Greenman 	if (bp->b_rcred != NOCRED) {
40616f62314SDavid Greenman 		crfree(bp->b_rcred);
40716f62314SDavid Greenman 		bp->b_rcred = NOCRED;
40816f62314SDavid Greenman 	}
40916f62314SDavid Greenman 	if (bp->b_wcred != NOCRED) {
41016f62314SDavid Greenman 		crfree(bp->b_wcred);
41116f62314SDavid Greenman 		bp->b_wcred = NOCRED;
41216f62314SDavid Greenman 	}
41316f62314SDavid Greenman 
41416f62314SDavid Greenman 	if (bp->b_vp)
41516f62314SDavid Greenman 		brelvp(bp);
41616f62314SDavid Greenman 
41716f62314SDavid Greenman 	TAILQ_INSERT_HEAD(&bswlist, bp, b_freelist);
41816f62314SDavid Greenman 
41916f62314SDavid Greenman 	if (bswneeded) {
42016f62314SDavid Greenman 		bswneeded = 0;
42116f62314SDavid Greenman 		wakeup((caddr_t)&bswlist);
42216f62314SDavid Greenman 	}
42316f62314SDavid Greenman 	splx(s);
42416f62314SDavid Greenman }
42516f62314SDavid Greenman 
42616f62314SDavid Greenman 
427