only delete space used by inode, on inode deletion; required
[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 *
a9e495d8 10 * @(#)vm_pager.c 7.6 (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
44#include "param.h"
175f072e
KM
45#include "malloc.h"
46
ffe0d082
MK
47#include "vm.h"
48#include "vm_page.h"
49#include "vm_kern.h"
175f072e 50
175f072e
KM
51#include "swappager.h"
52#if NSWAPPAGER > 0
53extern struct pagerops swappagerops;
5a2135db 54#define swappagerops_p &swappagerops
175f072e 55#else
5a2135db 56#define swappagerops_p NULL
175f072e 57#endif
5a2135db 58
175f072e
KM
59#include "vnodepager.h"
60#if NVNODEPAGER > 0
61extern struct pagerops vnodepagerops;
5a2135db 62#define vnodepagerops_p &vnodepagerops
175f072e 63#else
5a2135db 64#define vnodepagerops_p NULL
175f072e 65#endif
5a2135db 66
175f072e
KM
67#include "devpager.h"
68#if NDEVPAGER > 0
69extern struct pagerops devicepagerops;
5a2135db 70#define devicepagerops_p &devicepagerops
175f072e 71#else
5a2135db 72#define devicepagerops_p NULL
175f072e
KM
73#endif
74
75struct pagerops *pagertab[] = {
5a2135db
KM
76 swappagerops_p, /* PG_SWAP */
77 vnodepagerops_p, /* PG_VNODE */
78 devicepagerops_p, /* PG_DEV */
175f072e
KM
79};
80int npagers = sizeof (pagertab) / sizeof (pagertab[0]);
81
ffe0d082 82struct pagerops *dfltpagerops = NULL; /* default pager */
175f072e
KM
83
84/*
85 * Kernel address space for mapping pages.
86 * Used by pagers where KVAs are needed for IO.
87 */
88#define PAGER_MAP_SIZE (256 * PAGE_SIZE)
89vm_map_t pager_map;
11371b93 90vm_offset_t pager_sva, pager_eva;
175f072e
KM
91
92void
93vm_pager_init()
94{
175f072e
KM
95 struct pagerops **pgops;
96
97 /*
98 * Allocate a kernel submap for tracking get/put page mappings
99 */
11371b93 100 pager_map = kmem_suballoc(kernel_map, &pager_sva, &pager_eva,
175f072e
KM
101 PAGER_MAP_SIZE, FALSE);
102 /*
103 * Initialize known pagers
104 */
105 for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++)
106 (*(*pgops)->pgo_init)();
ffe0d082 107 if (dfltpagerops == NULL)
175f072e
KM
108 panic("no default pager");
109}
110
111/*
112 * Allocate an instance of a pager of the given type.
113 */
114vm_pager_t
115vm_pager_allocate(type, handle, size, prot)
116 int type;
117 caddr_t handle;
118 vm_size_t size;
119 vm_prot_t prot;
120{
121 vm_pager_t pager;
122 struct pagerops *ops;
123
124 ops = (type == PG_DFLT) ? dfltpagerops : pagertab[type];
125 return((*ops->pgo_alloc)(handle, size, prot));
126}
127
128void
129vm_pager_deallocate(pager)
130 vm_pager_t pager;
131{
ffe0d082 132 if (pager == NULL)
175f072e
KM
133 panic("vm_pager_deallocate: null pager");
134
135 VM_PAGER_DEALLOC(pager);
136}
137
138vm_pager_get(pager, m, sync)
139 vm_pager_t pager;
140 vm_page_t m;
141 boolean_t sync;
142{
143 extern boolean_t vm_page_zero_fill();
144
ffe0d082 145 if (pager == NULL)
175f072e
KM
146 return(vm_page_zero_fill(m) ? VM_PAGER_OK : VM_PAGER_FAIL);
147 return(VM_PAGER_GET(pager, m, sync));
148}
149
150vm_pager_put(pager, m, sync)
151 vm_pager_t pager;
152 vm_page_t m;
153 boolean_t sync;
154{
ffe0d082 155 if (pager == NULL)
175f072e
KM
156 panic("vm_pager_put: null pager");
157 return(VM_PAGER_PUT(pager, m, sync));
158}
159
160boolean_t
161vm_pager_has_page(pager, offset)
162 vm_pager_t pager;
163 vm_offset_t offset;
164{
ffe0d082 165 if (pager == NULL)
175f072e
KM
166 panic("vm_pager_has_page");
167 return(VM_PAGER_HASPAGE(pager, offset));
168}
169
170/*
171 * Called by pageout daemon before going back to sleep.
172 * Gives pagers a chance to clean up any completed async pageing operations.
173 */
174void
175vm_pager_sync()
176{
177 struct pagerops **pgops;
178
179 for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++)
ffe0d082 180 (*(*pgops)->pgo_putpage)(NULL, NULL, FALSE);
175f072e
KM
181}
182
183vm_offset_t
184vm_pager_map_page(m)
185 vm_page_t m;
186{
187 vm_offset_t kva;
188
11371b93
MH
189#ifdef DEBUG
190 if (!m->busy || m->active)
191 panic("vm_pager_map_page: page active or not busy");
192 if (m->pagerowned)
193 printf("vm_pager_map_page: page %x already in pager\n", m);
194#endif
175f072e 195 kva = kmem_alloc_wait(pager_map, PAGE_SIZE);
11371b93
MH
196#ifdef DEBUG
197 m->pagerowned = 1;
198#endif
175f072e
KM
199 pmap_enter(vm_map_pmap(pager_map), kva, VM_PAGE_TO_PHYS(m),
200 VM_PROT_DEFAULT, TRUE);
175f072e
KM
201 return(kva);
202}
203
204void
205vm_pager_unmap_page(kva)
206 vm_offset_t kva;
207{
11371b93
MH
208#ifdef DEBUG
209 vm_page_t m;
210
211 m = PHYS_TO_VM_PAGE(pmap_extract(vm_map_pmap(pager_map), kva));
175f072e 212#endif
11371b93 213 pmap_remove(vm_map_pmap(pager_map), kva, kva + PAGE_SIZE);
175f072e 214 kmem_free_wakeup(pager_map, kva, PAGE_SIZE);
11371b93
MH
215#ifdef DEBUG
216 if (m->pagerowned)
217 m->pagerowned = 0;
218 else
219 printf("vm_pager_unmap_page: page %x(%x/%x) not owned\n",
220 m, kva, VM_PAGE_TO_PHYS(m));
221#endif
175f072e
KM
222}
223
224vm_pager_t
225vm_pager_lookup(list, handle)
226 register queue_head_t *list;
227 caddr_t handle;
228{
229 register vm_pager_t pager;
230
231 pager = (vm_pager_t) queue_first(list);
232 while (!queue_end(list, (queue_entry_t)pager)) {
233 if (pager->pg_handle == handle)
234 return(pager);
235 pager = (vm_pager_t) queue_next(&pager->pg_list);
236 }
ffe0d082 237 return(NULL);
175f072e
KM
238}
239
240/*
241 * This routine gains a reference to the object.
242 * Explicit deallocation is necessary.
243 */
244pager_cache(object, should_cache)
245 vm_object_t object;
246 boolean_t should_cache;
247{
ffe0d082 248 if (object == NULL)
175f072e
KM
249 return(KERN_INVALID_ARGUMENT);
250
251 vm_object_cache_lock();
252 vm_object_lock(object);
a9e495d8
KM
253 if (should_cache)
254 object->flags |= OBJ_CANPERSIST;
255 else
256 object->flags &= ~OBJ_CANPERSIST;
175f072e
KM
257 vm_object_unlock(object);
258 vm_object_cache_unlock();
259
260 vm_object_deallocate(object);
261
262 return(KERN_SUCCESS);
263}