expand parameters to functions; READDIR drops eofflag;
[unix-history] / usr / src / sys / vm / vm_pager.c
CommitLineData
175f072e 1/*
175f072e
KM
2 * Copyright (c) 1991 Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * The Mach Operating System project at Carnegie-Mellon University.
7 *
0e24ad83 8 * %sccs.include.redist.c%
175f072e 9 *
1692aa9f 10 * @(#)vm_pager.c 7.8 (Berkeley) %G%
0e24ad83
KM
11 *
12 *
13 * Copyright (c) 1987, 1990 Carnegie-Mellon University.
14 * All rights reserved.
15 *
16 * Authors: Avadis Tevanian, Jr., Michael Wayne Young
17 *
18 * Permission to use, copy, modify and distribute this software and
19 * its documentation is hereby granted, provided that both the copyright
20 * notice and this permission notice appear in all copies of the
21 * software, derivative works or modified versions, and any portions
22 * thereof, and that both notices appear in supporting documentation.
23 *
24 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
25 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
26 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
27 *
28 * Carnegie Mellon requests users of this software to return to
29 *
30 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
31 * School of Computer Science
32 * Carnegie Mellon University
33 * Pittsburgh PA 15213-3890
34 *
35 * any improvements or extensions that they make and grant Carnegie the
36 * rights to redistribute these changes.
175f072e
KM
37 */
38
39/*
40 * Paging space routine stubs. Emulates a matchmaker-like interface
41 * for builtin pagers.
42 */
43
1692aa9f
KB
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/malloc.h>
175f072e 47
1692aa9f
KB
48#include <vm/vm.h>
49#include <vm/vm_page.h>
50#include <vm/vm_kern.h>
175f072e 51
175f072e
KM
52#include "swappager.h"
53#if NSWAPPAGER > 0
54extern struct pagerops swappagerops;
5a2135db 55#define swappagerops_p &swappagerops
175f072e 56#endif
5a2135db 57
175f072e
KM
58#include "vnodepager.h"
59#if NVNODEPAGER > 0
60extern struct pagerops vnodepagerops;
5a2135db 61#define vnodepagerops_p &vnodepagerops
175f072e 62#endif
5a2135db 63
175f072e
KM
64#include "devpager.h"
65#if NDEVPAGER > 0
66extern struct pagerops devicepagerops;
5a2135db 67#define devicepagerops_p &devicepagerops
175f072e
KM
68#endif
69
70struct pagerops *pagertab[] = {
1f245e77 71#if NSWAPPAGER > 0
5a2135db 72 swappagerops_p, /* PG_SWAP */
1f245e77
KM
73#endif
74#if NVNODEPAGER > 0
5a2135db 75 vnodepagerops_p, /* PG_VNODE */
1f245e77
KM
76#endif
77#if NDEVPAGER > 0
5a2135db 78 devicepagerops_p, /* PG_DEV */
1f245e77 79#endif
175f072e
KM
80};
81int npagers = sizeof (pagertab) / sizeof (pagertab[0]);
82
ffe0d082 83struct pagerops *dfltpagerops = NULL; /* default pager */
175f072e
KM
84
85/*
86 * Kernel address space for mapping pages.
87 * Used by pagers where KVAs are needed for IO.
88 */
89#define PAGER_MAP_SIZE (256 * PAGE_SIZE)
90vm_map_t pager_map;
11371b93 91vm_offset_t pager_sva, pager_eva;
175f072e
KM
92
93void
94vm_pager_init()
95{
175f072e
KM
96 struct pagerops **pgops;
97
98 /*
99 * Allocate a kernel submap for tracking get/put page mappings
100 */
11371b93 101 pager_map = kmem_suballoc(kernel_map, &pager_sva, &pager_eva,
175f072e
KM
102 PAGER_MAP_SIZE, FALSE);
103 /*
104 * Initialize known pagers
105 */
106 for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++)
107 (*(*pgops)->pgo_init)();
ffe0d082 108 if (dfltpagerops == NULL)
175f072e
KM
109 panic("no default pager");
110}
111
112/*
113 * Allocate an instance of a pager of the given type.
114 */
115vm_pager_t
116vm_pager_allocate(type, handle, size, prot)
117 int type;
118 caddr_t handle;
119 vm_size_t size;
120 vm_prot_t prot;
121{
122 vm_pager_t pager;
123 struct pagerops *ops;
124
125 ops = (type == PG_DFLT) ? dfltpagerops : pagertab[type];
126 return((*ops->pgo_alloc)(handle, size, prot));
127}
128
129void
130vm_pager_deallocate(pager)
131 vm_pager_t pager;
132{
ffe0d082 133 if (pager == NULL)
175f072e
KM
134 panic("vm_pager_deallocate: null pager");
135
136 VM_PAGER_DEALLOC(pager);
137}
138
1692aa9f 139int
175f072e
KM
140vm_pager_get(pager, m, sync)
141 vm_pager_t pager;
142 vm_page_t m;
143 boolean_t sync;
144{
145 extern boolean_t vm_page_zero_fill();
146
ffe0d082 147 if (pager == NULL)
175f072e
KM
148 return(vm_page_zero_fill(m) ? VM_PAGER_OK : VM_PAGER_FAIL);
149 return(VM_PAGER_GET(pager, m, sync));
150}
151
1692aa9f 152int
175f072e
KM
153vm_pager_put(pager, m, sync)
154 vm_pager_t pager;
155 vm_page_t m;
156 boolean_t sync;
157{
ffe0d082 158 if (pager == NULL)
175f072e
KM
159 panic("vm_pager_put: null pager");
160 return(VM_PAGER_PUT(pager, m, sync));
161}
162
163boolean_t
164vm_pager_has_page(pager, offset)
165 vm_pager_t pager;
166 vm_offset_t offset;
167{
ffe0d082 168 if (pager == NULL)
175f072e
KM
169 panic("vm_pager_has_page");
170 return(VM_PAGER_HASPAGE(pager, offset));
171}
172
173/*
174 * Called by pageout daemon before going back to sleep.
175 * Gives pagers a chance to clean up any completed async pageing operations.
176 */
177void
178vm_pager_sync()
179{
180 struct pagerops **pgops;
181
182 for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++)
ffe0d082 183 (*(*pgops)->pgo_putpage)(NULL, NULL, FALSE);
175f072e
KM
184}
185
186vm_offset_t
187vm_pager_map_page(m)
188 vm_page_t m;
189{
190 vm_offset_t kva;
191
11371b93
MH
192#ifdef DEBUG
193 if (!m->busy || m->active)
194 panic("vm_pager_map_page: page active or not busy");
195 if (m->pagerowned)
196 printf("vm_pager_map_page: page %x already in pager\n", m);
197#endif
175f072e 198 kva = kmem_alloc_wait(pager_map, PAGE_SIZE);
11371b93
MH
199#ifdef DEBUG
200 m->pagerowned = 1;
201#endif
175f072e
KM
202 pmap_enter(vm_map_pmap(pager_map), kva, VM_PAGE_TO_PHYS(m),
203 VM_PROT_DEFAULT, TRUE);
175f072e
KM
204 return(kva);
205}
206
207void
208vm_pager_unmap_page(kva)
209 vm_offset_t kva;
210{
11371b93
MH
211#ifdef DEBUG
212 vm_page_t m;
213
214 m = PHYS_TO_VM_PAGE(pmap_extract(vm_map_pmap(pager_map), kva));
175f072e 215#endif
11371b93 216 pmap_remove(vm_map_pmap(pager_map), kva, kva + PAGE_SIZE);
175f072e 217 kmem_free_wakeup(pager_map, kva, PAGE_SIZE);
11371b93
MH
218#ifdef DEBUG
219 if (m->pagerowned)
220 m->pagerowned = 0;
221 else
222 printf("vm_pager_unmap_page: page %x(%x/%x) not owned\n",
223 m, kva, VM_PAGE_TO_PHYS(m));
224#endif
175f072e
KM
225}
226
227vm_pager_t
228vm_pager_lookup(list, handle)
229 register queue_head_t *list;
230 caddr_t handle;
231{
232 register vm_pager_t pager;
233
234 pager = (vm_pager_t) queue_first(list);
235 while (!queue_end(list, (queue_entry_t)pager)) {
236 if (pager->pg_handle == handle)
237 return(pager);
238 pager = (vm_pager_t) queue_next(&pager->pg_list);
239 }
ffe0d082 240 return(NULL);
175f072e
KM
241}
242
243/*
244 * This routine gains a reference to the object.
245 * Explicit deallocation is necessary.
246 */
1692aa9f 247int
175f072e
KM
248pager_cache(object, should_cache)
249 vm_object_t object;
250 boolean_t should_cache;
251{
ffe0d082 252 if (object == NULL)
175f072e
KM
253 return(KERN_INVALID_ARGUMENT);
254
255 vm_object_cache_lock();
256 vm_object_lock(object);
a9e495d8
KM
257 if (should_cache)
258 object->flags |= OBJ_CANPERSIST;
259 else
260 object->flags &= ~OBJ_CANPERSIST;
175f072e
KM
261 vm_object_unlock(object);
262 vm_object_cache_unlock();
263
264 vm_object_deallocate(object);
265
266 return(KERN_SUCCESS);
267}