xref: /freebsd/sys/vm/vm_pager.c (revision 618540833659ea9819b7e2260a9b3707f0aa6a20)
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  *
6461854083SDavid Greenman  * $Id: vm_pager.c,v 1.8 1994/10/09 01:52:16 phk 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>
7405f0fdd2SPoul-Henning Kamp #include <sys/proc.h>
75df8bae1dSRodney W. Grimes #include <sys/malloc.h>
7616f62314SDavid Greenman #include <sys/buf.h>
7716f62314SDavid Greenman #include <sys/ucred.h>
78df8bae1dSRodney W. Grimes 
79df8bae1dSRodney W. Grimes #include <vm/vm.h>
80df8bae1dSRodney W. Grimes #include <vm/vm_page.h>
81df8bae1dSRodney W. Grimes #include <vm/vm_kern.h>
82df8bae1dSRodney W. Grimes 
83df8bae1dSRodney W. Grimes extern struct pagerops swappagerops;
84df8bae1dSRodney W. Grimes extern struct pagerops vnodepagerops;
85df8bae1dSRodney W. Grimes extern struct pagerops devicepagerops;
86df8bae1dSRodney W. Grimes 
87df8bae1dSRodney W. Grimes struct pagerops *pagertab[] = {
88df8bae1dSRodney W. Grimes 	&swappagerops,		/* PG_SWAP */
89df8bae1dSRodney W. Grimes 	&vnodepagerops,		/* PG_VNODE */
90df8bae1dSRodney W. Grimes 	&devicepagerops,	/* PG_DEV */
91df8bae1dSRodney W. Grimes };
92df8bae1dSRodney W. Grimes int npagers = sizeof (pagertab) / sizeof (pagertab[0]);
93df8bae1dSRodney W. Grimes 
94df8bae1dSRodney W. Grimes struct pagerops *dfltpagerops = NULL;	/* default pager */
95df8bae1dSRodney W. Grimes 
96df8bae1dSRodney W. Grimes /*
97df8bae1dSRodney W. Grimes  * Kernel address space for mapping pages.
98df8bae1dSRodney W. Grimes  * Used by pagers where KVAs are needed for IO.
99df8bae1dSRodney W. Grimes  *
100df8bae1dSRodney W. Grimes  * XXX needs to be large enough to support the number of pending async
101df8bae1dSRodney W. Grimes  * cleaning requests (NPENDINGIO == 64) * the maximum swap cluster size
102df8bae1dSRodney W. Grimes  * (MAXPHYS == 64k) if you want to get the most efficiency.
103df8bae1dSRodney W. Grimes  */
10416f62314SDavid Greenman #define PAGER_MAP_SIZE	(8 * 1024 * 1024)
105df8bae1dSRodney W. Grimes 
10626f9a767SRodney W. Grimes int pager_map_size = PAGER_MAP_SIZE;
107df8bae1dSRodney W. Grimes vm_map_t pager_map;
108df8bae1dSRodney W. Grimes boolean_t pager_map_wanted;
109df8bae1dSRodney W. Grimes vm_offset_t pager_sva, pager_eva;
11016f62314SDavid Greenman int bswneeded;
11116f62314SDavid Greenman vm_offset_t swapbkva;		/* swap buffers kva */
112df8bae1dSRodney W. Grimes 
113df8bae1dSRodney W. Grimes void
114df8bae1dSRodney W. Grimes vm_pager_init()
115df8bae1dSRodney W. Grimes {
116df8bae1dSRodney W. Grimes 	struct pagerops **pgops;
117df8bae1dSRodney W. Grimes 
118df8bae1dSRodney W. Grimes 	/*
119df8bae1dSRodney W. Grimes 	 * Initialize known pagers
120df8bae1dSRodney W. Grimes 	 */
121df8bae1dSRodney W. Grimes 	for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++)
122df8bae1dSRodney W. Grimes 		if (pgops)
123df8bae1dSRodney W. Grimes 			(*(*pgops)->pgo_init)();
124df8bae1dSRodney W. Grimes 	if (dfltpagerops == NULL)
125df8bae1dSRodney W. Grimes 		panic("no default pager");
126df8bae1dSRodney W. Grimes }
127df8bae1dSRodney W. Grimes 
12816f62314SDavid Greenman void
12916f62314SDavid Greenman vm_pager_bufferinit()
13016f62314SDavid Greenman {
13116f62314SDavid Greenman 	struct buf *bp;
13216f62314SDavid Greenman 	int i;
13316f62314SDavid Greenman 	bp = swbuf;
13416f62314SDavid Greenman 	/*
13516f62314SDavid Greenman 	 * Now set up swap and physical I/O buffer headers.
13616f62314SDavid Greenman 	 */
13716f62314SDavid Greenman 	for (i = 0; i < nswbuf - 1; i++, bp++) {
13816f62314SDavid Greenman 		TAILQ_INSERT_HEAD(&bswlist, bp, b_freelist);
13916f62314SDavid Greenman 		bp->b_rcred = bp->b_wcred = NOCRED;
14016f62314SDavid Greenman 		bp->b_vnbufs.le_next = NOLIST;
14116f62314SDavid Greenman 	}
14216f62314SDavid Greenman 	bp->b_rcred = bp->b_wcred = NOCRED;
14316f62314SDavid Greenman 	bp->b_vnbufs.le_next = NOLIST;
14416f62314SDavid Greenman 	bp->b_actf = NULL;
14516f62314SDavid Greenman 
14616f62314SDavid Greenman 	swapbkva = kmem_alloc_pageable( pager_map, nswbuf * MAXPHYS);
14716f62314SDavid Greenman 	if( !swapbkva)
14816f62314SDavid Greenman 		panic("Not enough pager_map VM space for physical buffers");
14916f62314SDavid Greenman }
15016f62314SDavid Greenman 
151df8bae1dSRodney W. Grimes /*
152df8bae1dSRodney W. Grimes  * Allocate an instance of a pager of the given type.
153df8bae1dSRodney W. Grimes  * Size, protection and offset parameters are passed in for pagers that
154df8bae1dSRodney W. Grimes  * need to perform page-level validation (e.g. the device pager).
155df8bae1dSRodney W. Grimes  */
156df8bae1dSRodney W. Grimes vm_pager_t
157df8bae1dSRodney W. Grimes vm_pager_allocate(type, handle, size, prot, off)
158df8bae1dSRodney W. Grimes 	int type;
159df8bae1dSRodney W. Grimes 	caddr_t handle;
160df8bae1dSRodney W. Grimes 	vm_size_t size;
161df8bae1dSRodney W. Grimes 	vm_prot_t prot;
162df8bae1dSRodney W. Grimes 	vm_offset_t off;
163df8bae1dSRodney W. Grimes {
164df8bae1dSRodney W. Grimes 	struct pagerops *ops;
165df8bae1dSRodney W. Grimes 
166df8bae1dSRodney W. Grimes 	ops = (type == PG_DFLT) ? dfltpagerops : pagertab[type];
167df8bae1dSRodney W. Grimes 	if (ops)
168df8bae1dSRodney W. Grimes 		return ((*ops->pgo_alloc)(handle, size, prot, off));
169df8bae1dSRodney W. Grimes 	return (NULL);
170df8bae1dSRodney W. Grimes }
171df8bae1dSRodney W. Grimes 
172df8bae1dSRodney W. Grimes void
173df8bae1dSRodney W. Grimes vm_pager_deallocate(pager)
174df8bae1dSRodney W. Grimes 	vm_pager_t	pager;
175df8bae1dSRodney W. Grimes {
176df8bae1dSRodney W. Grimes 	if (pager == NULL)
177df8bae1dSRodney W. Grimes 		panic("vm_pager_deallocate: null pager");
178df8bae1dSRodney W. Grimes 
179df8bae1dSRodney W. Grimes 	(*pager->pg_ops->pgo_dealloc)(pager);
180df8bae1dSRodney W. Grimes }
181df8bae1dSRodney W. Grimes 
18226f9a767SRodney W. Grimes 
183df8bae1dSRodney W. Grimes int
18426f9a767SRodney W. Grimes vm_pager_get_pages(pager, m, count, reqpage, sync)
185df8bae1dSRodney W. Grimes 	vm_pager_t	pager;
18626f9a767SRodney W. Grimes 	vm_page_t	*m;
18726f9a767SRodney W. Grimes 	int		count;
18826f9a767SRodney W. Grimes 	int		reqpage;
189df8bae1dSRodney W. Grimes 	boolean_t	sync;
190df8bae1dSRodney W. Grimes {
19126f9a767SRodney W. Grimes 	int i;
192df8bae1dSRodney W. Grimes 
193df8bae1dSRodney W. Grimes 	if (pager == NULL) {
19426f9a767SRodney W. Grimes 		for (i=0;i<count;i++) {
19526f9a767SRodney W. Grimes 			if( i != reqpage) {
19626f9a767SRodney W. Grimes 				PAGE_WAKEUP(m[i]);
19726f9a767SRodney W. Grimes 				vm_page_free(m[i]);
198df8bae1dSRodney W. Grimes 			}
19926f9a767SRodney W. Grimes 		}
20026f9a767SRodney W. Grimes 		vm_page_zero_fill(m[reqpage]);
20126f9a767SRodney W. Grimes 		return VM_PAGER_OK;
20226f9a767SRodney W. Grimes 	}
20326f9a767SRodney W. Grimes 
20426f9a767SRodney W. Grimes 	if( pager->pg_ops->pgo_getpages == 0) {
20526f9a767SRodney W. Grimes 		for(i=0;i<count;i++) {
20626f9a767SRodney W. Grimes 			if( i != reqpage) {
20726f9a767SRodney W. Grimes 				PAGE_WAKEUP(m[i]);
20826f9a767SRodney W. Grimes 				vm_page_free(m[i]);
20926f9a767SRodney W. Grimes 			}
21026f9a767SRodney W. Grimes 		}
21126f9a767SRodney W. Grimes 		return(VM_PAGER_GET(pager, m[reqpage], sync));
21226f9a767SRodney W. Grimes 	} else {
21326f9a767SRodney W. Grimes 		return(VM_PAGER_GET_MULTI(pager, m, count, reqpage, sync));
21426f9a767SRodney W. Grimes 	}
215df8bae1dSRodney W. Grimes }
216df8bae1dSRodney W. Grimes 
217df8bae1dSRodney W. Grimes int
21826f9a767SRodney W. Grimes vm_pager_put_pages(pager, m, count, sync, rtvals)
219df8bae1dSRodney W. Grimes 	vm_pager_t	pager;
22026f9a767SRodney W. Grimes 	vm_page_t	*m;
22126f9a767SRodney W. Grimes 	int		count;
222df8bae1dSRodney W. Grimes 	boolean_t	sync;
22326f9a767SRodney W. Grimes 	int		*rtvals;
224df8bae1dSRodney W. Grimes {
22526f9a767SRodney W. Grimes 	int i;
22626f9a767SRodney W. Grimes 
22726f9a767SRodney W. Grimes 	if( pager->pg_ops->pgo_putpages)
22826f9a767SRodney W. Grimes 		return(VM_PAGER_PUT_MULTI(pager, m, count, sync, rtvals));
22926f9a767SRodney W. Grimes 	else {
23026f9a767SRodney W. Grimes 		for(i=0;i<count;i++) {
23126f9a767SRodney W. Grimes 			rtvals[i] = VM_PAGER_PUT( pager, m[i], sync);
23226f9a767SRodney W. Grimes 		}
23326f9a767SRodney W. Grimes 		return rtvals[0];
23426f9a767SRodney W. Grimes 	}
235df8bae1dSRodney W. Grimes }
236df8bae1dSRodney W. Grimes 
237df8bae1dSRodney W. Grimes boolean_t
238df8bae1dSRodney W. Grimes vm_pager_has_page(pager, offset)
239df8bae1dSRodney W. Grimes 	vm_pager_t	pager;
240df8bae1dSRodney W. Grimes 	vm_offset_t	offset;
241df8bae1dSRodney W. Grimes {
242df8bae1dSRodney W. Grimes 	if (pager == NULL)
243df8bae1dSRodney W. Grimes 		panic("vm_pager_has_page: null pager");
244df8bae1dSRodney W. Grimes 	return ((*pager->pg_ops->pgo_haspage)(pager, offset));
245df8bae1dSRodney W. Grimes }
246df8bae1dSRodney W. Grimes 
247df8bae1dSRodney W. Grimes /*
248df8bae1dSRodney W. Grimes  * Called by pageout daemon before going back to sleep.
249df8bae1dSRodney W. Grimes  * Gives pagers a chance to clean up any completed async pageing operations.
250df8bae1dSRodney W. Grimes  */
251df8bae1dSRodney W. Grimes void
252df8bae1dSRodney W. Grimes vm_pager_sync()
253df8bae1dSRodney W. Grimes {
254df8bae1dSRodney W. Grimes 	struct pagerops **pgops;
255df8bae1dSRodney W. Grimes 
256df8bae1dSRodney W. Grimes 	for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++)
257df8bae1dSRodney W. Grimes 		if (pgops)
25826f9a767SRodney W. Grimes 			(*(*pgops)->pgo_putpage)(NULL, NULL, 0);
259df8bae1dSRodney W. Grimes }
260df8bae1dSRodney W. Grimes 
26126f9a767SRodney W. Grimes #if 0
262df8bae1dSRodney W. Grimes void
263df8bae1dSRodney W. Grimes vm_pager_cluster(pager, offset, loff, hoff)
264df8bae1dSRodney W. Grimes 	vm_pager_t	pager;
265df8bae1dSRodney W. Grimes 	vm_offset_t	offset;
266df8bae1dSRodney W. Grimes 	vm_offset_t	*loff;
267df8bae1dSRodney W. Grimes 	vm_offset_t	*hoff;
268df8bae1dSRodney W. Grimes {
269df8bae1dSRodney W. Grimes 	if (pager == NULL)
270df8bae1dSRodney W. Grimes 		panic("vm_pager_cluster: null pager");
271df8bae1dSRodney W. Grimes 	return ((*pager->pg_ops->pgo_cluster)(pager, offset, loff, hoff));
272df8bae1dSRodney W. Grimes }
27326f9a767SRodney W. Grimes #endif
274df8bae1dSRodney W. Grimes 
275df8bae1dSRodney W. Grimes vm_offset_t
27626f9a767SRodney W. Grimes vm_pager_map_page(m)
277df8bae1dSRodney W. Grimes 	vm_page_t	m;
27826f9a767SRodney W. Grimes {
27926f9a767SRodney W. Grimes 	vm_offset_t kva;
280df8bae1dSRodney W. Grimes 
28126f9a767SRodney W. Grimes 	kva = kmem_alloc_wait(pager_map, PAGE_SIZE);
282a481f200SDavid Greenman 	pmap_kenter(kva, VM_PAGE_TO_PHYS(m));
283df8bae1dSRodney W. Grimes 	return(kva);
284df8bae1dSRodney W. Grimes }
285df8bae1dSRodney W. Grimes 
286df8bae1dSRodney W. Grimes void
28726f9a767SRodney W. Grimes vm_pager_unmap_page(kva)
288df8bae1dSRodney W. Grimes 	vm_offset_t	kva;
289df8bae1dSRodney W. Grimes {
290a481f200SDavid Greenman 	pmap_kremove(kva);
29126f9a767SRodney W. Grimes 	kmem_free_wakeup(pager_map, kva, PAGE_SIZE);
292df8bae1dSRodney W. Grimes }
293df8bae1dSRodney W. Grimes 
294df8bae1dSRodney W. Grimes vm_page_t
295df8bae1dSRodney W. Grimes vm_pager_atop(kva)
296df8bae1dSRodney W. Grimes 	vm_offset_t	kva;
297df8bae1dSRodney W. Grimes {
298df8bae1dSRodney W. Grimes 	vm_offset_t pa;
299df8bae1dSRodney W. Grimes 
300a481f200SDavid Greenman 	pa = pmap_kextract( kva);
301df8bae1dSRodney W. Grimes 	if (pa == 0)
302df8bae1dSRodney W. Grimes 		panic("vm_pager_atop");
303df8bae1dSRodney W. Grimes 	return (PHYS_TO_VM_PAGE(pa));
304df8bae1dSRodney W. Grimes }
305df8bae1dSRodney W. Grimes 
306df8bae1dSRodney W. Grimes vm_pager_t
307df8bae1dSRodney W. Grimes vm_pager_lookup(pglist, handle)
308df8bae1dSRodney W. Grimes 	register struct pagerlst *pglist;
309df8bae1dSRodney W. Grimes 	caddr_t handle;
310df8bae1dSRodney W. Grimes {
311df8bae1dSRodney W. Grimes 	register vm_pager_t pager;
312df8bae1dSRodney W. Grimes 
313df8bae1dSRodney W. Grimes 	for (pager = pglist->tqh_first; pager; pager = pager->pg_list.tqe_next)
314df8bae1dSRodney W. Grimes 		if (pager->pg_handle == handle)
315df8bae1dSRodney W. Grimes 			return (pager);
316df8bae1dSRodney W. Grimes 	return (NULL);
317df8bae1dSRodney W. Grimes }
318df8bae1dSRodney W. Grimes 
319df8bae1dSRodney W. Grimes /*
320df8bae1dSRodney W. Grimes  * This routine gains a reference to the object.
321df8bae1dSRodney W. Grimes  * Explicit deallocation is necessary.
322df8bae1dSRodney W. Grimes  */
323df8bae1dSRodney W. Grimes int
324df8bae1dSRodney W. Grimes pager_cache(object, should_cache)
325df8bae1dSRodney W. Grimes 	vm_object_t	object;
326df8bae1dSRodney W. Grimes 	boolean_t	should_cache;
327df8bae1dSRodney W. Grimes {
328df8bae1dSRodney W. Grimes 	if (object == NULL)
329df8bae1dSRodney W. Grimes 		return (KERN_INVALID_ARGUMENT);
330df8bae1dSRodney W. Grimes 
331df8bae1dSRodney W. Grimes 	vm_object_cache_lock();
332df8bae1dSRodney W. Grimes 	vm_object_lock(object);
333df8bae1dSRodney W. Grimes 	if (should_cache)
334df8bae1dSRodney W. Grimes 		object->flags |= OBJ_CANPERSIST;
335df8bae1dSRodney W. Grimes 	else
336df8bae1dSRodney W. Grimes 		object->flags &= ~OBJ_CANPERSIST;
337df8bae1dSRodney W. Grimes 	vm_object_unlock(object);
338df8bae1dSRodney W. Grimes 	vm_object_cache_unlock();
339df8bae1dSRodney W. Grimes 
340df8bae1dSRodney W. Grimes 	vm_object_deallocate(object);
341df8bae1dSRodney W. Grimes 
342df8bae1dSRodney W. Grimes 	return (KERN_SUCCESS);
343df8bae1dSRodney W. Grimes }
34416f62314SDavid Greenman 
34516f62314SDavid Greenman /*
34616f62314SDavid Greenman  * allocate a physical buffer
34716f62314SDavid Greenman  */
34816f62314SDavid Greenman struct buf *
34916f62314SDavid Greenman getpbuf() {
35016f62314SDavid Greenman 	int s;
35116f62314SDavid Greenman 	struct buf *bp;
35216f62314SDavid Greenman 
35316f62314SDavid Greenman 	s = splbio();
35416f62314SDavid Greenman 	/* get a bp from the swap buffer header pool */
35516f62314SDavid Greenman 	while ((bp = bswlist.tqh_first) == NULL) {
35616f62314SDavid Greenman 		bswneeded = 1;
35716f62314SDavid Greenman 		tsleep((caddr_t)&bswneeded, PVM, "wswbuf", 0);
35816f62314SDavid Greenman 	}
35916f62314SDavid Greenman 	TAILQ_REMOVE(&bswlist, bp, b_freelist);
36016f62314SDavid Greenman 	splx(s);
36116f62314SDavid Greenman 
36216f62314SDavid Greenman 	bzero(bp, sizeof *bp);
36316f62314SDavid Greenman 	bp->b_rcred = NOCRED;
36416f62314SDavid Greenman 	bp->b_wcred = NOCRED;
36516f62314SDavid Greenman 	bp->b_data = (caddr_t) (MAXPHYS * (bp-swbuf)) + swapbkva;
36616f62314SDavid Greenman 	return bp;
36716f62314SDavid Greenman }
36816f62314SDavid Greenman 
36916f62314SDavid Greenman /*
37016f62314SDavid Greenman  * allocate a physical buffer, if one is available
37116f62314SDavid Greenman  */
37216f62314SDavid Greenman struct buf *
37316f62314SDavid Greenman trypbuf() {
37416f62314SDavid Greenman 	int s;
37516f62314SDavid Greenman 	struct buf *bp;
37616f62314SDavid Greenman 
37716f62314SDavid Greenman 	s = splbio();
37816f62314SDavid Greenman 	if ((bp = bswlist.tqh_first) == NULL) {
37916f62314SDavid Greenman 		splx(s);
38016f62314SDavid Greenman 		return NULL;
38116f62314SDavid Greenman 	}
38216f62314SDavid Greenman 	TAILQ_REMOVE(&bswlist, bp, b_freelist);
38316f62314SDavid Greenman 	splx(s);
38416f62314SDavid Greenman 
38516f62314SDavid Greenman 	bzero(bp, sizeof *bp);
38616f62314SDavid Greenman 	bp->b_rcred = NOCRED;
38716f62314SDavid Greenman 	bp->b_wcred = NOCRED;
38816f62314SDavid Greenman 	bp->b_data = (caddr_t) (MAXPHYS * (bp-swbuf)) + swapbkva;
38916f62314SDavid Greenman 	return bp;
39016f62314SDavid Greenman }
39116f62314SDavid Greenman 
39216f62314SDavid Greenman /*
39316f62314SDavid Greenman  * release a physical buffer
39416f62314SDavid Greenman  */
39516f62314SDavid Greenman void
39616f62314SDavid Greenman relpbuf(bp)
39716f62314SDavid Greenman 	struct buf *bp;
39816f62314SDavid Greenman {
39916f62314SDavid Greenman 	int s;
40016f62314SDavid Greenman 
40116f62314SDavid Greenman 	s = splbio();
40216f62314SDavid Greenman 
40316f62314SDavid Greenman 	if (bp->b_rcred != NOCRED) {
40416f62314SDavid Greenman 		crfree(bp->b_rcred);
40516f62314SDavid Greenman 		bp->b_rcred = NOCRED;
40616f62314SDavid Greenman 	}
40716f62314SDavid Greenman 	if (bp->b_wcred != NOCRED) {
40816f62314SDavid Greenman 		crfree(bp->b_wcred);
40916f62314SDavid Greenman 		bp->b_wcred = NOCRED;
41016f62314SDavid Greenman 	}
41116f62314SDavid Greenman 
41216f62314SDavid Greenman 	if (bp->b_vp)
41316f62314SDavid Greenman 		brelvp(bp);
41416f62314SDavid Greenman 
41561854083SDavid Greenman 	if (bp->b_flags & B_WANTED)
41661854083SDavid Greenman 		wakeup((caddr_t)bp);
41761854083SDavid Greenman 
41816f62314SDavid Greenman 	TAILQ_INSERT_HEAD(&bswlist, bp, b_freelist);
41916f62314SDavid Greenman 
42016f62314SDavid Greenman 	if (bswneeded) {
42116f62314SDavid Greenman 		bswneeded = 0;
42216f62314SDavid Greenman 		wakeup((caddr_t)&bswlist);
42316f62314SDavid Greenman 	}
42416f62314SDavid Greenman 	splx(s);
42516f62314SDavid Greenman }
426