vnode_pager.c (4797) | vnode_pager.c (5455) |
---|---|
1/* 2 * Copyright (c) 1990 University of Utah. 3 * Copyright (c) 1991 The Regents of the University of California. 4 * All rights reserved. 5 * Copyright (c) 1993,1994 John S. Dyson 6 * 7 * This code is derived from software contributed to Berkeley by 8 * the Systems Programming Group of the University of Utah Computer --- 23 unchanged lines hidden (view full) --- 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * from: @(#)vnode_pager.c 7.5 (Berkeley) 4/20/91 | 1/* 2 * Copyright (c) 1990 University of Utah. 3 * Copyright (c) 1991 The Regents of the University of California. 4 * All rights reserved. 5 * Copyright (c) 1993,1994 John S. Dyson 6 * 7 * This code is derived from software contributed to Berkeley by 8 * the Systems Programming Group of the University of Utah Computer --- 23 unchanged lines hidden (view full) --- 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * from: @(#)vnode_pager.c 7.5 (Berkeley) 4/20/91 |
40 * $Id: vnode_pager.c,v 1.17 1994/11/17 01:22:45 gibbs Exp $ | 40 * $Id: vnode_pager.c,v 1.18 1994/11/24 14:43:22 davidg Exp $ |
41 */ 42 43/* 44 * Page to/from files (vnodes). 45 * 46 * TODO: 47 * pageouts 48 * fix credential use (uses current process credentials now) --- 14 unchanged lines hidden (view full) --- 63 * 1) Totally bypass buffer cache for reads 64 * (Currently will still sometimes use buffer cache for reads) 65 * 2) Bypass buffer cache for writes 66 * (Code does not support it, but mods are simple) 67 */ 68 69#include <sys/param.h> 70#include <sys/systm.h> | 41 */ 42 43/* 44 * Page to/from files (vnodes). 45 * 46 * TODO: 47 * pageouts 48 * fix credential use (uses current process credentials now) --- 14 unchanged lines hidden (view full) --- 63 * 1) Totally bypass buffer cache for reads 64 * (Currently will still sometimes use buffer cache for reads) 65 * 2) Bypass buffer cache for writes 66 * (Code does not support it, but mods are simple) 67 */ 68 69#include <sys/param.h> 70#include <sys/systm.h> |
71#include <sys/kernel.h> |
|
71#include <sys/proc.h> 72#include <sys/malloc.h> 73#include <sys/vnode.h> 74#include <sys/uio.h> 75#include <sys/mount.h> 76 77#include <vm/vm.h> 78#include <vm/vm_page.h> 79#include <vm/vnode_pager.h> 80 81#include <sys/buf.h> 82#include <miscfs/specfs/specdev.h> 83 | 72#include <sys/proc.h> 73#include <sys/malloc.h> 74#include <sys/vnode.h> 75#include <sys/uio.h> 76#include <sys/mount.h> 77 78#include <vm/vm.h> 79#include <vm/vm_page.h> 80#include <vm/vnode_pager.h> 81 82#include <sys/buf.h> 83#include <miscfs/specfs/specdev.h> 84 |
84int vnode_pager_putmulti(); | 85int vnode_pager_putmulti(); |
85 | 86 |
86void vnode_pager_init(); | 87void vnode_pager_init(); |
87vm_pager_t vnode_pager_alloc(caddr_t, vm_offset_t, vm_prot_t, vm_offset_t); | 88vm_pager_t vnode_pager_alloc(caddr_t, vm_offset_t, vm_prot_t, vm_offset_t); |
88void vnode_pager_dealloc(); 89int vnode_pager_getpage(); 90int vnode_pager_getmulti(); 91int vnode_pager_putpage(); | 89void vnode_pager_dealloc(); 90int vnode_pager_getpage(); 91int vnode_pager_getmulti(); 92int vnode_pager_putpage(); |
92boolean_t vnode_pager_haspage(); 93 94struct pagerops vnodepagerops = { 95 vnode_pager_init, 96 vnode_pager_alloc, 97 vnode_pager_dealloc, 98 vnode_pager_getpage, 99 vnode_pager_getmulti, --- 27 unchanged lines hidden (view full) --- 127vnode_pager_alloc(handle, size, prot, offset) 128 caddr_t handle; 129 vm_size_t size; 130 vm_prot_t prot; 131 vm_offset_t offset; 132{ 133 register vm_pager_t pager; 134 register vn_pager_t vnp; | 93boolean_t vnode_pager_haspage(); 94 95struct pagerops vnodepagerops = { 96 vnode_pager_init, 97 vnode_pager_alloc, 98 vnode_pager_dealloc, 99 vnode_pager_getpage, 100 vnode_pager_getmulti, --- 27 unchanged lines hidden (view full) --- 128vnode_pager_alloc(handle, size, prot, offset) 129 caddr_t handle; 130 vm_size_t size; 131 vm_prot_t prot; 132 vm_offset_t offset; 133{ 134 register vm_pager_t pager; 135 register vn_pager_t vnp; |
135 vm_object_t object; | 136 vm_object_t object, tobject; |
136 struct vattr vattr; 137 struct vnode *vp; 138 struct proc *p = curproc; /* XXX */ | 137 struct vattr vattr; 138 struct vnode *vp; 139 struct proc *p = curproc; /* XXX */ |
140 int rtval; |
|
139 140 /* 141 * Pageout to vnode, no can do yet. 142 */ 143 if (handle == NULL) 144 return (NULL); 145 146 /* 147 * Vnodes keep a pointer to any associated pager so no need to lookup 148 * with vm_pager_lookup. 149 */ 150 vp = (struct vnode *) handle; | 141 142 /* 143 * Pageout to vnode, no can do yet. 144 */ 145 if (handle == NULL) 146 return (NULL); 147 148 /* 149 * Vnodes keep a pointer to any associated pager so no need to lookup 150 * with vm_pager_lookup. 151 */ 152 vp = (struct vnode *) handle; |
151 object = (vm_object_t) vp->v_vmdata; | 153 while ((object = (vm_object_t) vp->v_vmdata) && (object->flags & OBJ_DEAD)) 154 tsleep((caddr_t) object, PVM, "vadead", 0); 155 |
152 pager = NULL; | 156 pager = NULL; |
153 if( object != NULL) | 157 if (object != NULL) |
154 pager = object->pager; 155 if (pager == NULL) { 156 157 /* 158 * Allocate pager structures 159 */ 160 pager = (vm_pager_t) malloc(sizeof *pager, M_VMPAGER, M_WAITOK); 161 if (pager == NULL) 162 return (NULL); 163 vnp = (vn_pager_t) malloc(sizeof *vnp, M_VMPGDATA, M_WAITOK); 164 if (vnp == NULL) { 165 free((caddr_t) pager, M_VMPAGER); 166 return (NULL); 167 } | 158 pager = object->pager; 159 if (pager == NULL) { 160 161 /* 162 * Allocate pager structures 163 */ 164 pager = (vm_pager_t) malloc(sizeof *pager, M_VMPAGER, M_WAITOK); 165 if (pager == NULL) 166 return (NULL); 167 vnp = (vn_pager_t) malloc(sizeof *vnp, M_VMPGDATA, M_WAITOK); 168 if (vnp == NULL) { 169 free((caddr_t) pager, M_VMPAGER); 170 return (NULL); 171 } |
168 | |
169 /* 170 * And an object of the appropriate size 171 */ | 172 /* 173 * And an object of the appropriate size 174 */ |
172 if (VOP_GETATTR(vp, &vattr, p->p_ucred, p) == 0) { | 175 if ((rtval = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) == 0) { |
173 object = vm_object_allocate(round_page(vattr.va_size)); 174 vm_object_enter(object, pager); 175 vm_object_setpager(object, pager, 0, TRUE); 176 } else { | 176 object = vm_object_allocate(round_page(vattr.va_size)); 177 vm_object_enter(object, pager); 178 vm_object_setpager(object, pager, 0, TRUE); 179 } else { |
180 printf("Error in getattr: %d\n", rtval); |
|
177 free((caddr_t) vnp, M_VMPGDATA); 178 free((caddr_t) pager, M_VMPAGER); 179 return (NULL); 180 } 181 182 /* 183 * Hold a reference to the vnode and initialize pager data. 184 */ --- 20 unchanged lines hidden (view full) --- 205} 206 207void 208vnode_pager_dealloc(pager) 209 vm_pager_t pager; 210{ 211 register vn_pager_t vnp = (vn_pager_t) pager->pg_data; 212 register struct vnode *vp; | 181 free((caddr_t) vnp, M_VMPGDATA); 182 free((caddr_t) pager, M_VMPAGER); 183 return (NULL); 184 } 185 186 /* 187 * Hold a reference to the vnode and initialize pager data. 188 */ --- 20 unchanged lines hidden (view full) --- 209} 210 211void 212vnode_pager_dealloc(pager) 213 vm_pager_t pager; 214{ 215 register vn_pager_t vnp = (vn_pager_t) pager->pg_data; 216 register struct vnode *vp; |
217 vm_object_t object; |
|
213 214 vp = vnp->vnp_vp; 215 if (vp) { | 218 219 vp = vnp->vnp_vp; 220 if (vp) { |
221 int s = splbio(); 222 223 object = (vm_object_t) vp->v_vmdata; 224 if (object) { 225 while (object->paging_in_progress) { 226 tsleep(object, PVM, "vnpdea", 0); 227 } 228 } 229 splx(s); 230 |
|
216 vp->v_vmdata = NULL; | 231 vp->v_vmdata = NULL; |
217 vp->v_flag &= ~(VTEXT|VVMIO); | 232 vp->v_flag &= ~(VTEXT | VVMIO); |
218 vrele(vp); 219 } 220 TAILQ_REMOVE(&vnode_pager_list, pager, pg_list); 221 free((caddr_t) vnp, M_VMPGDATA); 222 free((caddr_t) pager, M_VMPAGER); 223} 224 225int 226vnode_pager_getmulti(pager, m, count, reqpage, sync) 227 vm_pager_t pager; 228 vm_page_t *m; | 233 vrele(vp); 234 } 235 TAILQ_REMOVE(&vnode_pager_list, pager, pg_list); 236 free((caddr_t) vnp, M_VMPGDATA); 237 free((caddr_t) pager, M_VMPAGER); 238} 239 240int 241vnode_pager_getmulti(pager, m, count, reqpage, sync) 242 vm_pager_t pager; 243 vm_page_t *m; |
229 int count; 230 int reqpage; | 244 int count; 245 int reqpage; |
231 boolean_t sync; 232{ 233 234 return vnode_pager_input((vn_pager_t) pager->pg_data, m, count, reqpage); 235} 236 237int 238vnode_pager_getpage(pager, m, sync) --- 13 unchanged lines hidden (view full) --- 252 253boolean_t 254vnode_pager_putpage(pager, m, sync) 255 vm_pager_t pager; 256 vm_page_t m; 257 boolean_t sync; 258{ 259 vm_page_t marray[1]; | 246 boolean_t sync; 247{ 248 249 return vnode_pager_input((vn_pager_t) pager->pg_data, m, count, reqpage); 250} 251 252int 253vnode_pager_getpage(pager, m, sync) --- 13 unchanged lines hidden (view full) --- 267 268boolean_t 269vnode_pager_putpage(pager, m, sync) 270 vm_pager_t pager; 271 vm_page_t m; 272 boolean_t sync; 273{ 274 vm_page_t marray[1]; |
260 int rtvals[1]; | 275 int rtvals[1]; |
261 262 if (pager == NULL) 263 return FALSE; 264 marray[0] = m; 265 vnode_pager_output((vn_pager_t) pager->pg_data, marray, 1, rtvals); 266 return rtvals[0]; 267} 268 269int 270vnode_pager_putmulti(pager, m, c, sync, rtvals) 271 vm_pager_t pager; 272 vm_page_t *m; | 276 277 if (pager == NULL) 278 return FALSE; 279 marray[0] = m; 280 vnode_pager_output((vn_pager_t) pager->pg_data, marray, 1, rtvals); 281 return rtvals[0]; 282} 283 284int 285vnode_pager_putmulti(pager, m, c, sync, rtvals) 286 vm_pager_t pager; 287 vm_page_t *m; |
273 int c; | 288 int c; |
274 boolean_t sync; | 289 boolean_t sync; |
275 int *rtvals; | 290 int *rtvals; |
276{ 277 return vnode_pager_output((vn_pager_t) pager->pg_data, m, c, rtvals); 278} 279 280 281boolean_t 282vnode_pager_haspage(pager, offset) 283 vm_pager_t pager; 284 vm_offset_t offset; 285{ 286 register vn_pager_t vnp = (vn_pager_t) pager->pg_data; 287 register struct vnode *vp = vnp->vnp_vp; 288 daddr_t bn; | 291{ 292 return vnode_pager_output((vn_pager_t) pager->pg_data, m, c, rtvals); 293} 294 295 296boolean_t 297vnode_pager_haspage(pager, offset) 298 vm_pager_t pager; 299 vm_offset_t offset; 300{ 301 register vn_pager_t vnp = (vn_pager_t) pager->pg_data; 302 register struct vnode *vp = vnp->vnp_vp; 303 daddr_t bn; |
289 int err; | 304 int err; |
290 daddr_t block; 291 292 /* | 305 daddr_t block; 306 307 /* |
293 * If filesystem no longer mounted or offset beyond end of 294 * file we do not have the page. | 308 * If filesystem no longer mounted or offset beyond end of file we do 309 * not have the page. |
295 */ 296 if ((vp->v_mount == NULL) || (offset >= vnp->vnp_size)) 297 return FALSE; 298 299 block = offset / vp->v_mount->mnt_stat.f_iosize; 300 if (incore(vp, block)) 301 return TRUE; 302 /* 303 * Read the index to find the disk block to read from. If there is no 304 * block, report that we don't have this data. 305 * 306 * Assumes that the vnode has whole page or nothing. 307 */ 308 err = VOP_BMAP(vp, block, (struct vnode **) 0, &bn, 0); | 310 */ 311 if ((vp->v_mount == NULL) || (offset >= vnp->vnp_size)) 312 return FALSE; 313 314 block = offset / vp->v_mount->mnt_stat.f_iosize; 315 if (incore(vp, block)) 316 return TRUE; 317 /* 318 * Read the index to find the disk block to read from. If there is no 319 * block, report that we don't have this data. 320 * 321 * Assumes that the vnode has whole page or nothing. 322 */ 323 err = VOP_BMAP(vp, block, (struct vnode **) 0, &bn, 0); |
309/* 310 printf("vnode_pager_haspage: (%d)0x%x: err: %d, bn: %d\n", 311 offset, offset, err, bn); 312*/ 313 if (err) { | 324 if (err) |
314 return (TRUE); | 325 return (TRUE); |
315 } | |
316 return ((long) bn < 0 ? FALSE : TRUE); 317} 318 319/* 320 * Lets the VM system know about a change in size for a file. 321 * If this vnode is mapped into some address space (i.e. we have a pager 322 * for it) we adjust our own internal size and flush any cached pages in 323 * the associated object that are affected by the size change. 324 * 325 * Note: this routine may be invoked as a result of a pager put 326 * operation (possibly at object termination time), so we must be careful. 327 */ 328void 329vnode_pager_setsize(vp, nsize) 330 struct vnode *vp; | 326 return ((long) bn < 0 ? FALSE : TRUE); 327} 328 329/* 330 * Lets the VM system know about a change in size for a file. 331 * If this vnode is mapped into some address space (i.e. we have a pager 332 * for it) we adjust our own internal size and flush any cached pages in 333 * the associated object that are affected by the size change. 334 * 335 * Note: this routine may be invoked as a result of a pager put 336 * operation (possibly at object termination time), so we must be careful. 337 */ 338void 339vnode_pager_setsize(vp, nsize) 340 struct vnode *vp; |
331 u_long nsize; | 341 u_long nsize; |
332{ 333 register vn_pager_t vnp; 334 register vm_object_t object; 335 vm_pager_t pager; 336 337 /* 338 * Not a mapped vnode 339 */ 340 if (vp == NULL || vp->v_type != VREG || vp->v_vmdata == NULL) 341 return; 342 343 /* 344 * Hasn't changed size 345 */ 346 object = (vm_object_t) vp->v_vmdata; | 342{ 343 register vn_pager_t vnp; 344 register vm_object_t object; 345 vm_pager_t pager; 346 347 /* 348 * Not a mapped vnode 349 */ 350 if (vp == NULL || vp->v_type != VREG || vp->v_vmdata == NULL) 351 return; 352 353 /* 354 * Hasn't changed size 355 */ 356 object = (vm_object_t) vp->v_vmdata; |
347 if( object == NULL) | 357 if (object == NULL) |
348 return; | 358 return; |
349 if( (pager = object->pager) == NULL) | 359 if ((pager = object->pager) == NULL) |
350 return; 351 vnp = (vn_pager_t) pager->pg_data; 352 if (nsize == vnp->vnp_size) 353 return; 354 355 /* 356 * No object. This can happen during object termination since 357 * vm_object_page_clean is called after the object has been removed 358 * from the hash table, and clean may cause vnode write operations 359 * which can wind up back here. 360 */ 361 object = vm_object_lookup(pager); 362 if (object == NULL) 363 return; 364 365 /* 366 * File has shrunk. Toss any cached pages beyond the new EOF. 367 */ 368 if (nsize < vnp->vnp_size) { | 360 return; 361 vnp = (vn_pager_t) pager->pg_data; 362 if (nsize == vnp->vnp_size) 363 return; 364 365 /* 366 * No object. This can happen during object termination since 367 * vm_object_page_clean is called after the object has been removed 368 * from the hash table, and clean may cause vnode write operations 369 * which can wind up back here. 370 */ 371 object = vm_object_lookup(pager); 372 if (object == NULL) 373 return; 374 375 /* 376 * File has shrunk. Toss any cached pages beyond the new EOF. 377 */ 378 if (nsize < vnp->vnp_size) { |
369 vm_object_lock(object); 370 vm_object_page_remove(object, 371 round_page((vm_offset_t) nsize), vnp->vnp_size); 372 vm_object_unlock(object); 373 | 379 if (round_page((vm_offset_t) nsize) < vnp->vnp_size) { 380 vm_object_lock(object); 381 vm_object_page_remove(object, 382 round_page((vm_offset_t) nsize), vnp->vnp_size); 383 vm_object_unlock(object); 384 } |
374 /* 375 * this gets rid of garbage at the end of a page that is now 376 * only partially backed by the vnode... 377 */ 378 if (nsize & PAGE_MASK) { 379 vm_offset_t kva; 380 vm_page_t m; 381 382 m = vm_page_lookup(object, trunc_page((vm_offset_t) nsize)); 383 if (m) { 384 kva = vm_pager_map_page(m); 385 bzero((caddr_t) kva + (nsize & PAGE_MASK), | 385 /* 386 * this gets rid of garbage at the end of a page that is now 387 * only partially backed by the vnode... 388 */ 389 if (nsize & PAGE_MASK) { 390 vm_offset_t kva; 391 vm_page_t m; 392 393 m = vm_page_lookup(object, trunc_page((vm_offset_t) nsize)); 394 if (m) { 395 kva = vm_pager_map_page(m); 396 bzero((caddr_t) kva + (nsize & PAGE_MASK), |
386 round_page(nsize) - nsize); | 397 round_page(nsize) - nsize); |
387 vm_pager_unmap_page(kva); 388 } 389 } | 398 vm_pager_unmap_page(kva); 399 } 400 } |
390 } else { 391 392 /* 393 * this allows the filesystem and VM cache to stay in sync if 394 * the VM page hasn't been modified... After the page is 395 * removed -- it will be faulted back in from the filesystem 396 * cache. 397 */ 398 if (vnp->vnp_size & PAGE_MASK) { 399 vm_page_t m; 400 401 m = vm_page_lookup(object, trunc_page(vnp->vnp_size)); 402 if (m && (m->flags & PG_CLEAN)) { 403 vm_object_lock(object); 404 vm_object_page_remove(object, 405 vnp->vnp_size, vnp->vnp_size); 406 vm_object_unlock(object); 407 } 408 } | |
409 } 410 vnp->vnp_size = (vm_offset_t) nsize; 411 object->size = round_page(nsize); 412 413 vm_object_deallocate(object); 414} 415 416void --- 31 unchanged lines hidden (view full) --- 448 register vm_object_t object; 449 boolean_t uncached, locked; 450 vm_pager_t pager; 451 452 /* 453 * Not a mapped vnode 454 */ 455 object = (vm_object_t) vp->v_vmdata; | 401 } 402 vnp->vnp_size = (vm_offset_t) nsize; 403 object->size = round_page(nsize); 404 405 vm_object_deallocate(object); 406} 407 408void --- 31 unchanged lines hidden (view full) --- 440 register vm_object_t object; 441 boolean_t uncached, locked; 442 vm_pager_t pager; 443 444 /* 445 * Not a mapped vnode 446 */ 447 object = (vm_object_t) vp->v_vmdata; |
456 if( object == NULL) 457 return(TRUE); | 448 if (object == NULL) 449 return (TRUE); 450 |
458 pager = object->pager; 459 if (pager == NULL) 460 return (TRUE); 461 462 /* 463 * Unlock the vnode if it is currently locked. We do this since 464 * uncaching the object may result in its destruction which may 465 * initiate paging activity which may necessitate locking the vnode. --- 30 unchanged lines hidden (view full) --- 496 * calculate the linear (byte) disk address of specified virtual 497 * file address 498 */ 499vm_offset_t 500vnode_pager_addr(vp, address) 501 struct vnode *vp; 502 vm_offset_t address; 503{ | 451 pager = object->pager; 452 if (pager == NULL) 453 return (TRUE); 454 455 /* 456 * Unlock the vnode if it is currently locked. We do this since 457 * uncaching the object may result in its destruction which may 458 * initiate paging activity which may necessitate locking the vnode. --- 30 unchanged lines hidden (view full) --- 489 * calculate the linear (byte) disk address of specified virtual 490 * file address 491 */ 492vm_offset_t 493vnode_pager_addr(vp, address) 494 struct vnode *vp; 495 vm_offset_t address; 496{ |
504 int rtaddress; 505 int bsize; | 497 int rtaddress; 498 int bsize; |
506 vm_offset_t block; 507 struct vnode *rtvp; | 499 vm_offset_t block; 500 struct vnode *rtvp; |
508 int err; 509 int vblock, voffset; | 501 int err; 502 int vblock, voffset; |
510 | 503 |
504 if ((int) address < 0) 505 return -1; 506 |
|
511 bsize = vp->v_mount->mnt_stat.f_iosize; 512 vblock = address / bsize; 513 voffset = address % bsize; 514 515 err = VOP_BMAP(vp, vblock, &rtvp, &block, 0); 516 517 if (err) 518 rtaddress = -1; --- 7 unchanged lines hidden (view full) --- 526 * interrupt routine for I/O completion 527 */ 528void 529vnode_pager_iodone(bp) 530 struct buf *bp; 531{ 532 bp->b_flags |= B_DONE; 533 wakeup((caddr_t) bp); | 507 bsize = vp->v_mount->mnt_stat.f_iosize; 508 vblock = address / bsize; 509 voffset = address % bsize; 510 511 err = VOP_BMAP(vp, vblock, &rtvp, &block, 0); 512 513 if (err) 514 rtaddress = -1; --- 7 unchanged lines hidden (view full) --- 522 * interrupt routine for I/O completion 523 */ 524void 525vnode_pager_iodone(bp) 526 struct buf *bp; 527{ 528 bp->b_flags |= B_DONE; 529 wakeup((caddr_t) bp); |
534 if( bp->b_flags & B_ASYNC) { | 530 if (bp->b_flags & B_ASYNC) { |
535 vm_offset_t paddr; 536 vm_page_t m; 537 vm_object_t obj = 0; 538 int i; 539 int npages; 540 541 paddr = (vm_offset_t) bp->b_data; | 531 vm_offset_t paddr; 532 vm_page_t m; 533 vm_object_t obj = 0; 534 int i; 535 int npages; 536 537 paddr = (vm_offset_t) bp->b_data; |
542 if( bp->b_bufsize != bp->b_bcount) 543 bzero( bp->b_data + bp->b_bcount, 544 bp->b_bufsize - bp->b_bcount); | 538 if (bp->b_bufsize != bp->b_bcount) 539 bzero(bp->b_data + bp->b_bcount, 540 bp->b_bufsize - bp->b_bcount); |
545 546 npages = (bp->b_bufsize + PAGE_SIZE - 1) / PAGE_SIZE; | 541 542 npages = (bp->b_bufsize + PAGE_SIZE - 1) / PAGE_SIZE; |
547/* 548 printf("bcount: %d, bufsize: %d, npages: %d\n", 549 bp->b_bcount, bp->b_bufsize, npages); 550*/ 551 for( i = 0; i < npages; i++) { | 543 for (i = 0; i < npages; i++) { |
552 m = PHYS_TO_VM_PAGE(pmap_kextract(paddr + i * PAGE_SIZE)); 553 obj = m->object; | 544 m = PHYS_TO_VM_PAGE(pmap_kextract(paddr + i * PAGE_SIZE)); 545 obj = m->object; |
554 if( m) { 555 m->flags |= PG_CLEAN; 556 m->flags &= ~(PG_LAUNDRY|PG_FAKE); | 546 if (m) { 547 m->dirty = 0; 548 m->valid = VM_PAGE_BITS_ALL; 549 if (m->flags & PG_WANTED) 550 m->flags |= PG_REFERENCED; |
557 PAGE_WAKEUP(m); 558 } else { 559 panic("vnode_pager_iodone: page is gone!!!"); 560 } 561 } | 551 PAGE_WAKEUP(m); 552 } else { 553 panic("vnode_pager_iodone: page is gone!!!"); 554 } 555 } |
562 pmap_qremove( paddr, npages); 563 if( obj) { | 556 pmap_qremove(paddr, npages); 557 if (obj) { |
564 --obj->paging_in_progress; | 558 --obj->paging_in_progress; |
565 if( obj->paging_in_progress == 0) | 559 if (obj->paging_in_progress == 0) |
566 wakeup((caddr_t) obj); 567 } else { 568 panic("vnode_pager_iodone: object is gone???"); 569 } | 560 wakeup((caddr_t) obj); 561 } else { 562 panic("vnode_pager_iodone: object is gone???"); 563 } |
570 HOLDRELE(bp->b_vp); | |
571 relpbuf(bp); 572 } 573} 574 575/* 576 * small block file system vnode pager input 577 */ 578int 579vnode_pager_input_smlfs(vnp, m) 580 vn_pager_t vnp; 581 vm_page_t m; 582{ | 564 relpbuf(bp); 565 } 566} 567 568/* 569 * small block file system vnode pager input 570 */ 571int 572vnode_pager_input_smlfs(vnp, m) 573 vn_pager_t vnp; 574 vm_page_t m; 575{ |
583 int i; 584 int s; 585 vm_offset_t paging_offset; | 576 int i; 577 int s; |
586 struct vnode *dp, *vp; 587 struct buf *bp; | 578 struct vnode *dp, *vp; 579 struct buf *bp; |
588 vm_offset_t foff; | |
589 vm_offset_t kva; | 580 vm_offset_t kva; |
590 int fileaddr; 591 int block; | 581 int fileaddr; 582 int block; |
592 vm_offset_t bsize; | 583 vm_offset_t bsize; |
593 int error = 0; | 584 int error = 0; |
594 | 585 |
595 paging_offset = m->object->paging_offset; | |
596 vp = vnp->vnp_vp; 597 bsize = vp->v_mount->mnt_stat.f_iosize; | 586 vp = vnp->vnp_vp; 587 bsize = vp->v_mount->mnt_stat.f_iosize; |
598 foff = m->offset + paging_offset; | |
599 | 588 |
600 VOP_BMAP(vp, foff, &dp, 0, 0); | 589 VOP_BMAP(vp, 0, &dp, 0, 0); |
601 602 kva = vm_pager_map_page(m); 603 604 for (i = 0; i < PAGE_SIZE / bsize; i++) { 605 | 590 591 kva = vm_pager_map_page(m); 592 593 for (i = 0; i < PAGE_SIZE / bsize; i++) { 594 |
606 /* 607 * calculate logical block and offset 608 */ 609 block = foff / bsize + i; 610 s = splbio(); 611 while ((bp = incore(vp, block)) != 0) { 612 int amount; | 595 if ((vm_page_bits(m->offset + i * bsize, bsize) & m->valid)) 596 continue; |
613 | 597 |
614 /* 615 * wait until the buffer is avail or gone 616 */ 617 if (bp->b_flags & B_BUSY) { 618 bp->b_flags |= B_WANTED; 619 tsleep((caddr_t) bp, PVM, "vnwblk", 0); 620 continue; 621 } 622 amount = bsize; 623 if ((foff + bsize) > vnp->vnp_size) 624 amount = vnp->vnp_size - foff; 625 626 /* 627 * make sure that this page is in the buffer 628 */ 629 if ((amount > 0) && amount <= bp->b_bcount) { 630 bp->b_flags |= B_BUSY; 631 splx(s); 632 633 /* 634 * copy the data from the buffer 635 */ 636 bcopy(bp->b_un.b_addr, (caddr_t) kva + i * bsize, amount); 637 if (amount < bsize) { 638 bzero((caddr_t) kva + amount, bsize - amount); 639 } 640 bp->b_flags &= ~B_BUSY; 641 wakeup((caddr_t) bp); 642 goto nextblock; 643 } 644 break; 645 } 646 splx(s); 647 fileaddr = vnode_pager_addr(vp, foff + i * bsize); | 598 fileaddr = vnode_pager_addr(vp, m->offset + i * bsize); |
648 if (fileaddr != -1) { 649 bp = getpbuf(); | 599 if (fileaddr != -1) { 600 bp = getpbuf(); |
650 VHOLD(vp); | |
651 652 /* build a minimal buffer header */ 653 bp->b_flags = B_BUSY | B_READ | B_CALL; 654 bp->b_iodone = vnode_pager_iodone; 655 bp->b_proc = curproc; 656 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred; 657 if (bp->b_rcred != NOCRED) 658 crhold(bp->b_rcred); 659 if (bp->b_wcred != NOCRED) 660 crhold(bp->b_wcred); 661 bp->b_un.b_addr = (caddr_t) kva + i * bsize; 662 bp->b_blkno = fileaddr / DEV_BSIZE; | 601 602 /* build a minimal buffer header */ 603 bp->b_flags = B_BUSY | B_READ | B_CALL; 604 bp->b_iodone = vnode_pager_iodone; 605 bp->b_proc = curproc; 606 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred; 607 if (bp->b_rcred != NOCRED) 608 crhold(bp->b_rcred); 609 if (bp->b_wcred != NOCRED) 610 crhold(bp->b_wcred); 611 bp->b_un.b_addr = (caddr_t) kva + i * bsize; 612 bp->b_blkno = fileaddr / DEV_BSIZE; |
663 bgetvp(dp, bp); | 613 pbgetvp(dp, bp); |
664 bp->b_bcount = bsize; 665 bp->b_bufsize = bsize; 666 667 /* do the input */ 668 VOP_STRATEGY(bp); 669 670 /* we definitely need to be at splbio here */ 671 --- 7 unchanged lines hidden (view full) --- 679 680 /* 681 * free the buffer header back to the swap buffer pool 682 */ 683 relpbuf(bp); 684 HOLDRELE(vp); 685 if (error) 686 break; | 614 bp->b_bcount = bsize; 615 bp->b_bufsize = bsize; 616 617 /* do the input */ 618 VOP_STRATEGY(bp); 619 620 /* we definitely need to be at splbio here */ 621 --- 7 unchanged lines hidden (view full) --- 629 630 /* 631 * free the buffer header back to the swap buffer pool 632 */ 633 relpbuf(bp); 634 HOLDRELE(vp); 635 if (error) 636 break; |
637 638 vm_page_set_clean(m, i * bsize, bsize); 639 vm_page_set_valid(m, i * bsize, bsize); |
|
687 } else { | 640 } else { |
641 vm_page_set_clean(m, i * bsize, bsize); |
|
688 bzero((caddr_t) kva + i * bsize, bsize); 689 } 690nextblock: 691 } 692 vm_pager_unmap_page(kva); | 642 bzero((caddr_t) kva + i * bsize, bsize); 643 } 644nextblock: 645 } 646 vm_pager_unmap_page(kva); |
647 pmap_clear_modify(VM_PAGE_TO_PHYS(m)); |
|
693 if (error) { 694 return VM_PAGER_ERROR; 695 } | 648 if (error) { 649 return VM_PAGER_ERROR; 650 } |
696 pmap_clear_modify(VM_PAGE_TO_PHYS(m)); 697 m->flags |= PG_CLEAN; 698 m->flags &= ~PG_LAUNDRY; | |
699 return VM_PAGER_OK; 700 701} 702 703 704/* 705 * old style vnode pager output routine 706 */ 707int 708vnode_pager_input_old(vnp, m) 709 vn_pager_t vnp; 710 vm_page_t m; 711{ 712 struct uio auio; 713 struct iovec aiov; | 651 return VM_PAGER_OK; 652 653} 654 655 656/* 657 * old style vnode pager output routine 658 */ 659int 660vnode_pager_input_old(vnp, m) 661 vn_pager_t vnp; 662 vm_page_t m; 663{ 664 struct uio auio; 665 struct iovec aiov; |
714 int error; 715 int size; 716 vm_offset_t foff; | 666 int error; 667 int size; |
717 vm_offset_t kva; 718 719 error = 0; | 668 vm_offset_t kva; 669 670 error = 0; |
720 foff = m->offset + m->object->paging_offset; | |
721 722 /* 723 * Return failure if beyond current EOF 724 */ | 671 672 /* 673 * Return failure if beyond current EOF 674 */ |
725 if (foff >= vnp->vnp_size) { | 675 if (m->offset >= vnp->vnp_size) { |
726 return VM_PAGER_BAD; 727 } else { 728 size = PAGE_SIZE; | 676 return VM_PAGER_BAD; 677 } else { 678 size = PAGE_SIZE; |
729 if (foff + size > vnp->vnp_size) 730 size = vnp->vnp_size - foff; 731/* 732 * Allocate a kernel virtual address and initialize so that 733 * we can use VOP_READ/WRITE routines. 734 */ | 679 if (m->offset + size > vnp->vnp_size) 680 size = vnp->vnp_size - m->offset; 681 /* 682 * Allocate a kernel virtual address and initialize so that 683 * we can use VOP_READ/WRITE routines. 684 */ |
735 kva = vm_pager_map_page(m); 736 aiov.iov_base = (caddr_t) kva; 737 aiov.iov_len = size; 738 auio.uio_iov = &aiov; 739 auio.uio_iovcnt = 1; | 685 kva = vm_pager_map_page(m); 686 aiov.iov_base = (caddr_t) kva; 687 aiov.iov_len = size; 688 auio.uio_iov = &aiov; 689 auio.uio_iovcnt = 1; |
740 auio.uio_offset = foff; | 690 auio.uio_offset = m->offset; |
741 auio.uio_segflg = UIO_SYSSPACE; 742 auio.uio_rw = UIO_READ; 743 auio.uio_resid = size; 744 auio.uio_procp = (struct proc *) 0; 745 746 error = VOP_READ(vnp->vnp_vp, &auio, 0, curproc->p_ucred); 747 if (!error) { 748 register int count = size - auio.uio_resid; 749 750 if (count == 0) 751 error = EINVAL; 752 else if (count != PAGE_SIZE) 753 bzero((caddr_t) kva + count, PAGE_SIZE - count); 754 } 755 vm_pager_unmap_page(kva); 756 } 757 pmap_clear_modify(VM_PAGE_TO_PHYS(m)); | 691 auio.uio_segflg = UIO_SYSSPACE; 692 auio.uio_rw = UIO_READ; 693 auio.uio_resid = size; 694 auio.uio_procp = (struct proc *) 0; 695 696 error = VOP_READ(vnp->vnp_vp, &auio, 0, curproc->p_ucred); 697 if (!error) { 698 register int count = size - auio.uio_resid; 699 700 if (count == 0) 701 error = EINVAL; 702 else if (count != PAGE_SIZE) 703 bzero((caddr_t) kva + count, PAGE_SIZE - count); 704 } 705 vm_pager_unmap_page(kva); 706 } 707 pmap_clear_modify(VM_PAGE_TO_PHYS(m)); |
758 m->flags |= PG_CLEAN; 759 m->flags &= ~PG_LAUNDRY; | 708 m->dirty = 0; |
760 return error ? VM_PAGER_ERROR : VM_PAGER_OK; 761} 762 763/* 764 * generic vnode pager input routine 765 */ 766int 767vnode_pager_input(vnp, m, count, reqpage) 768 register vn_pager_t vnp; 769 vm_page_t *m; | 709 return error ? VM_PAGER_ERROR : VM_PAGER_OK; 710} 711 712/* 713 * generic vnode pager input routine 714 */ 715int 716vnode_pager_input(vnp, m, count, reqpage) 717 register vn_pager_t vnp; 718 vm_page_t *m; |
770 int count, reqpage; | 719 int count, reqpage; |
771{ | 720{ |
772 int i; | 721 int i; |
773 vm_offset_t kva, foff; | 722 vm_offset_t kva, foff; |
774 int size, sizea; | 723 int size, sizea; |
775 vm_object_t object; | 724 vm_object_t object; |
776 vm_offset_t paging_offset; | |
777 struct vnode *dp, *vp; | 725 struct vnode *dp, *vp; |
778 int bsize; | 726 int bsize; |
779 | 727 |
780 int first, last; 781 int reqaddr, firstaddr; 782 int block, offset; | 728 int first, last; 729 int reqaddr, firstaddr; 730 int block, offset; |
783 784 struct buf *bp, *bpa; | 731 732 struct buf *bp, *bpa; |
785 int counta; 786 int s; 787 int failflag; | 733 int counta; 734 int s; 735 int failflag; |
788 | 736 |
789 int error = 0; | 737 int error = 0; |
790 791 object = m[reqpage]->object; /* all vm_page_t items are in same 792 * object */ | 738 739 object = m[reqpage]->object; /* all vm_page_t items are in same 740 * object */ |
793 paging_offset = object->paging_offset; | |
794 795 vp = vnp->vnp_vp; | 741 742 vp = vnp->vnp_vp; |
796 797 /* 798 * Make sure underlying filesystem is still mounted. 799 */ 800 if (vp->v_mount == NULL) 801 return VM_PAGER_FAIL; 802 | |
803 bsize = vp->v_mount->mnt_stat.f_iosize; 804 805 /* get the UNDERLYING device for the file with VOP_BMAP() */ 806 807 /* 808 * originally, we did not check for an error return value -- assuming 809 * an fs always has a bmap entry point -- that assumption is wrong!!! 810 */ | 743 bsize = vp->v_mount->mnt_stat.f_iosize; 744 745 /* get the UNDERLYING device for the file with VOP_BMAP() */ 746 747 /* 748 * originally, we did not check for an error return value -- assuming 749 * an fs always has a bmap entry point -- that assumption is wrong!!! 750 */ |
811 foff = m[reqpage]->offset + paging_offset; | 751 foff = m[reqpage]->offset; |
812 813 /* 814 * if we can't bmap, use old VOP code 815 */ | 752 753 /* 754 * if we can't bmap, use old VOP code 755 */ |
816 if (VOP_BMAP(vp, foff, &dp, 0, 0)) { | 756 if (VOP_BMAP(vp, 0, &dp, 0, 0)) { |
817 for (i = 0; i < count; i++) { 818 if (i != reqpage) { 819 vnode_pager_freepage(m[i]); 820 } 821 } 822 cnt.v_vnodein++; 823 cnt.v_vnodepgsin++; 824 return vnode_pager_input_old(vnp, m[reqpage]); 825 826 /* 827 * if the blocksize is smaller than a page size, then use 828 * special small filesystem code. NFS sometimes has a small 829 * blocksize, but it can handle large reads itself. 830 */ 831 } else if ((PAGE_SIZE / bsize) > 1 && | 757 for (i = 0; i < count; i++) { 758 if (i != reqpage) { 759 vnode_pager_freepage(m[i]); 760 } 761 } 762 cnt.v_vnodein++; 763 cnt.v_vnodepgsin++; 764 return vnode_pager_input_old(vnp, m[reqpage]); 765 766 /* 767 * if the blocksize is smaller than a page size, then use 768 * special small filesystem code. NFS sometimes has a small 769 * blocksize, but it can handle large reads itself. 770 */ 771 } else if ((PAGE_SIZE / bsize) > 1 && |
832 (vp->v_mount->mnt_stat.f_type != MOUNT_NFS)) { | 772 (vp->v_mount->mnt_stat.f_type != MOUNT_NFS)) { |
833 834 for (i = 0; i < count; i++) { 835 if (i != reqpage) { 836 vnode_pager_freepage(m[i]); 837 } 838 } 839 cnt.v_vnodein++; 840 cnt.v_vnodepgsin++; 841 return vnode_pager_input_smlfs(vnp, m[reqpage]); 842 } | 773 774 for (i = 0; i < count; i++) { 775 if (i != reqpage) { 776 vnode_pager_freepage(m[i]); 777 } 778 } 779 cnt.v_vnodein++; 780 cnt.v_vnodepgsin++; 781 return vnode_pager_input_smlfs(vnp, m[reqpage]); 782 } |
843/* 844 * here on direct device I/O 845 */ 846 847 848#ifdef NOTYET 849 if( (vp->v_flag & VVMIO) == 0) { 850#endif | |
851 /* | 783 /* |
852 * This pathetic hack gets data from the buffer cache, if it's there. 853 * I believe that this is not really necessary, and the ends can be 854 * gotten by defaulting to the normal vfs read behavior, but this 855 * might be more efficient, because the will NOT invoke read-aheads 856 * and one of the purposes of this code is to bypass the buffer cache 857 * and keep from flushing it by reading in a program. | 784 * if ANY DEV_BSIZE blocks are valid on a large filesystem block 785 * then, the entire page is valid -- |
858 */ | 786 */ |
859 860 /* 861 * calculate logical block and offset 862 */ 863 block = foff / bsize; 864 offset = foff % bsize; 865 s = splbio(); 866 867 /* 868 * if we have a buffer in core, then try to use it 869 */ 870 while ((bp = incore(vp, block)) != 0) { 871 int amount; 872 873 /* 874 * wait until the buffer is avail or gone 875 */ 876 if (bp->b_flags & B_BUSY) { 877 bp->b_flags |= B_WANTED; 878 tsleep((caddr_t) bp, PVM, "vnwblk", 0); 879 continue; 880 } 881 amount = PAGE_SIZE; 882 if ((foff + amount) > vnp->vnp_size) 883 amount = vnp->vnp_size - foff; 884 885 /* 886 * make sure that this page is in the buffer 887 */ 888 if ((amount > 0) && (offset + amount) <= bp->b_bcount) { 889 bp->b_flags |= B_BUSY; 890 splx(s); 891 kva = kmem_alloc_wait( pager_map, PAGE_SIZE); 892 893 /* 894 * map the requested page 895 */ 896 pmap_qenter(kva, &m[reqpage], 1); 897 898 /* 899 * copy the data from the buffer 900 */ 901 bcopy(bp->b_un.b_addr + offset, (caddr_t) kva, amount); 902 if (amount < PAGE_SIZE) { 903 bzero((caddr_t) kva + amount, PAGE_SIZE - amount); 904 } 905 906 /* 907 * unmap the page and free the kva 908 */ 909 pmap_qremove( kva, 1); 910 kmem_free_wakeup(pager_map, kva, PAGE_SIZE); 911 912 /* 913 * release the buffer back to the block subsystem 914 */ 915 bp->b_flags &= ~B_BUSY; 916 wakeup((caddr_t) bp); 917 918 /* 919 * we did not have to do any work to get the requested 920 * page, the read behind/ahead does not justify a read 921 */ 922 for (i = 0; i < count; i++) { 923 if (i != reqpage) { 924 vnode_pager_freepage(m[i]); 925 } 926 } 927 count = 1; 928 reqpage = 0; 929 m[0] = m[reqpage]; 930 931 /* 932 * sorry for the goto 933 */ 934 goto finishup; 935 } 936 937 /* 938 * buffer is nowhere to be found, read from the disk 939 */ 940 break; | 787 if (m[reqpage]->valid) { 788 m[reqpage]->valid = VM_PAGE_BITS_ALL; 789 for (i = 0; i < count; i++) { 790 if (i != reqpage) 791 vnode_pager_freepage(m[i]); |
941 } | 792 } |
942 splx(s); 943#ifdef NOTYET | 793 return VM_PAGER_OK; |
944 } | 794 } |
945#endif | 795 /* 796 * here on direct device I/O 797 */ |
946 947 reqaddr = vnode_pager_addr(vp, foff); | 798 799 reqaddr = vnode_pager_addr(vp, foff); |
800 if (reqaddr == -1 && foff < vnp->vnp_size) { 801 printf("reqaddr: %d, foff: %d, vnp_size: %d\n", 802 reqaddr, foff, vnp->vnp_size); 803 Debugger(""); 804 } |
|
948 s = splbio(); 949 950 /* 951 * Make sure that our I/O request is contiguous. Scan backward and 952 * stop for the first discontiguous entry or stop for a page being in 953 * buffer cache. 954 */ 955 failflag = 0; 956 first = reqpage; 957 for (i = reqpage - 1; i >= 0; --i) { 958 if (failflag || | 805 s = splbio(); 806 807 /* 808 * Make sure that our I/O request is contiguous. Scan backward and 809 * stop for the first discontiguous entry or stop for a page being in 810 * buffer cache. 811 */ 812 failflag = 0; 813 first = reqpage; 814 for (i = reqpage - 1; i >= 0; --i) { 815 if (failflag || |
959#ifdef NOTYET 960 ((vp->v_flag & VVMIO) == 0 && incore(vp, (foff + (i - reqpage) * PAGE_SIZE) / bsize)) || 961#else 962 (incore(vp, (foff + (i - reqpage) * PAGE_SIZE) / bsize)) || 963#endif 964 (vnode_pager_addr(vp, m[i]->offset + paging_offset)) | 816 (vnode_pager_addr(vp, m[i]->offset)) |
965 != reqaddr + (i - reqpage) * PAGE_SIZE) { 966 vnode_pager_freepage(m[i]); 967 failflag = 1; 968 } else { 969 first = i; 970 } 971 } 972 973 /* 974 * Scan forward and stop for the first non-contiguous entry or stop 975 * for a page being in buffer cache. 976 */ 977 failflag = 0; 978 last = reqpage + 1; 979 for (i = reqpage + 1; i < count; i++) { 980 if (failflag || | 817 != reqaddr + (i - reqpage) * PAGE_SIZE) { 818 vnode_pager_freepage(m[i]); 819 failflag = 1; 820 } else { 821 first = i; 822 } 823 } 824 825 /* 826 * Scan forward and stop for the first non-contiguous entry or stop 827 * for a page being in buffer cache. 828 */ 829 failflag = 0; 830 last = reqpage + 1; 831 for (i = reqpage + 1; i < count; i++) { 832 if (failflag || |
981#ifdef NOTYET 982 ((vp->v_flag & VVMIO) == 0 && incore(vp, (foff + (i - reqpage) * PAGE_SIZE) / bsize)) || 983#else 984 (incore(vp, (foff + (i - reqpage) * PAGE_SIZE) / bsize)) || 985#endif 986 (vnode_pager_addr(vp, m[i]->offset + paging_offset)) | 833 (vnode_pager_addr(vp, m[i]->offset)) |
987 != reqaddr + (i - reqpage) * PAGE_SIZE) { 988 vnode_pager_freepage(m[i]); 989 failflag = 1; 990 } else { 991 last = i + 1; 992 } 993 } 994 splx(s); --- 5 unchanged lines hidden (view full) --- 1000 count = last; 1001 if (first != 0) { 1002 for (i = first; i < count; i++) { 1003 m[i - first] = m[i]; 1004 } 1005 count -= first; 1006 reqpage -= first; 1007 } | 834 != reqaddr + (i - reqpage) * PAGE_SIZE) { 835 vnode_pager_freepage(m[i]); 836 failflag = 1; 837 } else { 838 last = i + 1; 839 } 840 } 841 splx(s); --- 5 unchanged lines hidden (view full) --- 847 count = last; 848 if (first != 0) { 849 for (i = first; i < count; i++) { 850 m[i - first] = m[i]; 851 } 852 count -= first; 853 reqpage -= first; 854 } |
1008 | |
1009 /* 1010 * calculate the file virtual address for the transfer 1011 */ | 855 /* 856 * calculate the file virtual address for the transfer 857 */ |
1012 foff = m[0]->offset + paging_offset; | 858 foff = m[0]->offset; |
1013 1014 /* 1015 * and get the disk physical address (in bytes) 1016 */ 1017 firstaddr = vnode_pager_addr(vp, foff); 1018 1019 /* 1020 * calculate the size of the transfer --- 4 unchanged lines hidden (view full) --- 1025 1026 /* 1027 * round up physical size for real devices 1028 */ 1029 if (dp->v_type == VBLK || dp->v_type == VCHR) 1030 size = (size + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); 1031 1032 counta = 0; | 859 860 /* 861 * and get the disk physical address (in bytes) 862 */ 863 firstaddr = vnode_pager_addr(vp, foff); 864 865 /* 866 * calculate the size of the transfer --- 4 unchanged lines hidden (view full) --- 871 872 /* 873 * round up physical size for real devices 874 */ 875 if (dp->v_type == VBLK || dp->v_type == VCHR) 876 size = (size + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); 877 878 counta = 0; |
1033 if( count*PAGE_SIZE > bsize) | 879 if (count * PAGE_SIZE > bsize) |
1034 counta = (count - reqpage) - 1; 1035 bpa = 0; 1036 sizea = 0; | 880 counta = (count - reqpage) - 1; 881 bpa = 0; 882 sizea = 0; |
1037 if( counta) { | 883 if (counta) { |
1038 bpa = getpbuf(); 1039 count -= counta; | 884 bpa = getpbuf(); 885 count -= counta; |
1040 sizea = size - count*PAGE_SIZE; | 886 sizea = size - count * PAGE_SIZE; |
1041 size = count * PAGE_SIZE; 1042 } | 887 size = count * PAGE_SIZE; 888 } |
1043 | |
1044 bp = getpbuf(); | 889 bp = getpbuf(); |
1045 kva = (vm_offset_t)bp->b_data; | 890 kva = (vm_offset_t) bp->b_data; |
1046 1047 /* 1048 * and map the pages to be read into the kva 1049 */ 1050 pmap_qenter(kva, m, count); | 891 892 /* 893 * and map the pages to be read into the kva 894 */ 895 pmap_qenter(kva, m, count); |
1051 VHOLD(vp); | |
1052 1053 /* build a minimal buffer header */ 1054 bp->b_flags = B_BUSY | B_READ | B_CALL; 1055 bp->b_iodone = vnode_pager_iodone; 1056 /* B_PHYS is not set, but it is nice to fill this in */ 1057 bp->b_proc = curproc; 1058 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred; 1059 if (bp->b_rcred != NOCRED) 1060 crhold(bp->b_rcred); 1061 if (bp->b_wcred != NOCRED) 1062 crhold(bp->b_wcred); 1063 bp->b_blkno = firstaddr / DEV_BSIZE; | 896 897 /* build a minimal buffer header */ 898 bp->b_flags = B_BUSY | B_READ | B_CALL; 899 bp->b_iodone = vnode_pager_iodone; 900 /* B_PHYS is not set, but it is nice to fill this in */ 901 bp->b_proc = curproc; 902 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred; 903 if (bp->b_rcred != NOCRED) 904 crhold(bp->b_rcred); 905 if (bp->b_wcred != NOCRED) 906 crhold(bp->b_wcred); 907 bp->b_blkno = firstaddr / DEV_BSIZE; |
1064 bgetvp(dp, bp); | 908 pbgetvp(dp, bp); |
1065 bp->b_bcount = size; 1066 bp->b_bufsize = size; 1067 1068 cnt.v_vnodein++; 1069 cnt.v_vnodepgsin += count; 1070 1071 /* do the input */ 1072 VOP_STRATEGY(bp); 1073 | 909 bp->b_bcount = size; 910 bp->b_bufsize = size; 911 912 cnt.v_vnodein++; 913 cnt.v_vnodepgsin += count; 914 915 /* do the input */ 916 VOP_STRATEGY(bp); 917 |
1074 if( counta) { 1075 for(i=0;i<counta;i++) { 1076 vm_page_deactivate(m[count+i]); | 918 if (counta) { 919 for (i = 0; i < counta; i++) { 920 vm_page_deactivate(m[count + i]); |
1077 } | 921 } |
1078 pmap_qenter((vm_offset_t)bpa->b_data, &m[count], counta); | 922 pmap_qenter((vm_offset_t) bpa->b_data, &m[count], counta); |
1079 ++m[count]->object->paging_in_progress; | 923 ++m[count]->object->paging_in_progress; |
1080 VHOLD(vp); | |
1081 bpa->b_flags = B_BUSY | B_READ | B_CALL | B_ASYNC; 1082 bpa->b_iodone = vnode_pager_iodone; 1083 /* B_PHYS is not set, but it is nice to fill this in */ 1084 bpa->b_proc = curproc; 1085 bpa->b_rcred = bpa->b_wcred = bpa->b_proc->p_ucred; 1086 if (bpa->b_rcred != NOCRED) 1087 crhold(bpa->b_rcred); 1088 if (bpa->b_wcred != NOCRED) 1089 crhold(bpa->b_wcred); 1090 bpa->b_blkno = (firstaddr + count * PAGE_SIZE) / DEV_BSIZE; | 924 bpa->b_flags = B_BUSY | B_READ | B_CALL | B_ASYNC; 925 bpa->b_iodone = vnode_pager_iodone; 926 /* B_PHYS is not set, but it is nice to fill this in */ 927 bpa->b_proc = curproc; 928 bpa->b_rcred = bpa->b_wcred = bpa->b_proc->p_ucred; 929 if (bpa->b_rcred != NOCRED) 930 crhold(bpa->b_rcred); 931 if (bpa->b_wcred != NOCRED) 932 crhold(bpa->b_wcred); 933 bpa->b_blkno = (firstaddr + count * PAGE_SIZE) / DEV_BSIZE; |
1091 bgetvp(dp, bpa); | 934 pbgetvp(dp, bpa); |
1092 bpa->b_bcount = sizea; | 935 bpa->b_bcount = sizea; |
1093 bpa->b_bufsize = counta*PAGE_SIZE; | 936 bpa->b_bufsize = counta * PAGE_SIZE; |
1094 1095 cnt.v_vnodepgsin += counta; 1096 VOP_STRATEGY(bpa); 1097 } | 937 938 cnt.v_vnodepgsin += counta; 939 VOP_STRATEGY(bpa); 940 } |
1098 | |
1099 s = splbio(); 1100 /* we definitely need to be at splbio here */ 1101 1102 while ((bp->b_flags & B_DONE) == 0) { 1103 tsleep((caddr_t) bp, PVM, "vnread", 0); 1104 } 1105 splx(s); 1106 if ((bp->b_flags & B_ERROR) != 0) 1107 error = EIO; 1108 1109 if (!error) { 1110 if (size != count * PAGE_SIZE) 1111 bzero((caddr_t) kva + size, PAGE_SIZE * count - size); 1112 } | 941 s = splbio(); 942 /* we definitely need to be at splbio here */ 943 944 while ((bp->b_flags & B_DONE) == 0) { 945 tsleep((caddr_t) bp, PVM, "vnread", 0); 946 } 947 splx(s); 948 if ((bp->b_flags & B_ERROR) != 0) 949 error = EIO; 950 951 if (!error) { 952 if (size != count * PAGE_SIZE) 953 bzero((caddr_t) kva + size, PAGE_SIZE * count - size); 954 } |
1113 pmap_qremove( kva, count); | 955 pmap_qremove(kva, count); |
1114 1115 /* 1116 * free the buffer header back to the swap buffer pool 1117 */ 1118 relpbuf(bp); 1119 HOLDRELE(vp); 1120 1121finishup: 1122 for (i = 0; i < count; i++) { 1123 pmap_clear_modify(VM_PAGE_TO_PHYS(m[i])); | 956 957 /* 958 * free the buffer header back to the swap buffer pool 959 */ 960 relpbuf(bp); 961 HOLDRELE(vp); 962 963finishup: 964 for (i = 0; i < count; i++) { 965 pmap_clear_modify(VM_PAGE_TO_PHYS(m[i])); |
1124 m[i]->flags |= PG_CLEAN; 1125 m[i]->flags &= ~PG_LAUNDRY; | 966 m[i]->dirty = 0; 967 m[i]->valid = VM_PAGE_BITS_ALL; |
1126 if (i != reqpage) { 1127 1128 /* 1129 * whether or not to leave the page activated is up in 1130 * the air, but we should put the page on a page queue 1131 * somewhere. (it already is in the object). Result: 1132 * It appears that emperical results show that 1133 * deactivating pages is best. 1134 */ 1135 1136 /* 1137 * just in case someone was asking for this page we 1138 * now tell them that it is ok to use 1139 */ 1140 if (!error) { | 968 if (i != reqpage) { 969 970 /* 971 * whether or not to leave the page activated is up in 972 * the air, but we should put the page on a page queue 973 * somewhere. (it already is in the object). Result: 974 * It appears that emperical results show that 975 * deactivating pages is best. 976 */ 977 978 /* 979 * just in case someone was asking for this page we 980 * now tell them that it is ok to use 981 */ 982 if (!error) { |
1141 vm_page_deactivate(m[i]); | 983 if (i != reqpage - 1) 984 vm_page_deactivate(m[i]); 985 else 986 vm_page_activate(m[i]); |
1142 PAGE_WAKEUP(m[i]); | 987 PAGE_WAKEUP(m[i]); |
1143 m[i]->flags &= ~PG_FAKE; | |
1144 } else { 1145 vnode_pager_freepage(m[i]); 1146 } 1147 } 1148 } 1149 if (error) { 1150 printf("vnode_pager_input: I/O read error\n"); 1151 } 1152 return (error ? VM_PAGER_ERROR : VM_PAGER_OK); 1153} 1154 1155/* 1156 * old-style vnode pager output routine 1157 */ 1158int 1159vnode_pager_output_old(vnp, m) 1160 register vn_pager_t vnp; 1161 vm_page_t m; 1162{ | 988 } else { 989 vnode_pager_freepage(m[i]); 990 } 991 } 992 } 993 if (error) { 994 printf("vnode_pager_input: I/O read error\n"); 995 } 996 return (error ? VM_PAGER_ERROR : VM_PAGER_OK); 997} 998 999/* 1000 * old-style vnode pager output routine 1001 */ 1002int 1003vnode_pager_output_old(vnp, m) 1004 register vn_pager_t vnp; 1005 vm_page_t m; 1006{ |
1163 vm_offset_t foff; 1164 vm_offset_t kva; | 1007 vm_offset_t kva, kva2; |
1165 vm_offset_t size; 1166 struct iovec aiov; 1167 struct uio auio; 1168 struct vnode *vp; | 1008 vm_offset_t size; 1009 struct iovec aiov; 1010 struct uio auio; 1011 struct vnode *vp; |
1169 int error; | 1012 int error; |
1170 1171 vp = vnp->vnp_vp; | 1013 1014 vp = vnp->vnp_vp; |
1172 foff = m->offset + m->object->paging_offset; | |
1173 1174 /* | 1015 1016 /* |
1175 * Return failure if beyond current EOF | 1017 * Dont return failure if beyond current EOF placate the VM system. |
1176 */ | 1018 */ |
1177 if (foff >= vnp->vnp_size) { 1178 return VM_PAGER_BAD; | 1019 if (m->offset >= vnp->vnp_size) { 1020 return VM_PAGER_OK; |
1179 } else { 1180 size = PAGE_SIZE; | 1021 } else { 1022 size = PAGE_SIZE; |
1181 if (foff + size > vnp->vnp_size) 1182 size = vnp->vnp_size - foff; 1183/* 1184 * Allocate a kernel virtual address and initialize so that 1185 * we can use VOP_WRITE routines. 1186 */ | 1023 if (m->offset + size > vnp->vnp_size) 1024 size = vnp->vnp_size - m->offset; 1025 1026 kva2 = kmem_alloc(pager_map, PAGE_SIZE); 1027 /* 1028 * Allocate a kernel virtual address and initialize so that 1029 * we can use VOP_WRITE routines. 1030 */ |
1187 kva = vm_pager_map_page(m); | 1031 kva = vm_pager_map_page(m); |
1188 aiov.iov_base = (caddr_t) kva; | 1032 bcopy((caddr_t) kva, (caddr_t) kva2, size); 1033 vm_pager_unmap_page(kva); 1034 pmap_clear_modify(VM_PAGE_TO_PHYS(m)); 1035 PAGE_WAKEUP(m); 1036 1037 aiov.iov_base = (caddr_t) kva2; |
1189 aiov.iov_len = size; 1190 auio.uio_iov = &aiov; 1191 auio.uio_iovcnt = 1; | 1038 aiov.iov_len = size; 1039 auio.uio_iov = &aiov; 1040 auio.uio_iovcnt = 1; |
1192 auio.uio_offset = foff; | 1041 auio.uio_offset = m->offset; |
1193 auio.uio_segflg = UIO_SYSSPACE; 1194 auio.uio_rw = UIO_WRITE; 1195 auio.uio_resid = size; 1196 auio.uio_procp = (struct proc *) 0; 1197 1198 error = VOP_WRITE(vp, &auio, 0, curproc->p_ucred); 1199 | 1042 auio.uio_segflg = UIO_SYSSPACE; 1043 auio.uio_rw = UIO_WRITE; 1044 auio.uio_resid = size; 1045 auio.uio_procp = (struct proc *) 0; 1046 1047 error = VOP_WRITE(vp, &auio, 0, curproc->p_ucred); 1048 |
1049 kmem_free_wakeup(pager_map, kva2, PAGE_SIZE); |
|
1200 if (!error) { 1201 if ((size - auio.uio_resid) == 0) { 1202 error = EINVAL; 1203 } 1204 } | 1050 if (!error) { 1051 if ((size - auio.uio_resid) == 0) { 1052 error = EINVAL; 1053 } 1054 } |
1205 vm_pager_unmap_page(kva); 1206 return error ? VM_PAGER_ERROR: VM_PAGER_OK; | 1055 return error ? VM_PAGER_ERROR : VM_PAGER_OK; |
1207 } 1208} 1209 1210/* 1211 * vnode pager output on a small-block file system 1212 */ 1213int 1214vnode_pager_output_smlfs(vnp, m) 1215 vn_pager_t vnp; 1216 vm_page_t m; 1217{ | 1056 } 1057} 1058 1059/* 1060 * vnode pager output on a small-block file system 1061 */ 1062int 1063vnode_pager_output_smlfs(vnp, m) 1064 vn_pager_t vnp; 1065 vm_page_t m; 1066{ |
1218 int i; 1219 int s; 1220 vm_offset_t paging_offset; | 1067 int i; 1068 int s; |
1221 struct vnode *dp, *vp; 1222 struct buf *bp; | 1069 struct vnode *dp, *vp; 1070 struct buf *bp; |
1223 vm_offset_t foff; | |
1224 vm_offset_t kva; | 1071 vm_offset_t kva; |
1225 int fileaddr; | 1072 int fileaddr; |
1226 vm_offset_t bsize; | 1073 vm_offset_t bsize; |
1227 int error = 0; | 1074 int error = 0; |
1228 | 1075 |
1229 paging_offset = m->object->paging_offset; | |
1230 vp = vnp->vnp_vp; 1231 bsize = vp->v_mount->mnt_stat.f_iosize; | 1076 vp = vnp->vnp_vp; 1077 bsize = vp->v_mount->mnt_stat.f_iosize; |
1232 foff = m->offset + paging_offset; | |
1233 | 1078 |
1234 VOP_BMAP(vp, foff, &dp, 0, 0); | 1079 VOP_BMAP(vp, 0, &dp, 0, 0); |
1235 kva = vm_pager_map_page(m); 1236 for (i = 0; !error && i < (PAGE_SIZE / bsize); i++) { 1237 | 1080 kva = vm_pager_map_page(m); 1081 for (i = 0; !error && i < (PAGE_SIZE / bsize); i++) { 1082 |
1083 if ((vm_page_bits(m->offset + i * bsize, bsize) & m->valid & m->dirty) == 0) 1084 continue; |
|
1238 /* 1239 * calculate logical block and offset 1240 */ | 1085 /* 1086 * calculate logical block and offset 1087 */ |
1241 fileaddr = vnode_pager_addr(vp, foff + i * bsize); | 1088 fileaddr = vnode_pager_addr(vp, m->offset + i * bsize); |
1242 if (fileaddr != -1) { | 1089 if (fileaddr != -1) { |
1243 s = splbio(); 1244 bp = incore(vp, (foff / bsize) + i); 1245 if (bp) { 1246 bp = getblk(vp, (foff / bsize) + i, bp->b_bufsize, 0, 0); 1247 bp->b_flags |= B_INVAL; 1248 brelse(bp); 1249 } 1250 splx(s); | |
1251 1252 bp = getpbuf(); | 1090 1091 bp = getpbuf(); |
1253 VHOLD(vp); | |
1254 1255 /* build a minimal buffer header */ 1256 bp->b_flags = B_BUSY | B_CALL | B_WRITE; 1257 bp->b_iodone = vnode_pager_iodone; 1258 bp->b_proc = curproc; 1259 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred; 1260 if (bp->b_rcred != NOCRED) 1261 crhold(bp->b_rcred); 1262 if (bp->b_wcred != NOCRED) 1263 crhold(bp->b_wcred); 1264 bp->b_un.b_addr = (caddr_t) kva + i * bsize; 1265 bp->b_blkno = fileaddr / DEV_BSIZE; | 1092 1093 /* build a minimal buffer header */ 1094 bp->b_flags = B_BUSY | B_CALL | B_WRITE; 1095 bp->b_iodone = vnode_pager_iodone; 1096 bp->b_proc = curproc; 1097 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred; 1098 if (bp->b_rcred != NOCRED) 1099 crhold(bp->b_rcred); 1100 if (bp->b_wcred != NOCRED) 1101 crhold(bp->b_wcred); 1102 bp->b_un.b_addr = (caddr_t) kva + i * bsize; 1103 bp->b_blkno = fileaddr / DEV_BSIZE; |
1266 bgetvp(dp, bp); | 1104 pbgetvp(dp, bp); |
1267 ++dp->v_numoutput; 1268 /* for NFS */ 1269 bp->b_dirtyoff = 0; 1270 bp->b_dirtyend = bsize; 1271 bp->b_bcount = bsize; 1272 bp->b_bufsize = bsize; 1273 1274 /* do the input */ --- 4 unchanged lines hidden (view full) --- 1279 s = splbio(); 1280 while ((bp->b_flags & B_DONE) == 0) { 1281 tsleep((caddr_t) bp, PVM, "vnswrt", 0); 1282 } 1283 splx(s); 1284 if ((bp->b_flags & B_ERROR) != 0) 1285 error = EIO; 1286 | 1105 ++dp->v_numoutput; 1106 /* for NFS */ 1107 bp->b_dirtyoff = 0; 1108 bp->b_dirtyend = bsize; 1109 bp->b_bcount = bsize; 1110 bp->b_bufsize = bsize; 1111 1112 /* do the input */ --- 4 unchanged lines hidden (view full) --- 1117 s = splbio(); 1118 while ((bp->b_flags & B_DONE) == 0) { 1119 tsleep((caddr_t) bp, PVM, "vnswrt", 0); 1120 } 1121 splx(s); 1122 if ((bp->b_flags & B_ERROR) != 0) 1123 error = EIO; 1124 |
1125 vm_page_set_clean(m, i * bsize, bsize); |
|
1287 /* 1288 * free the buffer header back to the swap buffer pool 1289 */ 1290 relpbuf(bp); 1291 HOLDRELE(vp); 1292 } 1293 } 1294 vm_pager_unmap_page(kva); --- 5 unchanged lines hidden (view full) --- 1300 1301/* 1302 * generic vnode pager output routine 1303 */ 1304int 1305vnode_pager_output(vnp, m, count, rtvals) 1306 vn_pager_t vnp; 1307 vm_page_t *m; | 1126 /* 1127 * free the buffer header back to the swap buffer pool 1128 */ 1129 relpbuf(bp); 1130 HOLDRELE(vp); 1131 } 1132 } 1133 vm_pager_unmap_page(kva); --- 5 unchanged lines hidden (view full) --- 1139 1140/* 1141 * generic vnode pager output routine 1142 */ 1143int 1144vnode_pager_output(vnp, m, count, rtvals) 1145 vn_pager_t vnp; 1146 vm_page_t *m; |
1308 int count; 1309 int *rtvals; | 1147 int count; 1148 int *rtvals; |
1310{ | 1149{ |
1311 int i, j; | 1150 int i, j; |
1312 vm_offset_t kva, foff; | 1151 vm_offset_t kva, foff; |
1313 int size; | 1152 int size; |
1314 vm_object_t object; | 1153 vm_object_t object; |
1315 vm_offset_t paging_offset; | |
1316 struct vnode *dp, *vp; 1317 struct buf *bp; 1318 vm_offset_t reqaddr; | 1154 struct vnode *dp, *vp; 1155 struct buf *bp; 1156 vm_offset_t reqaddr; |
1319 int bsize; 1320 int s; | 1157 int bsize; 1158 int s; 1159 daddr_t block; 1160 struct timeval tv; |
1321 | 1161 |
1322 int error = 0; | 1162 int error = 0; |
1323 1324retryoutput: 1325 object = m[0]->object; /* all vm_page_t items are in same object */ | 1163 1164retryoutput: 1165 object = m[0]->object; /* all vm_page_t items are in same object */ |
1326 paging_offset = object->paging_offset; | |
1327 1328 vp = vnp->vnp_vp; 1329 1330 /* 1331 * Make sure underlying filesystem is still mounted. 1332 */ 1333 if (vp->v_mount == NULL) 1334 return VM_PAGER_FAIL; 1335 1336 bsize = vp->v_mount->mnt_stat.f_iosize; 1337 1338 for (i = 0; i < count; i++) 1339 rtvals[i] = VM_PAGER_AGAIN; 1340 | 1166 1167 vp = vnp->vnp_vp; 1168 1169 /* 1170 * Make sure underlying filesystem is still mounted. 1171 */ 1172 if (vp->v_mount == NULL) 1173 return VM_PAGER_FAIL; 1174 1175 bsize = vp->v_mount->mnt_stat.f_iosize; 1176 1177 for (i = 0; i < count; i++) 1178 rtvals[i] = VM_PAGER_AGAIN; 1179 |
1180 if ((int) m[0]->offset < 0) { 1181 printf("vnode_pager_output: attempt to write meta-data!!! -- 0x%x\n", m[0]->offset); 1182 m[0]->dirty = 0; 1183 rtvals[0] = VM_PAGER_OK; 1184 return VM_PAGER_OK; 1185 } |
|
1341 /* 1342 * if the filesystem does not have a bmap, then use the old code 1343 */ | 1186 /* 1187 * if the filesystem does not have a bmap, then use the old code 1188 */ |
1344 if (VOP_BMAP(vp, m[0]->offset + paging_offset, &dp, 0, 0)) { | 1189 if (VOP_BMAP(vp, (m[0]->offset / bsize), &dp, &block, 0) || 1190 (block == -1)) { |
1345 1346 rtvals[0] = vnode_pager_output_old(vnp, m[0]); 1347 | 1191 1192 rtvals[0] = vnode_pager_output_old(vnp, m[0]); 1193 |
1348 pmap_clear_modify(VM_PAGE_TO_PHYS(m[0])); 1349 m[0]->flags |= PG_CLEAN; 1350 m[0]->flags &= ~PG_LAUNDRY; | 1194 m[0]->dirty = 0; |
1351 cnt.v_vnodeout++; 1352 cnt.v_vnodepgsout++; 1353 return rtvals[0]; 1354 } | 1195 cnt.v_vnodeout++; 1196 cnt.v_vnodepgsout++; 1197 return rtvals[0]; 1198 } |
1199 tv = time; 1200 VOP_UPDATE(vp, &tv, &tv, 0); |
|
1355 1356 /* 1357 * if the filesystem has a small blocksize, then use the small block 1358 * filesystem output code 1359 */ 1360 if ((bsize < PAGE_SIZE) && 1361 (vp->v_mount->mnt_stat.f_type != MOUNT_NFS)) { 1362 1363 for (i = 0; i < count; i++) { 1364 rtvals[i] = vnode_pager_output_smlfs(vnp, m[i]); 1365 if (rtvals[i] == VM_PAGER_OK) { 1366 pmap_clear_modify(VM_PAGE_TO_PHYS(m[i])); | 1201 1202 /* 1203 * if the filesystem has a small blocksize, then use the small block 1204 * filesystem output code 1205 */ 1206 if ((bsize < PAGE_SIZE) && 1207 (vp->v_mount->mnt_stat.f_type != MOUNT_NFS)) { 1208 1209 for (i = 0; i < count; i++) { 1210 rtvals[i] = vnode_pager_output_smlfs(vnp, m[i]); 1211 if (rtvals[i] == VM_PAGER_OK) { 1212 pmap_clear_modify(VM_PAGE_TO_PHYS(m[i])); |
1367 m[i]->flags |= PG_CLEAN; 1368 m[i]->flags &= ~PG_LAUNDRY; | |
1369 } 1370 } 1371 cnt.v_vnodeout++; 1372 cnt.v_vnodepgsout += count; 1373 return rtvals[0]; 1374 } | 1213 } 1214 } 1215 cnt.v_vnodeout++; 1216 cnt.v_vnodepgsout += count; 1217 return rtvals[0]; 1218 } |
1375 | |
1376 for (i = 0; i < count; i++) { | 1219 for (i = 0; i < count; i++) { |
1377 foff = m[i]->offset + paging_offset; | 1220 foff = m[i]->offset; |
1378 if (foff >= vnp->vnp_size) { 1379 for (j = i; j < count; j++) 1380 rtvals[j] = VM_PAGER_BAD; 1381 count = i; 1382 break; 1383 } 1384 } 1385 if (count == 0) { 1386 return rtvals[0]; 1387 } | 1221 if (foff >= vnp->vnp_size) { 1222 for (j = i; j < count; j++) 1223 rtvals[j] = VM_PAGER_BAD; 1224 count = i; 1225 break; 1226 } 1227 } 1228 if (count == 0) { 1229 return rtvals[0]; 1230 } |
1388 foff = m[0]->offset + paging_offset; | 1231 foff = m[0]->offset; |
1389 reqaddr = vnode_pager_addr(vp, foff); 1390 1391 /* 1392 * Scan forward and stop for the first non-contiguous entry or stop 1393 * for a page being in buffer cache. 1394 */ 1395 for (i = 1; i < count; i++) { | 1232 reqaddr = vnode_pager_addr(vp, foff); 1233 1234 /* 1235 * Scan forward and stop for the first non-contiguous entry or stop 1236 * for a page being in buffer cache. 1237 */ 1238 for (i = 1; i < count; i++) { |
1396 if (vnode_pager_addr(vp, m[i]->offset + paging_offset) | 1239 if (vnode_pager_addr(vp, m[i]->offset) |
1397 != reqaddr + i * PAGE_SIZE) { 1398 count = i; 1399 break; 1400 } 1401 } 1402 1403 /* 1404 * calculate the size of the transfer --- 4 unchanged lines hidden (view full) --- 1409 1410 /* 1411 * round up physical size for real devices 1412 */ 1413 if (dp->v_type == VBLK || dp->v_type == VCHR) 1414 size = (size + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); 1415 1416 bp = getpbuf(); | 1240 != reqaddr + i * PAGE_SIZE) { 1241 count = i; 1242 break; 1243 } 1244 } 1245 1246 /* 1247 * calculate the size of the transfer --- 4 unchanged lines hidden (view full) --- 1252 1253 /* 1254 * round up physical size for real devices 1255 */ 1256 if (dp->v_type == VBLK || dp->v_type == VCHR) 1257 size = (size + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); 1258 1259 bp = getpbuf(); |
1417 kva = (vm_offset_t)bp->b_data; | 1260 kva = (vm_offset_t) bp->b_data; |
1418 /* 1419 * and map the pages to be read into the kva 1420 */ 1421 pmap_qenter(kva, m, count); | 1261 /* 1262 * and map the pages to be read into the kva 1263 */ 1264 pmap_qenter(kva, m, count); |
1422#if 0 1423 printf("vnode: writing foff: %d, devoff: %d, size: %d\n", 1424 foff, reqaddr, size); 1425#endif | |
1426 | 1265 |
1427 /* 1428 * next invalidate the incore vfs_bio data 1429 */ 1430#ifdef NOTYET 1431 if( (vp->v_flag & VVMIO) == 0) { 1432#endif 1433 for (i = 0; i < count; i++) { 1434 int filblock = (foff + i * PAGE_SIZE) / bsize; 1435 struct buf *fbp; 1436 1437 s = splbio(); 1438 fbp = incore(vp, filblock); 1439 if (fbp) { 1440 fbp = getblk(vp, filblock, fbp->b_bufsize, 0, 0); 1441 if (fbp->b_flags & B_DELWRI) { 1442 if (fbp->b_bufsize <= PAGE_SIZE) 1443 fbp->b_flags &= ~B_DELWRI; 1444 else { 1445 bwrite(fbp); 1446 fbp = getblk(vp, filblock, 1447 fbp->b_bufsize, 0, 0); 1448 } 1449 } 1450 fbp->b_flags |= B_INVAL; 1451 brelse(fbp); 1452 } 1453 splx(s); 1454 } 1455#ifdef NOTYET 1456 } 1457#endif 1458 1459 1460 VHOLD(vp); | |
1461 /* build a minimal buffer header */ 1462 bp->b_flags = B_BUSY | B_WRITE | B_CALL; 1463 bp->b_iodone = vnode_pager_iodone; 1464 /* B_PHYS is not set, but it is nice to fill this in */ 1465 bp->b_proc = curproc; 1466 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred; 1467 1468 if (bp->b_rcred != NOCRED) 1469 crhold(bp->b_rcred); 1470 if (bp->b_wcred != NOCRED) 1471 crhold(bp->b_wcred); 1472 bp->b_blkno = reqaddr / DEV_BSIZE; | 1266 /* build a minimal buffer header */ 1267 bp->b_flags = B_BUSY | B_WRITE | B_CALL; 1268 bp->b_iodone = vnode_pager_iodone; 1269 /* B_PHYS is not set, but it is nice to fill this in */ 1270 bp->b_proc = curproc; 1271 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred; 1272 1273 if (bp->b_rcred != NOCRED) 1274 crhold(bp->b_rcred); 1275 if (bp->b_wcred != NOCRED) 1276 crhold(bp->b_wcred); 1277 bp->b_blkno = reqaddr / DEV_BSIZE; |
1473 bgetvp(dp, bp); | 1278 pbgetvp(dp, bp); |
1474 ++dp->v_numoutput; 1475 1476 /* for NFS */ 1477 bp->b_dirtyoff = 0; 1478 bp->b_dirtyend = size; 1479 1480 bp->b_bcount = size; 1481 bp->b_bufsize = size; --- 11 unchanged lines hidden (view full) --- 1493 while ((bp->b_flags & B_DONE) == 0) { 1494 tsleep((caddr_t) bp, PVM, "vnwrite", 0); 1495 } 1496 splx(s); 1497 1498 if ((bp->b_flags & B_ERROR) != 0) 1499 error = EIO; 1500 | 1279 ++dp->v_numoutput; 1280 1281 /* for NFS */ 1282 bp->b_dirtyoff = 0; 1283 bp->b_dirtyend = size; 1284 1285 bp->b_bcount = size; 1286 bp->b_bufsize = size; --- 11 unchanged lines hidden (view full) --- 1298 while ((bp->b_flags & B_DONE) == 0) { 1299 tsleep((caddr_t) bp, PVM, "vnwrite", 0); 1300 } 1301 splx(s); 1302 1303 if ((bp->b_flags & B_ERROR) != 0) 1304 error = EIO; 1305 |
1501 pmap_qremove( kva, count); | 1306 pmap_qremove(kva, count); |
1502 1503 /* 1504 * free the buffer header back to the swap buffer pool 1505 */ 1506 relpbuf(bp); 1507 HOLDRELE(vp); 1508 1509 if (!error) { 1510 for (i = 0; i < count; i++) { 1511 pmap_clear_modify(VM_PAGE_TO_PHYS(m[i])); | 1307 1308 /* 1309 * free the buffer header back to the swap buffer pool 1310 */ 1311 relpbuf(bp); 1312 HOLDRELE(vp); 1313 1314 if (!error) { 1315 for (i = 0; i < count; i++) { 1316 pmap_clear_modify(VM_PAGE_TO_PHYS(m[i])); |
1512 m[i]->flags |= PG_CLEAN; 1513 m[i]->flags &= ~PG_LAUNDRY; | 1317 m[i]->dirty = 0; |
1514 rtvals[i] = VM_PAGER_OK; 1515 } 1516 } else if (count != 1) { 1517 error = 0; 1518 count = 1; 1519 goto retryoutput; 1520 } 1521 if (error) { 1522 printf("vnode_pager_output: I/O write error\n"); 1523 } | 1318 rtvals[i] = VM_PAGER_OK; 1319 } 1320 } else if (count != 1) { 1321 error = 0; 1322 count = 1; 1323 goto retryoutput; 1324 } 1325 if (error) { 1326 printf("vnode_pager_output: I/O write error\n"); 1327 } |
1524 return (error ? VM_PAGER_ERROR: VM_PAGER_OK); | 1328 return (error ? VM_PAGER_ERROR : VM_PAGER_OK); |
1525} | 1329} |