145749Smckusick /* 245749Smckusick * Copyright (c) 1990 University of Utah. 363379Sbostic * Copyright (c) 1991, 1993 463379Sbostic * The Regents of the University of California. All rights reserved. 545749Smckusick * 645749Smckusick * This code is derived from software contributed to Berkeley by 745749Smckusick * the Systems Programming Group of the University of Utah Computer 845749Smckusick * Science Department. 945749Smckusick * 1045749Smckusick * %sccs.include.redist.c% 1145749Smckusick * 12*65695Shibler * @(#)vnode_pager.c 8.5 (Berkeley) 01/12/94 1345749Smckusick */ 1445749Smckusick 1545749Smckusick /* 1645749Smckusick * Page to/from files (vnodes). 1745749Smckusick * 1845749Smckusick * TODO: 1945749Smckusick * pageouts 2047977Skarels * fix credential use (uses current process credentials now) 2145749Smckusick */ 2245749Smckusick 2353342Sbostic #include <sys/param.h> 2453342Sbostic #include <sys/systm.h> 2553342Sbostic #include <sys/proc.h> 2653342Sbostic #include <sys/malloc.h> 2753342Sbostic #include <sys/vnode.h> 2853342Sbostic #include <sys/uio.h> 2953342Sbostic #include <sys/mount.h> 3047977Skarels 3153342Sbostic #include <vm/vm.h> 3253342Sbostic #include <vm/vm_page.h> 3353342Sbostic #include <vm/vnode_pager.h> 3445749Smckusick 3565231Smckusick struct pagerlst vnode_pager_list; /* list of managed vnodes */ 3645749Smckusick 3745749Smckusick #ifdef DEBUG 3845749Smckusick int vpagerdebug = 0x00; 3945749Smckusick #define VDB_FOLLOW 0x01 4045749Smckusick #define VDB_INIT 0x02 4145749Smckusick #define VDB_IO 0x04 4245749Smckusick #define VDB_FAIL 0x08 4345749Smckusick #define VDB_ALLOC 0x10 4445749Smckusick #define VDB_SIZE 0x20 4545749Smckusick #endif 4645749Smckusick 4764827Storek static vm_pager_t vnode_pager_alloc 4864827Storek __P((caddr_t, vm_size_t, vm_prot_t, vm_offset_t)); 49*65695Shibler static void vnode_pager_cluster 50*65695Shibler __P((vm_pager_t, vm_offset_t, 51*65695Shibler vm_offset_t *, vm_offset_t *)); 5253342Sbostic static void vnode_pager_dealloc __P((vm_pager_t)); 5353342Sbostic static int vnode_pager_getpage 54*65695Shibler __P((vm_pager_t, vm_page_t *, int, boolean_t)); 5553342Sbostic static boolean_t vnode_pager_haspage __P((vm_pager_t, vm_offset_t)); 5653342Sbostic static void vnode_pager_init __P((void)); 5753342Sbostic static int vnode_pager_io 58*65695Shibler __P((vn_pager_t, vm_page_t *, int, 59*65695Shibler boolean_t, enum uio_rw)); 6053342Sbostic static boolean_t vnode_pager_putpage 61*65695Shibler __P((vm_pager_t, vm_page_t *, int, boolean_t)); 6253342Sbostic 6353342Sbostic struct pagerops vnodepagerops = { 6453342Sbostic vnode_pager_init, 6553342Sbostic vnode_pager_alloc, 6653342Sbostic vnode_pager_dealloc, 6753342Sbostic vnode_pager_getpage, 6853342Sbostic vnode_pager_putpage, 69*65695Shibler vnode_pager_haspage, 70*65695Shibler vnode_pager_cluster 7153342Sbostic }; 7253342Sbostic 7353342Sbostic static void 7445749Smckusick vnode_pager_init() 7545749Smckusick { 7645749Smckusick #ifdef DEBUG 7745749Smckusick if (vpagerdebug & VDB_FOLLOW) 7845749Smckusick printf("vnode_pager_init()\n"); 7945749Smckusick #endif 8065231Smckusick TAILQ_INIT(&vnode_pager_list); 8145749Smckusick } 8245749Smckusick 8345749Smckusick /* 8445749Smckusick * Allocate (or lookup) pager for a vnode. 8545749Smckusick * Handle is a vnode pointer. 8645749Smckusick */ 8753342Sbostic static vm_pager_t 8864827Storek vnode_pager_alloc(handle, size, prot, foff) 8945749Smckusick caddr_t handle; 9045749Smckusick vm_size_t size; 9145749Smckusick vm_prot_t prot; 9264827Storek vm_offset_t foff; 9345749Smckusick { 9445749Smckusick register vm_pager_t pager; 9545749Smckusick register vn_pager_t vnp; 9645749Smckusick vm_object_t object; 9745749Smckusick struct vattr vattr; 9845749Smckusick struct vnode *vp; 9948042Smckusick struct proc *p = curproc; /* XXX */ 10045749Smckusick 10145749Smckusick #ifdef DEBUG 10245749Smckusick if (vpagerdebug & (VDB_FOLLOW|VDB_ALLOC)) 10345749Smckusick printf("vnode_pager_alloc(%x, %x, %x)\n", handle, size, prot); 10445749Smckusick #endif 10545749Smckusick /* 10645749Smckusick * Pageout to vnode, no can do yet. 10745749Smckusick */ 10845749Smckusick if (handle == NULL) 10948397Skarels return(NULL); 11045749Smckusick 11145749Smckusick /* 11245749Smckusick * Vnodes keep a pointer to any associated pager so no need to 11345749Smckusick * lookup with vm_pager_lookup. 11445749Smckusick */ 11545749Smckusick vp = (struct vnode *)handle; 11645749Smckusick pager = (vm_pager_t)vp->v_vmdata; 11748397Skarels if (pager == NULL) { 11845749Smckusick /* 11945749Smckusick * Allocate pager structures 12045749Smckusick */ 12145749Smckusick pager = (vm_pager_t)malloc(sizeof *pager, M_VMPAGER, M_WAITOK); 12248397Skarels if (pager == NULL) 12348397Skarels return(NULL); 12445749Smckusick vnp = (vn_pager_t)malloc(sizeof *vnp, M_VMPGDATA, M_WAITOK); 12548397Skarels if (vnp == NULL) { 12645749Smckusick free((caddr_t)pager, M_VMPAGER); 12748397Skarels return(NULL); 12845749Smckusick } 12945749Smckusick /* 13045749Smckusick * And an object of the appropriate size 13145749Smckusick */ 13248042Smckusick if (VOP_GETATTR(vp, &vattr, p->p_ucred, p) == 0) { 13345749Smckusick object = vm_object_allocate(round_page(vattr.va_size)); 13445749Smckusick vm_object_enter(object, pager); 13545749Smckusick vm_object_setpager(object, pager, 0, TRUE); 13645749Smckusick } else { 13745749Smckusick free((caddr_t)vnp, M_VMPGDATA); 13845749Smckusick free((caddr_t)pager, M_VMPAGER); 13948397Skarels return(NULL); 14045749Smckusick } 14145749Smckusick /* 14245749Smckusick * Hold a reference to the vnode and initialize pager data. 14345749Smckusick */ 14445749Smckusick VREF(vp); 14545749Smckusick vnp->vnp_flags = 0; 14645749Smckusick vnp->vnp_vp = vp; 14745749Smckusick vnp->vnp_size = vattr.va_size; 14865231Smckusick TAILQ_INSERT_TAIL(&vnode_pager_list, pager, pg_list); 14945749Smckusick pager->pg_handle = handle; 15045749Smckusick pager->pg_type = PG_VNODE; 151*65695Shibler pager->pg_flags = 0; 15245749Smckusick pager->pg_ops = &vnodepagerops; 15364858Shibler pager->pg_data = vnp; 15445749Smckusick vp->v_vmdata = (caddr_t)pager; 15545749Smckusick } else { 15645749Smckusick /* 15745749Smckusick * vm_object_lookup() will remove the object from the 15845749Smckusick * cache if found and also gain a reference to the object. 15945749Smckusick */ 16045749Smckusick object = vm_object_lookup(pager); 16147977Skarels #ifdef DEBUG 16245749Smckusick vnp = (vn_pager_t)pager->pg_data; 16347977Skarels #endif 16445749Smckusick } 16545749Smckusick #ifdef DEBUG 16645749Smckusick if (vpagerdebug & VDB_ALLOC) 16745749Smckusick printf("vnode_pager_setup: vp %x sz %x pager %x object %x\n", 16845749Smckusick vp, vnp->vnp_size, pager, object); 16945749Smckusick #endif 17045749Smckusick return(pager); 17145749Smckusick } 17245749Smckusick 17353342Sbostic static void 17445749Smckusick vnode_pager_dealloc(pager) 17545749Smckusick vm_pager_t pager; 17645749Smckusick { 17745749Smckusick register vn_pager_t vnp = (vn_pager_t)pager->pg_data; 17845749Smckusick register struct vnode *vp; 17948042Smckusick struct proc *p = curproc; /* XXX */ 18045749Smckusick 18145749Smckusick #ifdef DEBUG 18245749Smckusick if (vpagerdebug & VDB_FOLLOW) 18345749Smckusick printf("vnode_pager_dealloc(%x)\n", pager); 18445749Smckusick #endif 18545749Smckusick if (vp = vnp->vnp_vp) { 18645749Smckusick vp->v_vmdata = NULL; 18745749Smckusick vp->v_flag &= ~VTEXT; 18845749Smckusick #if 0 18945749Smckusick /* can hang if done at reboot on NFS FS */ 19048042Smckusick (void) VOP_FSYNC(vp, p->p_ucred, p); 19145749Smckusick #endif 19245749Smckusick vrele(vp); 19345749Smckusick } 19465231Smckusick TAILQ_REMOVE(&vnode_pager_list, pager, pg_list); 19545749Smckusick free((caddr_t)vnp, M_VMPGDATA); 19645749Smckusick free((caddr_t)pager, M_VMPAGER); 19745749Smckusick } 19845749Smckusick 19953342Sbostic static int 200*65695Shibler vnode_pager_getpage(pager, mlist, npages, sync) 20145749Smckusick vm_pager_t pager; 202*65695Shibler vm_page_t *mlist; 203*65695Shibler int npages; 20445749Smckusick boolean_t sync; 20545749Smckusick { 20645749Smckusick 20745749Smckusick #ifdef DEBUG 20845749Smckusick if (vpagerdebug & VDB_FOLLOW) 209*65695Shibler printf("vnode_pager_getpage(%x, %x, %x, %x)\n", 210*65695Shibler pager, mlist, npages, sync); 21145749Smckusick #endif 212*65695Shibler return(vnode_pager_io((vn_pager_t)pager->pg_data, 213*65695Shibler mlist, npages, sync, UIO_READ)); 21445749Smckusick } 21545749Smckusick 21653342Sbostic static boolean_t 217*65695Shibler vnode_pager_putpage(pager, mlist, npages, sync) 21845749Smckusick vm_pager_t pager; 219*65695Shibler vm_page_t *mlist; 220*65695Shibler int npages; 22145749Smckusick boolean_t sync; 22245749Smckusick { 22345749Smckusick int err; 22445749Smckusick 22545749Smckusick #ifdef DEBUG 22645749Smckusick if (vpagerdebug & VDB_FOLLOW) 227*65695Shibler printf("vnode_pager_putpage(%x, %x, %x, %x)\n", 228*65695Shibler pager, mlist, npages, sync); 22945749Smckusick #endif 23048397Skarels if (pager == NULL) 23154818Storek return (FALSE); /* ??? */ 232*65695Shibler err = vnode_pager_io((vn_pager_t)pager->pg_data, 233*65695Shibler mlist, npages, sync, UIO_WRITE); 234*65695Shibler /* 235*65695Shibler * If the operation was successful, mark the pages clean. 236*65695Shibler */ 23745749Smckusick if (err == VM_PAGER_OK) { 238*65695Shibler while (npages--) { 239*65695Shibler (*mlist)->flags |= PG_CLEAN; 240*65695Shibler pmap_clear_modify(VM_PAGE_TO_PHYS(*mlist)); 241*65695Shibler mlist++; 242*65695Shibler } 24345749Smckusick } 24445749Smckusick return(err); 24545749Smckusick } 24645749Smckusick 24753342Sbostic static boolean_t 24845749Smckusick vnode_pager_haspage(pager, offset) 24945749Smckusick vm_pager_t pager; 25045749Smckusick vm_offset_t offset; 25145749Smckusick { 25245749Smckusick register vn_pager_t vnp = (vn_pager_t)pager->pg_data; 25345749Smckusick daddr_t bn; 25445749Smckusick int err; 25545749Smckusick 25645749Smckusick #ifdef DEBUG 25745749Smckusick if (vpagerdebug & VDB_FOLLOW) 25845749Smckusick printf("vnode_pager_haspage(%x, %x)\n", pager, offset); 25945749Smckusick #endif 26045749Smckusick 26145749Smckusick /* 26245749Smckusick * Offset beyond end of file, do not have the page 26345749Smckusick */ 26445749Smckusick if (offset >= vnp->vnp_size) { 26545749Smckusick #ifdef DEBUG 26645749Smckusick if (vpagerdebug & (VDB_FAIL|VDB_SIZE)) 26745749Smckusick printf("vnode_pager_haspage: pg %x, off %x, size %x\n", 26845749Smckusick pager, offset, vnp->vnp_size); 26945749Smckusick #endif 27045749Smckusick return(FALSE); 27145749Smckusick } 27245749Smckusick 27345749Smckusick /* 27445749Smckusick * Read the index to find the disk block to read 27545749Smckusick * from. If there is no block, report that we don't 27645749Smckusick * have this data. 27745749Smckusick * 27845749Smckusick * Assumes that the vnode has whole page or nothing. 27945749Smckusick */ 280*65695Shibler VOP_LOCK(vnp->vnp_vp); 28145749Smckusick err = VOP_BMAP(vnp->vnp_vp, 28251941Smckusick offset / vnp->vnp_vp->v_mount->mnt_stat.f_iosize, 28356457Smargo (struct vnode **)0, &bn, NULL); 284*65695Shibler VOP_UNLOCK(vnp->vnp_vp); 28545749Smckusick if (err) { 28645749Smckusick #ifdef DEBUG 28745749Smckusick if (vpagerdebug & VDB_FAIL) 28845749Smckusick printf("vnode_pager_haspage: BMAP err %d, pg %x, off %x\n", 28945749Smckusick err, pager, offset); 29045749Smckusick #endif 29145749Smckusick return(TRUE); 29245749Smckusick } 29345749Smckusick return((long)bn < 0 ? FALSE : TRUE); 29445749Smckusick } 29545749Smckusick 296*65695Shibler static void 297*65695Shibler vnode_pager_cluster(pager, offset, loffset, hoffset) 298*65695Shibler vm_pager_t pager; 299*65695Shibler vm_offset_t offset; 300*65695Shibler vm_offset_t *loffset; 301*65695Shibler vm_offset_t *hoffset; 302*65695Shibler { 303*65695Shibler vn_pager_t vnp = (vn_pager_t)pager->pg_data; 304*65695Shibler vm_offset_t loff, hoff; 305*65695Shibler 306*65695Shibler #ifdef DEBUG 307*65695Shibler if (vpagerdebug & VDB_FOLLOW) 308*65695Shibler printf("vnode_pager_cluster(%x, %x) ", pager, offset); 309*65695Shibler #endif 310*65695Shibler loff = offset; 311*65695Shibler if (loff >= vnp->vnp_size) 312*65695Shibler panic("vnode_pager_cluster: bad offset"); 313*65695Shibler /* 314*65695Shibler * XXX could use VOP_BMAP to get maxcontig value 315*65695Shibler */ 316*65695Shibler hoff = loff + MAXBSIZE; 317*65695Shibler if (hoff > round_page(vnp->vnp_size)) 318*65695Shibler hoff = round_page(vnp->vnp_size); 319*65695Shibler 320*65695Shibler *loffset = loff; 321*65695Shibler *hoffset = hoff; 322*65695Shibler #ifdef DEBUG 323*65695Shibler if (vpagerdebug & VDB_FOLLOW) 324*65695Shibler printf("returns [%x-%x]\n", loff, hoff); 325*65695Shibler #endif 326*65695Shibler } 327*65695Shibler 32845749Smckusick /* 32945749Smckusick * (XXX) 33045749Smckusick * Lets the VM system know about a change in size for a file. 33145749Smckusick * If this vnode is mapped into some address space (i.e. we have a pager 33245749Smckusick * for it) we adjust our own internal size and flush any cached pages in 33345749Smckusick * the associated object that are affected by the size change. 33445749Smckusick * 33545749Smckusick * Note: this routine may be invoked as a result of a pager put 33645749Smckusick * operation (possibly at object termination time), so we must be careful. 33745749Smckusick */ 33853480Smckusick void 33945749Smckusick vnode_pager_setsize(vp, nsize) 34045749Smckusick struct vnode *vp; 34145749Smckusick u_long nsize; 34245749Smckusick { 34345749Smckusick register vn_pager_t vnp; 34445749Smckusick register vm_object_t object; 34545749Smckusick vm_pager_t pager; 34645749Smckusick 34745749Smckusick /* 34845749Smckusick * Not a mapped vnode 34945749Smckusick */ 35045749Smckusick if (vp == NULL || vp->v_type != VREG || vp->v_vmdata == NULL) 35145749Smckusick return; 35245749Smckusick /* 35345749Smckusick * Hasn't changed size 35445749Smckusick */ 35545749Smckusick pager = (vm_pager_t)vp->v_vmdata; 35645749Smckusick vnp = (vn_pager_t)pager->pg_data; 35745749Smckusick if (nsize == vnp->vnp_size) 35845749Smckusick return; 35945749Smckusick /* 36045749Smckusick * No object. 36145749Smckusick * This can happen during object termination since 36245749Smckusick * vm_object_page_clean is called after the object 36345749Smckusick * has been removed from the hash table, and clean 36445749Smckusick * may cause vnode write operations which can wind 36545749Smckusick * up back here. 36645749Smckusick */ 36745749Smckusick object = vm_object_lookup(pager); 36848397Skarels if (object == NULL) 36945749Smckusick return; 37045749Smckusick 37145749Smckusick #ifdef DEBUG 37245749Smckusick if (vpagerdebug & (VDB_FOLLOW|VDB_SIZE)) 37345749Smckusick printf("vnode_pager_setsize: vp %x obj %x osz %d nsz %d\n", 37445749Smckusick vp, object, vnp->vnp_size, nsize); 37545749Smckusick #endif 37645749Smckusick /* 37745749Smckusick * File has shrunk. 37845749Smckusick * Toss any cached pages beyond the new EOF. 37945749Smckusick */ 38045749Smckusick if (nsize < vnp->vnp_size) { 38145749Smckusick vm_object_lock(object); 38245749Smckusick vm_object_page_remove(object, 38345749Smckusick (vm_offset_t)nsize, vnp->vnp_size); 38445749Smckusick vm_object_unlock(object); 38545749Smckusick } 38645749Smckusick vnp->vnp_size = (vm_offset_t)nsize; 38745749Smckusick vm_object_deallocate(object); 38845749Smckusick } 38945749Smckusick 39053480Smckusick void 39145749Smckusick vnode_pager_umount(mp) 39245749Smckusick register struct mount *mp; 39345749Smckusick { 39445749Smckusick register vm_pager_t pager, npager; 39545749Smckusick struct vnode *vp; 39645749Smckusick 39765231Smckusick for (pager = vnode_pager_list.tqh_first; pager != NULL; pager = npager){ 39845749Smckusick /* 39945749Smckusick * Save the next pointer now since uncaching may 40045749Smckusick * terminate the object and render pager invalid 40145749Smckusick */ 40265231Smckusick npager = pager->pg_list.tqe_next; 40345749Smckusick vp = ((vn_pager_t)pager->pg_data)->vnp_vp; 404*65695Shibler if (mp == (struct mount *)0 || vp->v_mount == mp) { 405*65695Shibler VOP_LOCK(vp); 40645749Smckusick (void) vnode_pager_uncache(vp); 407*65695Shibler VOP_UNLOCK(vp); 408*65695Shibler } 40945749Smckusick } 41045749Smckusick } 41145749Smckusick 41245749Smckusick /* 41345749Smckusick * Remove vnode associated object from the object cache. 41445749Smckusick * 415*65695Shibler * XXX unlock the vnode if it is currently locked. 416*65695Shibler * We must do this since uncaching the object may result in its 417*65695Shibler * destruction which may initiate paging activity which may necessitate 418*65695Shibler * re-locking the vnode. 41945749Smckusick */ 42053480Smckusick boolean_t 42145749Smckusick vnode_pager_uncache(vp) 42245749Smckusick register struct vnode *vp; 42345749Smckusick { 42445749Smckusick register vm_object_t object; 425*65695Shibler boolean_t uncached; 42645749Smckusick vm_pager_t pager; 42745749Smckusick 42845749Smckusick /* 42945749Smckusick * Not a mapped vnode 43045749Smckusick */ 43145749Smckusick pager = (vm_pager_t)vp->v_vmdata; 43248397Skarels if (pager == NULL) 43345749Smckusick return (TRUE); 434*65695Shibler #ifdef DEBUG 435*65695Shibler if (!VOP_ISLOCKED(vp)) { 436*65695Shibler extern int (**nfsv2_vnodeop_p)(); 437*65695Shibler 438*65695Shibler if (vp->v_op != nfsv2_vnodeop_p) 439*65695Shibler panic("vnode_pager_uncache: vnode not locked!"); 440*65695Shibler } 441*65695Shibler #endif 44245749Smckusick /* 44345749Smckusick * Must use vm_object_lookup() as it actually removes 44445749Smckusick * the object from the cache list. 44545749Smckusick */ 44645749Smckusick object = vm_object_lookup(pager); 44745749Smckusick if (object) { 44845749Smckusick uncached = (object->ref_count <= 1); 449*65695Shibler VOP_UNLOCK(vp); 45045749Smckusick pager_cache(object, FALSE); 451*65695Shibler VOP_LOCK(vp); 45245749Smckusick } else 45345749Smckusick uncached = TRUE; 45445749Smckusick return(uncached); 45545749Smckusick } 45645749Smckusick 45753342Sbostic static int 458*65695Shibler vnode_pager_io(vnp, mlist, npages, sync, rw) 45945749Smckusick register vn_pager_t vnp; 460*65695Shibler vm_page_t *mlist; 461*65695Shibler int npages; 462*65695Shibler boolean_t sync; 46345749Smckusick enum uio_rw rw; 46445749Smckusick { 46545749Smckusick struct uio auio; 46645749Smckusick struct iovec aiov; 46745749Smckusick vm_offset_t kva, foff; 46845749Smckusick int error, size; 46948042Smckusick struct proc *p = curproc; /* XXX */ 47045749Smckusick 471*65695Shibler /* XXX */ 472*65695Shibler vm_page_t m; 473*65695Shibler if (npages != 1) 474*65695Shibler panic("vnode_pager_io: cannot handle multiple pages"); 475*65695Shibler m = *mlist; 476*65695Shibler /* XXX */ 477*65695Shibler 47845749Smckusick #ifdef DEBUG 47945749Smckusick if (vpagerdebug & VDB_FOLLOW) 48045749Smckusick printf("vnode_pager_io(%x, %x, %c): vnode %x\n", 48145749Smckusick vnp, m, rw == UIO_READ ? 'R' : 'W', vnp->vnp_vp); 48245749Smckusick #endif 48345749Smckusick foff = m->offset + m->object->paging_offset; 48445749Smckusick /* 48545749Smckusick * Return failure if beyond current EOF 48645749Smckusick */ 48745749Smckusick if (foff >= vnp->vnp_size) { 48845749Smckusick #ifdef DEBUG 48945749Smckusick if (vpagerdebug & VDB_SIZE) 49045749Smckusick printf("vnode_pager_io: vp %x, off %d size %d\n", 49145749Smckusick vnp->vnp_vp, foff, vnp->vnp_size); 49245749Smckusick #endif 49345749Smckusick return(VM_PAGER_BAD); 49445749Smckusick } 49545749Smckusick if (foff + PAGE_SIZE > vnp->vnp_size) 49645749Smckusick size = vnp->vnp_size - foff; 49745749Smckusick else 49845749Smckusick size = PAGE_SIZE; 49945749Smckusick /* 50045749Smckusick * Allocate a kernel virtual address and initialize so that 50145749Smckusick * we can use VOP_READ/WRITE routines. 50245749Smckusick */ 503*65695Shibler kva = vm_pager_map_pages(mlist, npages, sync); 504*65695Shibler if (kva == NULL) 505*65695Shibler return(VM_PAGER_AGAIN); 50645749Smckusick aiov.iov_base = (caddr_t)kva; 50745749Smckusick aiov.iov_len = size; 50845749Smckusick auio.uio_iov = &aiov; 50945749Smckusick auio.uio_iovcnt = 1; 51045749Smckusick auio.uio_offset = foff; 51145749Smckusick auio.uio_segflg = UIO_SYSSPACE; 51245749Smckusick auio.uio_rw = rw; 51345749Smckusick auio.uio_resid = size; 51448042Smckusick auio.uio_procp = (struct proc *)0; 51545749Smckusick #ifdef DEBUG 51645749Smckusick if (vpagerdebug & VDB_IO) 51745749Smckusick printf("vnode_pager_io: vp %x kva %x foff %x size %x", 51845749Smckusick vnp->vnp_vp, kva, foff, size); 51945749Smckusick #endif 520*65695Shibler VOP_LOCK(vnp->vnp_vp); 52145749Smckusick if (rw == UIO_READ) 52248042Smckusick error = VOP_READ(vnp->vnp_vp, &auio, 0, p->p_ucred); 52345749Smckusick else 52448042Smckusick error = VOP_WRITE(vnp->vnp_vp, &auio, 0, p->p_ucred); 525*65695Shibler VOP_UNLOCK(vnp->vnp_vp); 52645749Smckusick #ifdef DEBUG 52745749Smckusick if (vpagerdebug & VDB_IO) { 52845749Smckusick if (error || auio.uio_resid) 52945749Smckusick printf(" returns error %x, resid %x", 53045749Smckusick error, auio.uio_resid); 53145749Smckusick printf("\n"); 53245749Smckusick } 53345749Smckusick #endif 53445749Smckusick if (!error) { 53545749Smckusick register int count = size - auio.uio_resid; 53645749Smckusick 53745749Smckusick if (count == 0) 53845749Smckusick error = EINVAL; 53945749Smckusick else if (count != PAGE_SIZE && rw == UIO_READ) 54053342Sbostic bzero((void *)(kva + count), PAGE_SIZE - count); 54145749Smckusick } 542*65695Shibler vm_pager_unmap_pages(kva, npages); 54356321Shibler return (error ? VM_PAGER_ERROR : VM_PAGER_OK); 54445749Smckusick } 545