vm_pager.c (8416) | vm_pager.c (9507) |
---|---|
1/* 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. 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 * 8 * Redistribution and use in source and binary forms, with or without --- 47 unchanged lines hidden (view full) --- 56 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 57 * School of Computer Science 58 * Carnegie Mellon University 59 * Pittsburgh PA 15213-3890 60 * 61 * any improvements or extensions that they make and grant Carnegie the 62 * rights to redistribute these changes. 63 * | 1/* 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. 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 * 8 * Redistribution and use in source and binary forms, with or without --- 47 unchanged lines hidden (view full) --- 56 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 57 * School of Computer Science 58 * Carnegie Mellon University 59 * Pittsburgh PA 15213-3890 60 * 61 * any improvements or extensions that they make and grant Carnegie the 62 * rights to redistribute these changes. 63 * |
64 * $Id: vm_pager.c,v 1.14 1995/04/25 06:22:47 davidg Exp $ | 64 * $Id: vm_pager.c,v 1.15 1995/05/10 18:56:07 davidg Exp $ |
65 */ 66 67/* 68 * Paging space routine stubs. Emulates a matchmaker-like interface 69 * for builtin pagers. 70 */ 71 72#include <sys/param.h> 73#include <sys/systm.h> 74#include <sys/proc.h> 75#include <sys/malloc.h> 76#include <sys/buf.h> 77#include <sys/ucred.h> 78 79#include <vm/vm.h> 80#include <vm/vm_page.h> 81#include <vm/vm_kern.h> | 65 */ 66 67/* 68 * Paging space routine stubs. Emulates a matchmaker-like interface 69 * for builtin pagers. 70 */ 71 72#include <sys/param.h> 73#include <sys/systm.h> 74#include <sys/proc.h> 75#include <sys/malloc.h> 76#include <sys/buf.h> 77#include <sys/ucred.h> 78 79#include <vm/vm.h> 80#include <vm/vm_page.h> 81#include <vm/vm_kern.h> |
82#include <vm/vm_pager.h> |
|
82 | 83 |
84extern struct pagerops defaultpagerops; |
|
83extern struct pagerops swappagerops; 84extern struct pagerops vnodepagerops; 85extern struct pagerops devicepagerops; 86 87struct pagerops *pagertab[] = { | 85extern struct pagerops swappagerops; 86extern struct pagerops vnodepagerops; 87extern struct pagerops devicepagerops; 88 89struct pagerops *pagertab[] = { |
88 &swappagerops, /* PG_SWAP */ 89 &vnodepagerops, /* PG_VNODE */ 90 &devicepagerops, /* PG_DEV */ | 90 &defaultpagerops, /* OBJT_DEFAULT */ 91 &swappagerops, /* OBJT_SWAP */ 92 &vnodepagerops, /* OBJT_VNODE */ 93 &devicepagerops, /* OBJT_DEVICE */ |
91}; 92int npagers = sizeof(pagertab) / sizeof(pagertab[0]); 93 | 94}; 95int npagers = sizeof(pagertab) / sizeof(pagertab[0]); 96 |
94struct pagerops *dfltpagerops = NULL; /* default pager */ 95 | |
96/* 97 * Kernel address space for mapping pages. 98 * Used by pagers where KVAs are needed for IO. 99 * 100 * XXX needs to be large enough to support the number of pending async 101 * cleaning requests (NPENDINGIO == 64) * the maximum swap cluster size 102 * (MAXPHYS == 64k) if you want to get the most efficiency. 103 */ --- 10 unchanged lines hidden (view full) --- 114vm_pager_init() 115{ 116 struct pagerops **pgops; 117 118 /* 119 * Initialize known pagers 120 */ 121 for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++) | 97/* 98 * Kernel address space for mapping pages. 99 * Used by pagers where KVAs are needed for IO. 100 * 101 * XXX needs to be large enough to support the number of pending async 102 * cleaning requests (NPENDINGIO == 64) * the maximum swap cluster size 103 * (MAXPHYS == 64k) if you want to get the most efficiency. 104 */ --- 10 unchanged lines hidden (view full) --- 115vm_pager_init() 116{ 117 struct pagerops **pgops; 118 119 /* 120 * Initialize known pagers 121 */ 122 for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++) |
122 if (pgops) | 123 if (pgops && ((*pgops)->pgo_init != NULL)) |
123 (*(*pgops)->pgo_init) (); | 124 (*(*pgops)->pgo_init) (); |
124 if (dfltpagerops == NULL) 125 panic("no default pager"); | |
126} 127 128void 129vm_pager_bufferinit() 130{ 131 struct buf *bp; 132 int i; 133 --- 15 unchanged lines hidden (view full) --- 149 panic("Not enough pager_map VM space for physical buffers"); 150} 151 152/* 153 * Allocate an instance of a pager of the given type. 154 * Size, protection and offset parameters are passed in for pagers that 155 * need to perform page-level validation (e.g. the device pager). 156 */ | 125} 126 127void 128vm_pager_bufferinit() 129{ 130 struct buf *bp; 131 int i; 132 --- 15 unchanged lines hidden (view full) --- 148 panic("Not enough pager_map VM space for physical buffers"); 149} 150 151/* 152 * Allocate an instance of a pager of the given type. 153 * Size, protection and offset parameters are passed in for pagers that 154 * need to perform page-level validation (e.g. the device pager). 155 */ |
157vm_pager_t | 156vm_object_t |
158vm_pager_allocate(type, handle, size, prot, off) | 157vm_pager_allocate(type, handle, size, prot, off) |
159 int type; | 158 objtype_t type; |
160 void *handle; 161 vm_size_t size; 162 vm_prot_t prot; 163 vm_offset_t off; 164{ 165 struct pagerops *ops; 166 | 159 void *handle; 160 vm_size_t size; 161 vm_prot_t prot; 162 vm_offset_t off; 163{ 164 struct pagerops *ops; 165 |
167 ops = (type == PG_DFLT) ? dfltpagerops : pagertab[type]; | 166 ops = pagertab[type]; |
168 if (ops) 169 return ((*ops->pgo_alloc) (handle, size, prot, off)); 170 return (NULL); 171} 172 173void | 167 if (ops) 168 return ((*ops->pgo_alloc) (handle, size, prot, off)); 169 return (NULL); 170} 171 172void |
174vm_pager_deallocate(pager) 175 vm_pager_t pager; | 173vm_pager_deallocate(object) 174 vm_object_t object; |
176{ | 175{ |
177 if (pager == NULL) 178 panic("vm_pager_deallocate: null pager"); 179 180 (*pager->pg_ops->pgo_dealloc) (pager); | 176 (*pagertab[object->type]->pgo_dealloc) (object); |
181} 182 183 184int | 177} 178 179 180int |
185vm_pager_get_pages(pager, m, count, reqpage, sync) 186 vm_pager_t pager; | 181vm_pager_get_pages(object, m, count, reqpage) 182 vm_object_t object; |
187 vm_page_t *m; 188 int count; 189 int reqpage; | 183 vm_page_t *m; 184 int count; 185 int reqpage; |
190 boolean_t sync; | |
191{ | 186{ |
192 int i; 193 194 if (pager == NULL) { 195 for (i = 0; i < count; i++) { 196 if (i != reqpage) { 197 PAGE_WAKEUP(m[i]); 198 vm_page_free(m[i]); 199 } 200 } 201 vm_page_zero_fill(m[reqpage]); 202 return VM_PAGER_OK; 203 } 204 if (pager->pg_ops->pgo_getpages == 0) { 205 for (i = 0; i < count; i++) { 206 if (i != reqpage) { 207 PAGE_WAKEUP(m[i]); 208 vm_page_free(m[i]); 209 } 210 } 211 return (VM_PAGER_GET(pager, m[reqpage], sync)); 212 } else { 213 return (VM_PAGER_GET_MULTI(pager, m, count, reqpage, sync)); 214 } | 187 return ((*pagertab[object->type]->pgo_getpages)(object, m, count, reqpage)); |
215} 216 217int | 188} 189 190int |
218vm_pager_put_pages(pager, m, count, sync, rtvals) 219 vm_pager_t pager; | 191vm_pager_put_pages(object, m, count, sync, rtvals) 192 vm_object_t object; |
220 vm_page_t *m; 221 int count; 222 boolean_t sync; 223 int *rtvals; 224{ | 193 vm_page_t *m; 194 int count; 195 boolean_t sync; 196 int *rtvals; 197{ |
225 int i; 226 227 if (pager->pg_ops->pgo_putpages) 228 return (VM_PAGER_PUT_MULTI(pager, m, count, sync, rtvals)); 229 else { 230 for (i = 0; i < count; i++) { 231 rtvals[i] = VM_PAGER_PUT(pager, m[i], sync); 232 } 233 return rtvals[0]; 234 } | 198 return ((*pagertab[object->type]->pgo_putpages)(object, m, count, sync, rtvals)); |
235} 236 237boolean_t | 199} 200 201boolean_t |
238vm_pager_has_page(pager, offset) 239 vm_pager_t pager; | 202vm_pager_has_page(object, offset, before, after) 203 vm_object_t object; |
240 vm_offset_t offset; | 204 vm_offset_t offset; |
205 int *before; 206 int *after; |
|
241{ | 207{ |
242 if (pager == NULL) 243 panic("vm_pager_has_page: null pager"); 244 return ((*pager->pg_ops->pgo_haspage) (pager, offset)); | 208 return ((*pagertab[object->type]->pgo_haspage) (object, offset, before, after)); |
245} 246 247/* 248 * Called by pageout daemon before going back to sleep. 249 * Gives pagers a chance to clean up any completed async pageing operations. 250 */ 251void 252vm_pager_sync() 253{ 254 struct pagerops **pgops; 255 256 for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++) | 209} 210 211/* 212 * Called by pageout daemon before going back to sleep. 213 * Gives pagers a chance to clean up any completed async pageing operations. 214 */ 215void 216vm_pager_sync() 217{ 218 struct pagerops **pgops; 219 220 for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++) |
257 if (pgops) 258 (*(*pgops)->pgo_putpage) (NULL, NULL, 0); | 221 if (pgops && ((*pgops)->pgo_sync != NULL)) 222 (*(*pgops)->pgo_sync) (); |
259} 260 | 223} 224 |
261#if 0 262void 263vm_pager_cluster(pager, offset, loff, hoff) 264 vm_pager_t pager; 265 vm_offset_t offset; 266 vm_offset_t *loff; 267 vm_offset_t *hoff; 268{ 269 if (pager == NULL) 270 panic("vm_pager_cluster: null pager"); 271 return ((*pager->pg_ops->pgo_cluster) (pager, offset, loff, hoff)); 272} 273#endif 274 | |
275vm_offset_t 276vm_pager_map_page(m) 277 vm_page_t m; 278{ 279 vm_offset_t kva; 280 281 kva = kmem_alloc_wait(pager_map, PAGE_SIZE); 282 pmap_kenter(kva, VM_PAGE_TO_PHYS(m)); --- 15 unchanged lines hidden (view full) --- 298 vm_offset_t pa; 299 300 pa = pmap_kextract(kva); 301 if (pa == 0) 302 panic("vm_pager_atop"); 303 return (PHYS_TO_VM_PAGE(pa)); 304} 305 | 225vm_offset_t 226vm_pager_map_page(m) 227 vm_page_t m; 228{ 229 vm_offset_t kva; 230 231 kva = kmem_alloc_wait(pager_map, PAGE_SIZE); 232 pmap_kenter(kva, VM_PAGE_TO_PHYS(m)); --- 15 unchanged lines hidden (view full) --- 248 vm_offset_t pa; 249 250 pa = pmap_kextract(kva); 251 if (pa == 0) 252 panic("vm_pager_atop"); 253 return (PHYS_TO_VM_PAGE(pa)); 254} 255 |
306vm_pager_t 307vm_pager_lookup(pglist, handle) 308 register struct pagerlst *pglist; 309 caddr_t handle; | 256vm_object_t 257vm_pager_object_lookup(pg_list, handle) 258 register struct pagerlst *pg_list; 259 void *handle; |
310{ | 260{ |
311 register vm_pager_t pager; | 261 register vm_object_t object; |
312 | 262 |
313 for (pager = pglist->tqh_first; pager; pager = pager->pg_list.tqe_next) 314 if (pager->pg_handle == handle) 315 return (pager); | 263 for (object = pg_list->tqh_first; object != NULL; object = object->pager_object_list.tqe_next) 264 if (object->handle == handle) 265 return (object); |
316 return (NULL); 317} 318 319/* 320 * This routine loses a reference to the object - 321 * thus a reference must be gained before calling. 322 */ 323int 324pager_cache(object, should_cache) 325 vm_object_t object; 326 boolean_t should_cache; 327{ 328 if (object == NULL) 329 return (KERN_INVALID_ARGUMENT); 330 | 266 return (NULL); 267} 268 269/* 270 * This routine loses a reference to the object - 271 * thus a reference must be gained before calling. 272 */ 273int 274pager_cache(object, should_cache) 275 vm_object_t object; 276 boolean_t should_cache; 277{ 278 if (object == NULL) 279 return (KERN_INVALID_ARGUMENT); 280 |
331 vm_object_cache_lock(); 332 vm_object_lock(object); | |
333 if (should_cache) 334 object->flags |= OBJ_CANPERSIST; 335 else 336 object->flags &= ~OBJ_CANPERSIST; | 281 if (should_cache) 282 object->flags |= OBJ_CANPERSIST; 283 else 284 object->flags &= ~OBJ_CANPERSIST; |
337 vm_object_unlock(object); 338 vm_object_cache_unlock(); | |
339 340 vm_object_deallocate(object); 341 342 return (KERN_SUCCESS); 343} 344 345/* 346 * allocate a physical buffer 347 */ 348struct buf * 349getpbuf() 350{ 351 int s; 352 struct buf *bp; 353 354 s = splbio(); 355 /* get a bp from the swap buffer header pool */ 356 while ((bp = bswlist.tqh_first) == NULL) { 357 bswneeded = 1; | 285 286 vm_object_deallocate(object); 287 288 return (KERN_SUCCESS); 289} 290 291/* 292 * allocate a physical buffer 293 */ 294struct buf * 295getpbuf() 296{ 297 int s; 298 struct buf *bp; 299 300 s = splbio(); 301 /* get a bp from the swap buffer header pool */ 302 while ((bp = bswlist.tqh_first) == NULL) { 303 bswneeded = 1; |
358 tsleep((caddr_t) &bswneeded, PVM, "wswbuf", 0); | 304 tsleep(&bswneeded, PVM, "wswbuf", 0); |
359 } 360 TAILQ_REMOVE(&bswlist, bp, b_freelist); 361 splx(s); 362 363 bzero(bp, sizeof *bp); 364 bp->b_rcred = NOCRED; 365 bp->b_wcred = NOCRED; 366 bp->b_data = (caddr_t) (MAXPHYS * (bp - swbuf)) + swapbkva; --- 44 unchanged lines hidden (view full) --- 411 if (bp->b_wcred != NOCRED) { 412 crfree(bp->b_wcred); 413 bp->b_wcred = NOCRED; 414 } 415 if (bp->b_vp) 416 pbrelvp(bp); 417 418 if (bp->b_flags & B_WANTED) | 305 } 306 TAILQ_REMOVE(&bswlist, bp, b_freelist); 307 splx(s); 308 309 bzero(bp, sizeof *bp); 310 bp->b_rcred = NOCRED; 311 bp->b_wcred = NOCRED; 312 bp->b_data = (caddr_t) (MAXPHYS * (bp - swbuf)) + swapbkva; --- 44 unchanged lines hidden (view full) --- 357 if (bp->b_wcred != NOCRED) { 358 crfree(bp->b_wcred); 359 bp->b_wcred = NOCRED; 360 } 361 if (bp->b_vp) 362 pbrelvp(bp); 363 364 if (bp->b_flags & B_WANTED) |
419 wakeup((caddr_t) bp); | 365 wakeup(bp); |
420 421 TAILQ_INSERT_HEAD(&bswlist, bp, b_freelist); 422 423 if (bswneeded) { 424 bswneeded = 0; | 366 367 TAILQ_INSERT_HEAD(&bswlist, bp, b_freelist); 368 369 if (bswneeded) { 370 bswneeded = 0; |
425 wakeup((caddr_t) &bswneeded); | 371 wakeup(&bswneeded); |
426 } 427 splx(s); 428} | 372 } 373 splx(s); 374} |