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 * Copyright (c) 1995, David Greenman 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * from: @(#)vnode_pager.c 7.5 (Berkeley) 4/20/91 41 * $Id: vnode_pager.c,v 1.57 1995/12/17 23:29:56 dyson Exp $ 42 */ 43 44 /* 45 * Page to/from files (vnodes). 46 */ 47 48 /* 49 * TODO: 50 * Implement VOP_GETPAGES/PUTPAGES interface for filesystems. Will 51 * greatly re-simplify the vnode_pager. 52 */ 53 54 #include <sys/param.h> 55 #include <sys/systm.h> 56 #include <sys/kernel.h> 57 #include <sys/proc.h> 58 #include <sys/malloc.h> 59 #include <sys/vnode.h> 60 #include <sys/uio.h> 61 #include <sys/mount.h> 62 #include <sys/buf.h> 63 #include <sys/vmmeter.h> 64 65 #include <vm/vm.h> 66 #include <vm/vm_param.h> 67 #include <vm/vm_prot.h> 68 #include <vm/vm_object.h> 69 #include <vm/vm_page.h> 70 #include <vm/vm_pager.h> 71 #include <vm/vnode_pager.h> 72 #include <vm/vm_extern.h> 73 74 static vm_offset_t vnode_pager_addr __P((struct vnode *vp, vm_ooffset_t address, 75 int *run)); 76 static void vnode_pager_iodone __P((struct buf *bp)); 77 static int vnode_pager_input_smlfs __P((vm_object_t object, vm_page_t m)); 78 static int vnode_pager_input_old __P((vm_object_t object, vm_page_t m)); 79 static void vnode_pager_dealloc __P((vm_object_t)); 80 static int vnode_pager_getpages __P((vm_object_t, vm_page_t *, int, int)); 81 static int vnode_pager_putpages __P((vm_object_t, vm_page_t *, int, boolean_t, int *)); 82 static boolean_t vnode_pager_haspage __P((vm_object_t, vm_pindex_t, int *, int *)); 83 84 struct pagerops vnodepagerops = { 85 NULL, 86 vnode_pager_alloc, 87 vnode_pager_dealloc, 88 vnode_pager_getpages, 89 vnode_pager_putpages, 90 vnode_pager_haspage, 91 NULL 92 }; 93 94 static int vnode_pager_leaf_getpages __P((vm_object_t object, vm_page_t *m, 95 int count, int reqpage)); 96 static int vnode_pager_leaf_putpages __P((vm_object_t object, vm_page_t *m, 97 int count, boolean_t sync, 98 int *rtvals)); 99 100 /* 101 * Allocate (or lookup) pager for a vnode. 102 * Handle is a vnode pointer. 103 */ 104 vm_object_t 105 vnode_pager_alloc(handle, size, prot, offset) 106 void *handle; 107 vm_size_t size; 108 vm_prot_t prot; 109 vm_ooffset_t offset; 110 { 111 vm_object_t object; 112 struct vnode *vp; 113 114 /* 115 * Pageout to vnode, no can do yet. 116 */ 117 if (handle == NULL) 118 return (NULL); 119 120 vp = (struct vnode *) handle; 121 122 /* 123 * Prevent race condition when allocating the object. This 124 * can happen with NFS vnodes since the nfsnode isn't locked. 125 */ 126 while (vp->v_flag & VOLOCK) { 127 vp->v_flag |= VOWANT; 128 tsleep(vp, PVM, "vnpobj", 0); 129 } 130 vp->v_flag |= VOLOCK; 131 132 /* 133 * If the object is being terminated, wait for it to 134 * go away. 135 */ 136 while (((object = vp->v_object) != NULL) && 137 (object->flags & OBJ_DEAD)) { 138 tsleep(object, PVM, "vadead", 0); 139 } 140 141 if (object == NULL) { 142 /* 143 * And an object of the appropriate size 144 */ 145 object = vm_object_allocate(OBJT_VNODE, size); 146 object->flags = OBJ_CANPERSIST; 147 148 /* 149 * Hold a reference to the vnode and initialize object data. 150 */ 151 VREF(vp); 152 object->un_pager.vnp.vnp_size = (vm_ooffset_t) size * PAGE_SIZE; 153 154 object->handle = handle; 155 vp->v_object = object; 156 } else { 157 /* 158 * vm_object_reference() will remove the object from the cache if 159 * found and gain a reference to the object. 160 */ 161 vm_object_reference(object); 162 } 163 164 if (vp->v_type == VREG) 165 vp->v_flag |= VVMIO; 166 167 vp->v_flag &= ~VOLOCK; 168 if (vp->v_flag & VOWANT) { 169 vp->v_flag &= ~VOWANT; 170 wakeup(vp); 171 } 172 return (object); 173 } 174 175 static void 176 vnode_pager_dealloc(object) 177 vm_object_t object; 178 { 179 register struct vnode *vp = object->handle; 180 181 if (vp == NULL) 182 panic("vnode_pager_dealloc: pager already dealloced"); 183 184 if (object->paging_in_progress) { 185 int s = splbio(); 186 while (object->paging_in_progress) { 187 object->flags |= OBJ_PIPWNT; 188 tsleep(object, PVM, "vnpdea", 0); 189 } 190 splx(s); 191 } 192 193 object->handle = NULL; 194 195 vp->v_object = NULL; 196 vp->v_flag &= ~(VTEXT | VVMIO); 197 vp->v_flag |= VAGE; 198 vrele(vp); 199 } 200 201 static boolean_t 202 vnode_pager_haspage(object, pindex, before, after) 203 vm_object_t object; 204 vm_pindex_t pindex; 205 int *before; 206 int *after; 207 { 208 struct vnode *vp = object->handle; 209 daddr_t bn; 210 int err; 211 daddr_t reqblock; 212 int poff; 213 int bsize; 214 int pagesperblock, blocksperpage; 215 216 /* 217 * If filesystem no longer mounted or offset beyond end of file we do 218 * not have the page. 219 */ 220 if ((vp->v_mount == NULL) || 221 (IDX_TO_OFF(pindex) >= object->un_pager.vnp.vnp_size)) 222 return FALSE; 223 224 bsize = vp->v_mount->mnt_stat.f_iosize; 225 pagesperblock = bsize / PAGE_SIZE; 226 blocksperpage = 0; 227 if (pagesperblock > 0) { 228 reqblock = pindex / pagesperblock; 229 } else { 230 blocksperpage = (PAGE_SIZE / bsize); 231 reqblock = pindex * blocksperpage; 232 } 233 err = VOP_BMAP(vp, reqblock, (struct vnode **) 0, &bn, 234 after, before); 235 if (err) 236 return TRUE; 237 if ( bn == -1) 238 return FALSE; 239 if (pagesperblock > 0) { 240 poff = pindex - (reqblock * pagesperblock); 241 if (before) { 242 *before *= pagesperblock; 243 *before += poff; 244 } 245 if (after) { 246 int numafter; 247 *after *= pagesperblock; 248 numafter = pagesperblock - (poff + 1); 249 if (IDX_TO_OFF(pindex + numafter) > object->un_pager.vnp.vnp_size) { 250 numafter = OFF_TO_IDX((object->un_pager.vnp.vnp_size - IDX_TO_OFF(pindex))); 251 } 252 *after += numafter; 253 } 254 } else { 255 if (before) { 256 *before /= blocksperpage; 257 } 258 259 if (after) { 260 *after /= blocksperpage; 261 } 262 } 263 return TRUE; 264 } 265 266 /* 267 * Lets the VM system know about a change in size for a file. 268 * We adjust our own internal size and flush any cached pages in 269 * the associated object that are affected by the size change. 270 * 271 * Note: this routine may be invoked as a result of a pager put 272 * operation (possibly at object termination time), so we must be careful. 273 */ 274 void 275 vnode_pager_setsize(vp, nsize) 276 struct vnode *vp; 277 vm_ooffset_t nsize; 278 { 279 vm_object_t object = vp->v_object; 280 281 if (object == NULL) 282 return; 283 284 /* 285 * Hasn't changed size 286 */ 287 if (nsize == object->un_pager.vnp.vnp_size) 288 return; 289 290 /* 291 * File has shrunk. Toss any cached pages beyond the new EOF. 292 */ 293 if (nsize < object->un_pager.vnp.vnp_size) { 294 vm_ooffset_t nsizerounded; 295 nsizerounded = IDX_TO_OFF(OFF_TO_IDX(nsize + PAGE_SIZE - 1)); 296 if (nsizerounded < object->un_pager.vnp.vnp_size) { 297 vm_object_page_remove(object, 298 OFF_TO_IDX(nsize + PAGE_SIZE - 1), 299 OFF_TO_IDX(object->un_pager.vnp.vnp_size), 300 FALSE); 301 } 302 /* 303 * this gets rid of garbage at the end of a page that is now 304 * only partially backed by the vnode... 305 */ 306 if (nsize & PAGE_MASK) { 307 vm_offset_t kva; 308 vm_page_t m; 309 310 m = vm_page_lookup(object, OFF_TO_IDX(nsize)); 311 if (m) { 312 kva = vm_pager_map_page(m); 313 bzero((caddr_t) kva + (nsize & PAGE_MASK), 314 (int) (round_page(nsize) - nsize)); 315 vm_pager_unmap_page(kva); 316 } 317 } 318 } 319 object->un_pager.vnp.vnp_size = nsize; 320 object->size = OFF_TO_IDX(nsize + PAGE_SIZE - 1); 321 } 322 323 void 324 vnode_pager_umount(mp) 325 register struct mount *mp; 326 { 327 struct vnode *vp, *nvp; 328 329 loop: 330 for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { 331 /* 332 * Vnode can be reclaimed by getnewvnode() while we 333 * traverse the list. 334 */ 335 if (vp->v_mount != mp) 336 goto loop; 337 338 /* 339 * Save the next pointer now since uncaching may terminate the 340 * object and render vnode invalid 341 */ 342 nvp = vp->v_mntvnodes.le_next; 343 344 if (vp->v_object != NULL) { 345 VOP_LOCK(vp); 346 vnode_pager_uncache(vp); 347 VOP_UNLOCK(vp); 348 } 349 } 350 } 351 352 /* 353 * Remove vnode associated object from the object cache. 354 * This routine must be called with the vnode locked. 355 * 356 * XXX unlock the vnode. 357 * We must do this since uncaching the object may result in its 358 * destruction which may initiate paging activity which may necessitate 359 * re-locking the vnode. 360 */ 361 void 362 vnode_pager_uncache(vp) 363 struct vnode *vp; 364 { 365 vm_object_t object; 366 367 /* 368 * Not a mapped vnode 369 */ 370 object = vp->v_object; 371 if (object == NULL) 372 return; 373 374 vm_object_reference(object); 375 VOP_UNLOCK(vp); 376 pager_cache(object, FALSE); 377 VOP_LOCK(vp); 378 return; 379 } 380 381 382 void 383 vnode_pager_freepage(m) 384 vm_page_t m; 385 { 386 PAGE_WAKEUP(m); 387 vm_page_free(m); 388 } 389 390 /* 391 * calculate the linear (byte) disk address of specified virtual 392 * file address 393 */ 394 static vm_offset_t 395 vnode_pager_addr(vp, address, run) 396 struct vnode *vp; 397 vm_ooffset_t address; 398 int *run; 399 { 400 int rtaddress; 401 int bsize; 402 daddr_t block; 403 struct vnode *rtvp; 404 int err; 405 daddr_t vblock; 406 int voffset; 407 408 if ((int) address < 0) 409 return -1; 410 411 if (vp->v_mount == NULL) 412 return -1; 413 414 bsize = vp->v_mount->mnt_stat.f_iosize; 415 vblock = address / bsize; 416 voffset = address % bsize; 417 418 err = VOP_BMAP(vp, vblock, &rtvp, &block, run, NULL); 419 420 if (err || (block == -1)) 421 rtaddress = -1; 422 else { 423 rtaddress = block + voffset / DEV_BSIZE; 424 if( run) { 425 *run += 1; 426 *run *= bsize/PAGE_SIZE; 427 *run -= voffset/PAGE_SIZE; 428 } 429 } 430 431 return rtaddress; 432 } 433 434 /* 435 * interrupt routine for I/O completion 436 */ 437 static void 438 vnode_pager_iodone(bp) 439 struct buf *bp; 440 { 441 bp->b_flags |= B_DONE; 442 wakeup(bp); 443 } 444 445 /* 446 * small block file system vnode pager input 447 */ 448 static int 449 vnode_pager_input_smlfs(object, m) 450 vm_object_t object; 451 vm_page_t m; 452 { 453 int i; 454 int s; 455 struct vnode *dp, *vp; 456 struct buf *bp; 457 vm_offset_t kva; 458 int fileaddr; 459 vm_offset_t bsize; 460 int error = 0; 461 462 vp = object->handle; 463 if (vp->v_mount == NULL) 464 return VM_PAGER_BAD; 465 466 bsize = vp->v_mount->mnt_stat.f_iosize; 467 468 469 VOP_BMAP(vp, 0, &dp, 0, NULL, NULL); 470 471 kva = vm_pager_map_page(m); 472 473 for (i = 0; i < PAGE_SIZE / bsize; i++) { 474 475 if ((vm_page_bits(IDX_TO_OFF(m->pindex) + i * bsize, bsize) & m->valid)) 476 continue; 477 478 fileaddr = vnode_pager_addr(vp, 479 IDX_TO_OFF(m->pindex) + i * bsize, (int *)0); 480 if (fileaddr != -1) { 481 bp = getpbuf(); 482 483 /* build a minimal buffer header */ 484 bp->b_flags = B_BUSY | B_READ | B_CALL; 485 bp->b_iodone = vnode_pager_iodone; 486 bp->b_proc = curproc; 487 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred; 488 if (bp->b_rcred != NOCRED) 489 crhold(bp->b_rcred); 490 if (bp->b_wcred != NOCRED) 491 crhold(bp->b_wcred); 492 bp->b_un.b_addr = (caddr_t) kva + i * bsize; 493 bp->b_blkno = fileaddr; 494 pbgetvp(dp, bp); 495 bp->b_bcount = bsize; 496 bp->b_bufsize = bsize; 497 498 /* do the input */ 499 VOP_STRATEGY(bp); 500 501 /* we definitely need to be at splbio here */ 502 503 s = splbio(); 504 while ((bp->b_flags & B_DONE) == 0) { 505 tsleep(bp, PVM, "vnsrd", 0); 506 } 507 splx(s); 508 if ((bp->b_flags & B_ERROR) != 0) 509 error = EIO; 510 511 /* 512 * free the buffer header back to the swap buffer pool 513 */ 514 relpbuf(bp); 515 if (error) 516 break; 517 518 vm_page_set_validclean(m, (i * bsize) & (PAGE_SIZE-1), bsize); 519 } else { 520 vm_page_set_validclean(m, (i * bsize) & (PAGE_SIZE-1), bsize); 521 bzero((caddr_t) kva + i * bsize, bsize); 522 } 523 } 524 vm_pager_unmap_page(kva); 525 pmap_clear_modify(VM_PAGE_TO_PHYS(m)); 526 m->flags &= ~PG_ZERO; 527 if (error) { 528 return VM_PAGER_ERROR; 529 } 530 return VM_PAGER_OK; 531 532 } 533 534 535 /* 536 * old style vnode pager output routine 537 */ 538 static int 539 vnode_pager_input_old(object, m) 540 vm_object_t object; 541 vm_page_t m; 542 { 543 struct uio auio; 544 struct iovec aiov; 545 int error; 546 int size; 547 vm_offset_t kva; 548 549 error = 0; 550 551 /* 552 * Return failure if beyond current EOF 553 */ 554 if (IDX_TO_OFF(m->pindex) >= object->un_pager.vnp.vnp_size) { 555 return VM_PAGER_BAD; 556 } else { 557 size = PAGE_SIZE; 558 if (IDX_TO_OFF(m->pindex) + size > object->un_pager.vnp.vnp_size) 559 size = object->un_pager.vnp.vnp_size - IDX_TO_OFF(m->pindex); 560 561 /* 562 * Allocate a kernel virtual address and initialize so that 563 * we can use VOP_READ/WRITE routines. 564 */ 565 kva = vm_pager_map_page(m); 566 567 aiov.iov_base = (caddr_t) kva; 568 aiov.iov_len = size; 569 auio.uio_iov = &aiov; 570 auio.uio_iovcnt = 1; 571 auio.uio_offset = IDX_TO_OFF(m->pindex); 572 auio.uio_segflg = UIO_SYSSPACE; 573 auio.uio_rw = UIO_READ; 574 auio.uio_resid = size; 575 auio.uio_procp = (struct proc *) 0; 576 577 error = VOP_READ(object->handle, &auio, 0, curproc->p_ucred); 578 if (!error) { 579 register int count = size - auio.uio_resid; 580 581 if (count == 0) 582 error = EINVAL; 583 else if (count != PAGE_SIZE) 584 bzero((caddr_t) kva + count, PAGE_SIZE - count); 585 } 586 vm_pager_unmap_page(kva); 587 } 588 pmap_clear_modify(VM_PAGE_TO_PHYS(m)); 589 m->dirty = 0; 590 m->flags &= ~PG_ZERO; 591 return error ? VM_PAGER_ERROR : VM_PAGER_OK; 592 } 593 594 /* 595 * generic vnode pager input routine 596 */ 597 598 static int 599 vnode_pager_getpages(object, m, count, reqpage) 600 vm_object_t object; 601 vm_page_t *m; 602 int count; 603 int reqpage; 604 { 605 int rtval; 606 struct vnode *vp; 607 vp = object->handle; 608 rtval = VOP_GETPAGES(vp, m, count*PAGE_SIZE, reqpage, 0); 609 if (rtval == EOPNOTSUPP) 610 return vnode_pager_leaf_getpages(object, m, count, reqpage); 611 else 612 return rtval; 613 } 614 615 static int 616 vnode_pager_leaf_getpages(object, m, count, reqpage) 617 vm_object_t object; 618 vm_page_t *m; 619 int count; 620 int reqpage; 621 { 622 vm_offset_t kva; 623 off_t foff; 624 int i, size, bsize, first, firstaddr; 625 struct vnode *dp, *vp; 626 int runpg; 627 int runend; 628 struct buf *bp; 629 int s; 630 int error = 0; 631 632 vp = object->handle; 633 if (vp->v_mount == NULL) 634 return VM_PAGER_BAD; 635 636 bsize = vp->v_mount->mnt_stat.f_iosize; 637 638 /* get the UNDERLYING device for the file with VOP_BMAP() */ 639 640 /* 641 * originally, we did not check for an error return value -- assuming 642 * an fs always has a bmap entry point -- that assumption is wrong!!! 643 */ 644 foff = IDX_TO_OFF(m[reqpage]->pindex); 645 646 /* 647 * if we can't bmap, use old VOP code 648 */ 649 if (VOP_BMAP(vp, 0, &dp, 0, NULL, NULL)) { 650 for (i = 0; i < count; i++) { 651 if (i != reqpage) { 652 vnode_pager_freepage(m[i]); 653 } 654 } 655 cnt.v_vnodein++; 656 cnt.v_vnodepgsin++; 657 return vnode_pager_input_old(object, m[reqpage]); 658 659 /* 660 * if the blocksize is smaller than a page size, then use 661 * special small filesystem code. NFS sometimes has a small 662 * blocksize, but it can handle large reads itself. 663 */ 664 } else if ((PAGE_SIZE / bsize) > 1 && 665 (vp->v_mount->mnt_stat.f_type != MOUNT_NFS)) { 666 667 for (i = 0; i < count; i++) { 668 if (i != reqpage) { 669 vnode_pager_freepage(m[i]); 670 } 671 } 672 cnt.v_vnodein++; 673 cnt.v_vnodepgsin++; 674 return vnode_pager_input_smlfs(object, m[reqpage]); 675 } 676 /* 677 * if ANY DEV_BSIZE blocks are valid on a large filesystem block 678 * then, the entire page is valid -- 679 */ 680 if (m[reqpage]->valid) { 681 m[reqpage]->valid = VM_PAGE_BITS_ALL; 682 for (i = 0; i < count; i++) { 683 if (i != reqpage) 684 vnode_pager_freepage(m[i]); 685 } 686 return VM_PAGER_OK; 687 } 688 689 /* 690 * here on direct device I/O 691 */ 692 693 firstaddr = -1; 694 /* 695 * calculate the run that includes the required page 696 */ 697 for(first = 0, i = 0; i < count; i = runend) { 698 firstaddr = vnode_pager_addr(vp, 699 IDX_TO_OFF(m[i]->pindex), &runpg); 700 if (firstaddr == -1) { 701 if (i == reqpage && foff < object->un_pager.vnp.vnp_size) { 702 panic("vnode_pager_putpages: unexpected missing page: firstaddr: %d, foff: %ld, vnp_size: %d", 703 firstaddr, foff, object->un_pager.vnp.vnp_size); 704 } 705 vnode_pager_freepage(m[i]); 706 runend = i + 1; 707 first = runend; 708 continue; 709 } 710 runend = i + runpg; 711 if (runend <= reqpage) { 712 int j; 713 for (j = i; j < runend; j++) { 714 vnode_pager_freepage(m[j]); 715 } 716 } else { 717 if (runpg < (count - first)) { 718 for (i = first + runpg; i < count; i++) 719 vnode_pager_freepage(m[i]); 720 count = first + runpg; 721 } 722 break; 723 } 724 first = runend; 725 } 726 727 /* 728 * the first and last page have been calculated now, move input pages 729 * to be zero based... 730 */ 731 if (first != 0) { 732 for (i = first; i < count; i++) { 733 m[i - first] = m[i]; 734 } 735 count -= first; 736 reqpage -= first; 737 } 738 739 /* 740 * calculate the file virtual address for the transfer 741 */ 742 foff = IDX_TO_OFF(m[0]->pindex); 743 744 /* 745 * calculate the size of the transfer 746 */ 747 size = count * PAGE_SIZE; 748 if ((foff + size) > object->un_pager.vnp.vnp_size) 749 size = object->un_pager.vnp.vnp_size - foff; 750 751 /* 752 * round up physical size for real devices 753 */ 754 if (dp->v_type == VBLK || dp->v_type == VCHR) 755 size = (size + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); 756 757 bp = getpbuf(); 758 kva = (vm_offset_t) bp->b_data; 759 760 /* 761 * and map the pages to be read into the kva 762 */ 763 pmap_qenter(kva, m, count); 764 765 /* build a minimal buffer header */ 766 bp->b_flags = B_BUSY | B_READ | B_CALL; 767 bp->b_iodone = vnode_pager_iodone; 768 /* B_PHYS is not set, but it is nice to fill this in */ 769 bp->b_proc = curproc; 770 bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred; 771 if (bp->b_rcred != NOCRED) 772 crhold(bp->b_rcred); 773 if (bp->b_wcred != NOCRED) 774 crhold(bp->b_wcred); 775 bp->b_blkno = firstaddr; 776 pbgetvp(dp, bp); 777 bp->b_bcount = size; 778 bp->b_bufsize = size; 779 780 cnt.v_vnodein++; 781 cnt.v_vnodepgsin += count; 782 783 /* do the input */ 784 VOP_STRATEGY(bp); 785 786 s = splbio(); 787 /* we definitely need to be at splbio here */ 788 789 while ((bp->b_flags & B_DONE) == 0) { 790 tsleep(bp, PVM, "vnread", 0); 791 } 792 splx(s); 793 if ((bp->b_flags & B_ERROR) != 0) 794 error = EIO; 795 796 if (!error) { 797 if (size != count * PAGE_SIZE) 798 bzero((caddr_t) kva + size, PAGE_SIZE * count - size); 799 } 800 pmap_qremove(kva, count); 801 802 /* 803 * free the buffer header back to the swap buffer pool 804 */ 805 relpbuf(bp); 806 807 for (i = 0; i < count; i++) { 808 pmap_clear_modify(VM_PAGE_TO_PHYS(m[i])); 809 m[i]->dirty = 0; 810 m[i]->valid = VM_PAGE_BITS_ALL; 811 m[i]->flags &= ~PG_ZERO; 812 if (i != reqpage) { 813 814 /* 815 * whether or not to leave the page activated is up in 816 * the air, but we should put the page on a page queue 817 * somewhere. (it already is in the object). Result: 818 * It appears that emperical results show that 819 * deactivating pages is best. 820 */ 821 822 /* 823 * just in case someone was asking for this page we 824 * now tell them that it is ok to use 825 */ 826 if (!error) { 827 vm_page_deactivate(m[i]); 828 PAGE_WAKEUP(m[i]); 829 } else { 830 vnode_pager_freepage(m[i]); 831 } 832 } 833 } 834 if (error) { 835 printf("vnode_pager_getpages: I/O read error\n"); 836 } 837 return (error ? VM_PAGER_ERROR : VM_PAGER_OK); 838 } 839 840 static int 841 vnode_pager_putpages(object, m, count, sync, rtvals) 842 vm_object_t object; 843 vm_page_t *m; 844 int count; 845 boolean_t sync; 846 int *rtvals; 847 { 848 int rtval; 849 struct vnode *vp; 850 vp = object->handle; 851 rtval = VOP_PUTPAGES(vp, m, count*PAGE_SIZE, sync, rtvals, 0); 852 if (rtval == EOPNOTSUPP) 853 return vnode_pager_leaf_putpages(object, m, count, sync, rtvals); 854 else 855 return rtval; 856 } 857 858 /* 859 * generic vnode pager output routine 860 */ 861 static int 862 vnode_pager_leaf_putpages(object, m, count, sync, rtvals) 863 vm_object_t object; 864 vm_page_t *m; 865 int count; 866 boolean_t sync; 867 int *rtvals; 868 { 869 int i; 870 871 struct vnode *vp; 872 int maxsize, ncount; 873 vm_ooffset_t poffset; 874 struct uio auio; 875 struct iovec aiov; 876 int error; 877 878 vp = object->handle;; 879 for (i = 0; i < count; i++) 880 rtvals[i] = VM_PAGER_AGAIN; 881 882 if ((int) m[0]->pindex < 0) { 883 printf("vnode_pager_putpages: attempt to write meta-data!!! -- 0x%x(%x)\n", m[0]->pindex, m[0]->dirty); 884 rtvals[0] = VM_PAGER_BAD; 885 return VM_PAGER_BAD; 886 } 887 888 maxsize = count * PAGE_SIZE; 889 ncount = count; 890 891 poffset = IDX_TO_OFF(m[0]->pindex); 892 if (maxsize + poffset > object->un_pager.vnp.vnp_size) { 893 if (object->un_pager.vnp.vnp_size > poffset) 894 maxsize = object->un_pager.vnp.vnp_size - poffset; 895 else 896 maxsize = 0; 897 ncount = (maxsize + PAGE_SIZE - 1) / PAGE_SIZE; 898 if (ncount < count) { 899 for (i = ncount; i < count; i++) { 900 rtvals[i] = VM_PAGER_BAD; 901 } 902 #ifdef BOGUS 903 if (ncount == 0) { 904 printf("vnode_pager_putpages: write past end of file: %d, %lu\n", 905 poffset, 906 (unsigned long) object->un_pager.vnp.vnp_size); 907 return rtvals[0]; 908 } 909 #endif 910 } 911 } 912 913 for (i = 0; i < count; i++) { 914 m[i]->busy++; 915 m[i]->flags &= ~PG_BUSY; 916 } 917 918 aiov.iov_base = (caddr_t) 0; 919 aiov.iov_len = maxsize; 920 auio.uio_iov = &aiov; 921 auio.uio_iovcnt = 1; 922 auio.uio_offset = poffset; 923 auio.uio_segflg = UIO_NOCOPY; 924 auio.uio_rw = UIO_WRITE; 925 auio.uio_resid = maxsize; 926 auio.uio_procp = (struct proc *) 0; 927 error = VOP_WRITE(vp, &auio, IO_VMIO|(sync?IO_SYNC:0), curproc->p_ucred); 928 cnt.v_vnodeout++; 929 cnt.v_vnodepgsout += ncount; 930 931 if (error) { 932 printf("vnode_pager_putpages: I/O error %d\n", error); 933 } 934 if (auio.uio_resid) { 935 printf("vnode_pager_putpages: residual I/O %d at %ld\n", 936 auio.uio_resid, m[0]->pindex); 937 } 938 for (i = 0; i < count; i++) { 939 m[i]->busy--; 940 if (i < ncount) { 941 rtvals[i] = VM_PAGER_OK; 942 } 943 if ((m[i]->busy == 0) && (m[i]->flags & PG_WANTED)) 944 wakeup(m[i]); 945 } 946 return rtvals[0]; 947 } 948 949 struct vnode * 950 vnode_pager_lock(object) 951 vm_object_t object; 952 { 953 for (; object != NULL; object = object->backing_object) { 954 if (object->type != OBJT_VNODE) 955 continue; 956 957 VOP_LOCK(object->handle); 958 return object->handle; 959 } 960 return NULL; 961 } 962