vnode_pager.c revision 4797
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 9 * Science Department. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 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 $ 41 */ 42 43/* 44 * Page to/from files (vnodes). 45 * 46 * TODO: 47 * pageouts 48 * fix credential use (uses current process credentials now) 49 */ 50 51/* 52 * MODIFICATIONS: 53 * John S. Dyson 08 Dec 93 54 * 55 * This file in conjunction with some vm_fault mods, eliminate the performance 56 * advantage for using the buffer cache and minimize memory copies. 57 * 58 * 1) Supports multiple - block reads 59 * 2) Bypasses buffer cache for reads 60 * 61 * TODO: 62 * 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/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 84int vnode_pager_putmulti(); 85 86void vnode_pager_init(); 87vm_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(); 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, 100 vnode_pager_putpage, 101 vnode_pager_putmulti, 102 vnode_pager_haspage 103}; 104 105 106 107static int vnode_pager_input(vn_pager_t vnp, vm_page_t * m, int count, int reqpage); 108static int vnode_pager_output(vn_pager_t vnp, vm_page_t * m, int count, int *rtvals); 109 110extern vm_map_t pager_map; 111 112struct pagerlst vnode_pager_list; /* list of managed vnodes */ 113 114#define MAXBP (PAGE_SIZE/DEV_BSIZE); 115 116void 117vnode_pager_init() 118{ 119 TAILQ_INIT(&vnode_pager_list); 120} 121 122/* 123 * Allocate (or lookup) pager for a vnode. 124 * Handle is a vnode pointer. 125 */ 126vm_pager_t 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; 135 vm_object_t object; 136 struct vattr vattr; 137 struct vnode *vp; 138 struct proc *p = curproc; /* XXX */ 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; 151 object = (vm_object_t) vp->v_vmdata; 152 pager = NULL; 153 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 } 168 169 /* 170 * And an object of the appropriate size 171 */ 172 if (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 { 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 */ 185 VREF(vp); 186 vnp->vnp_flags = 0; 187 vnp->vnp_vp = vp; 188 vnp->vnp_size = vattr.va_size; 189 190 TAILQ_INSERT_TAIL(&vnode_pager_list, pager, pg_list); 191 pager->pg_handle = handle; 192 pager->pg_type = PG_VNODE; 193 pager->pg_ops = &vnodepagerops; 194 pager->pg_data = (caddr_t) vnp; 195 vp->v_vmdata = (caddr_t) object; 196 } else { 197 198 /* 199 * vm_object_lookup() will remove the object from the cache if 200 * found and also gain a reference to the object. 201 */ 202 (void) vm_object_lookup(pager); 203 } 204 return (pager); 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; 213 214 vp = vnp->vnp_vp; 215 if (vp) { 216 vp->v_vmdata = NULL; 217 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; 229 int count; 230 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) 239 vm_pager_t pager; 240 vm_page_t m; 241 boolean_t sync; 242{ 243 244 vm_page_t marray[1]; 245 246 if (pager == NULL) 247 return FALSE; 248 marray[0] = m; 249 250 return vnode_pager_input((vn_pager_t) pager->pg_data, marray, 1, 0); 251} 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]; 260 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; 273 int c; 274 boolean_t sync; 275 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; 289 int err; 290 daddr_t block; 291 292 /* 293 * If filesystem no longer mounted or offset beyond end of 294 * file we do 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); 309/* 310 printf("vnode_pager_haspage: (%d)0x%x: err: %d, bn: %d\n", 311 offset, offset, err, bn); 312*/ 313 if (err) { 314 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; 331 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; 347 if( object == NULL) 348 return; 349 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) { 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 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), 386 round_page(nsize) - nsize); 387 vm_pager_unmap_page(kva); 388 } 389 } 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 417vnode_pager_umount(mp) 418 register struct mount *mp; 419{ 420 register vm_pager_t pager, npager; 421 struct vnode *vp; 422 423 pager = vnode_pager_list.tqh_first; 424 while (pager) { 425 426 /* 427 * Save the next pointer now since uncaching may terminate the 428 * object and render pager invalid 429 */ 430 vp = ((vn_pager_t) pager->pg_data)->vnp_vp; 431 npager = pager->pg_list.tqe_next; 432 if (mp == (struct mount *) 0 || vp->v_mount == mp) 433 (void) vnode_pager_uncache(vp); 434 pager = npager; 435 } 436} 437 438/* 439 * Remove vnode associated object from the object cache. 440 * 441 * Note: this routine may be invoked as a result of a pager put 442 * operation (possibly at object termination time), so we must be careful. 443 */ 444boolean_t 445vnode_pager_uncache(vp) 446 register struct vnode *vp; 447{ 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; 456 if( object == NULL) 457 return(TRUE); 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. 466 */ 467 locked = VOP_ISLOCKED(vp); 468 if (locked) 469 VOP_UNLOCK(vp); 470 471 /* 472 * Must use vm_object_lookup() as it actually removes the object from 473 * the cache list. 474 */ 475 object = vm_object_lookup(pager); 476 if (object) { 477 uncached = (object->ref_count <= 1); 478 pager_cache(object, FALSE); 479 } else 480 uncached = TRUE; 481 if (locked) 482 VOP_LOCK(vp); 483 return (uncached); 484} 485 486 487void 488vnode_pager_freepage(m) 489 vm_page_t m; 490{ 491 PAGE_WAKEUP(m); 492 vm_page_free(m); 493} 494 495/* 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{ 504 int rtaddress; 505 int bsize; 506 vm_offset_t block; 507 struct vnode *rtvp; 508 int err; 509 int vblock, voffset; 510 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; 519 else 520 rtaddress = block * DEV_BSIZE + voffset; 521 522 return rtaddress; 523} 524 525/* 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); 534 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; 542 if( bp->b_bufsize != bp->b_bcount) 543 bzero( bp->b_data + bp->b_bcount, 544 bp->b_bufsize - bp->b_bcount); 545 546 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++) { 552 m = PHYS_TO_VM_PAGE(pmap_kextract(paddr + i * PAGE_SIZE)); 553 obj = m->object; 554 if( m) { 555 m->flags |= PG_CLEAN; 556 m->flags &= ~(PG_LAUNDRY|PG_FAKE); 557 PAGE_WAKEUP(m); 558 } else { 559 panic("vnode_pager_iodone: page is gone!!!"); 560 } 561 } 562 pmap_qremove( paddr, npages); 563 if( obj) { 564 --obj->paging_in_progress; 565 if( obj->paging_in_progress == 0) 566 wakeup((caddr_t) obj); 567 } else { 568 panic("vnode_pager_iodone: object is gone???"); 569 } 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{ 583 int i; 584 int s; 585 vm_offset_t paging_offset; 586 struct vnode *dp, *vp; 587 struct buf *bp; 588 vm_offset_t foff; 589 vm_offset_t kva; 590 int fileaddr; 591 int block; 592 vm_offset_t bsize; 593 int error = 0; 594 595 paging_offset = m->object->paging_offset; 596 vp = vnp->vnp_vp; 597 bsize = vp->v_mount->mnt_stat.f_iosize; 598 foff = m->offset + paging_offset; 599 600 VOP_BMAP(vp, foff, &dp, 0, 0); 601 602 kva = vm_pager_map_page(m); 603 604 for (i = 0; i < PAGE_SIZE / bsize; i++) { 605 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; 613 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); 648 if (fileaddr != -1) { 649 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; 663 bgetvp(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 672 s = splbio(); 673 while ((bp->b_flags & B_DONE) == 0) { 674 tsleep((caddr_t) bp, PVM, "vnsrd", 0); 675 } 676 splx(s); 677 if ((bp->b_flags & B_ERROR) != 0) 678 error = EIO; 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; 687 } else { 688 bzero((caddr_t) kva + i * bsize, bsize); 689 } 690nextblock: 691 } 692 vm_pager_unmap_page(kva); 693 if (error) { 694 return VM_PAGER_ERROR; 695 } 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; 714 int error; 715 int size; 716 vm_offset_t foff; 717 vm_offset_t kva; 718 719 error = 0; 720 foff = m->offset + m->object->paging_offset; 721 722 /* 723 * Return failure if beyond current EOF 724 */ 725 if (foff >= vnp->vnp_size) { 726 return VM_PAGER_BAD; 727 } else { 728 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 */ 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; 740 auio.uio_offset = foff; 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)); 758 m->flags |= PG_CLEAN; 759 m->flags &= ~PG_LAUNDRY; 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; 770 int count, reqpage; 771{ 772 int i; 773 vm_offset_t kva, foff; 774 int size, sizea; 775 vm_object_t object; 776 vm_offset_t paging_offset; 777 struct vnode *dp, *vp; 778 int bsize; 779 780 int first, last; 781 int reqaddr, firstaddr; 782 int block, offset; 783 784 struct buf *bp, *bpa; 785 int counta; 786 int s; 787 int failflag; 788 789 int error = 0; 790 791 object = m[reqpage]->object; /* all vm_page_t items are in same 792 * object */ 793 paging_offset = object->paging_offset; 794 795 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 */ 811 foff = m[reqpage]->offset + paging_offset; 812 813 /* 814 * if we can't bmap, use old VOP code 815 */ 816 if (VOP_BMAP(vp, foff, &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 && 832 (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 } 843/* 844 * here on direct device I/O 845 */ 846 847 848#ifdef NOTYET 849 if( (vp->v_flag & VVMIO) == 0) { 850#endif 851 /* 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. 858 */ 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; 941 } 942 splx(s); 943#ifdef NOTYET 944 } 945#endif 946 947 reqaddr = vnode_pager_addr(vp, foff); 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 || 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)) 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 || 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)) 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); 995 996 /* 997 * the first and last page have been calculated now, move input pages 998 * to be zero based... 999 */ 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 } 1008 1009 /* 1010 * calculate the file virtual address for the transfer 1011 */ 1012 foff = m[0]->offset + paging_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 1021 */ 1022 size = count * PAGE_SIZE; 1023 if ((foff + size) > vnp->vnp_size) 1024 size = vnp->vnp_size - foff; 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; 1033 if( count*PAGE_SIZE > bsize) 1034 counta = (count - reqpage) - 1; 1035 bpa = 0; 1036 sizea = 0; 1037 if( counta) { 1038 bpa = getpbuf(); 1039 count -= counta; 1040 sizea = size - count*PAGE_SIZE; 1041 size = count * PAGE_SIZE; 1042 } 1043 1044 bp = getpbuf(); 1045 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); 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; 1064 bgetvp(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 1074 if( counta) { 1075 for(i=0;i<counta;i++) { 1076 vm_page_deactivate(m[count+i]); 1077 } 1078 pmap_qenter((vm_offset_t)bpa->b_data, &m[count], counta); 1079 ++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; 1091 bgetvp(dp, bpa); 1092 bpa->b_bcount = sizea; 1093 bpa->b_bufsize = counta*PAGE_SIZE; 1094 1095 cnt.v_vnodepgsin += counta; 1096 VOP_STRATEGY(bpa); 1097 } 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 } 1113 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])); 1124 m[i]->flags |= PG_CLEAN; 1125 m[i]->flags &= ~PG_LAUNDRY; 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) { 1141 vm_page_deactivate(m[i]); 1142 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{ 1163 vm_offset_t foff; 1164 vm_offset_t kva; 1165 vm_offset_t size; 1166 struct iovec aiov; 1167 struct uio auio; 1168 struct vnode *vp; 1169 int error; 1170 1171 vp = vnp->vnp_vp; 1172 foff = m->offset + m->object->paging_offset; 1173 1174 /* 1175 * Return failure if beyond current EOF 1176 */ 1177 if (foff >= vnp->vnp_size) { 1178 return VM_PAGER_BAD; 1179 } else { 1180 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 */ 1187 kva = vm_pager_map_page(m); 1188 aiov.iov_base = (caddr_t) kva; 1189 aiov.iov_len = size; 1190 auio.uio_iov = &aiov; 1191 auio.uio_iovcnt = 1; 1192 auio.uio_offset = foff; 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 1200 if (!error) { 1201 if ((size - auio.uio_resid) == 0) { 1202 error = EINVAL; 1203 } 1204 } 1205 vm_pager_unmap_page(kva); 1206 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{ 1218 int i; 1219 int s; 1220 vm_offset_t paging_offset; 1221 struct vnode *dp, *vp; 1222 struct buf *bp; 1223 vm_offset_t foff; 1224 vm_offset_t kva; 1225 int fileaddr; 1226 vm_offset_t bsize; 1227 int error = 0; 1228 1229 paging_offset = m->object->paging_offset; 1230 vp = vnp->vnp_vp; 1231 bsize = vp->v_mount->mnt_stat.f_iosize; 1232 foff = m->offset + paging_offset; 1233 1234 VOP_BMAP(vp, foff, &dp, 0, 0); 1235 kva = vm_pager_map_page(m); 1236 for (i = 0; !error && i < (PAGE_SIZE / bsize); i++) { 1237 1238 /* 1239 * calculate logical block and offset 1240 */ 1241 fileaddr = vnode_pager_addr(vp, foff + i * bsize); 1242 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(); 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; 1266 bgetvp(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 */ 1275 VOP_STRATEGY(bp); 1276 1277 /* we definitely need to be at splbio here */ 1278 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 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); 1295 if (error) 1296 return VM_PAGER_ERROR; 1297 else 1298 return VM_PAGER_OK; 1299} 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; 1308 int count; 1309 int *rtvals; 1310{ 1311 int i, j; 1312 vm_offset_t kva, foff; 1313 int size; 1314 vm_object_t object; 1315 vm_offset_t paging_offset; 1316 struct vnode *dp, *vp; 1317 struct buf *bp; 1318 vm_offset_t reqaddr; 1319 int bsize; 1320 int s; 1321 1322 int error = 0; 1323 1324retryoutput: 1325 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 1341 /* 1342 * if the filesystem does not have a bmap, then use the old code 1343 */ 1344 if (VOP_BMAP(vp, m[0]->offset + paging_offset, &dp, 0, 0)) { 1345 1346 rtvals[0] = vnode_pager_output_old(vnp, m[0]); 1347 1348 pmap_clear_modify(VM_PAGE_TO_PHYS(m[0])); 1349 m[0]->flags |= PG_CLEAN; 1350 m[0]->flags &= ~PG_LAUNDRY; 1351 cnt.v_vnodeout++; 1352 cnt.v_vnodepgsout++; 1353 return rtvals[0]; 1354 } 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])); 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 } 1375 1376 for (i = 0; i < count; i++) { 1377 foff = m[i]->offset + paging_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 } 1388 foff = m[0]->offset + paging_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++) { 1396 if (vnode_pager_addr(vp, m[i]->offset + paging_offset) 1397 != reqaddr + i * PAGE_SIZE) { 1398 count = i; 1399 break; 1400 } 1401 } 1402 1403 /* 1404 * calculate the size of the transfer 1405 */ 1406 size = count * PAGE_SIZE; 1407 if ((foff + size) > vnp->vnp_size) 1408 size = vnp->vnp_size - foff; 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(); 1417 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); 1422#if 0 1423 printf("vnode: writing foff: %d, devoff: %d, size: %d\n", 1424 foff, reqaddr, size); 1425#endif 1426 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; 1473 bgetvp(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; 1482 1483 cnt.v_vnodeout++; 1484 cnt.v_vnodepgsout += count; 1485 1486 /* do the output */ 1487 VOP_STRATEGY(bp); 1488 1489 s = splbio(); 1490 1491 /* we definitely need to be at splbio here */ 1492 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 1501 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])); 1512 m[i]->flags |= PG_CLEAN; 1513 m[i]->flags &= ~PG_LAUNDRY; 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 } 1524 return (error ? VM_PAGER_ERROR: VM_PAGER_OK); 1525} 1526