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*66075Shibler * @(#)vnode_pager.c 8.7 (Berkeley) 02/13/94 1345749Smckusick */ 1445749Smckusick 1545749Smckusick * Page to/from files (vnodes). 1645749Smckusick * 1745749Smckusick * TODO: 1845749Smckusick * pageouts 1947977Skarels * fix credential use (uses current process credentials now) 2045749Smckusick */ 2145749Smckusick 2253342Sbostic #include <sys/param.h> 2353342Sbostic #include <sys/systm.h> 2453342Sbostic #include <sys/proc.h> 2553342Sbostic #include <sys/malloc.h> 2653342Sbostic #include <sys/vnode.h> 2753342Sbostic #include <sys/uio.h> 2853342Sbostic #include <sys/mount.h> 2947977Skarels 3053342Sbostic #include <vm/vm.h> 3153342Sbostic #include <vm/vm_page.h> 3253342Sbostic #include <vm/vnode_pager.h> 3345749Smckusick 3465231Smckusick struct pagerlst vnode_pager_list; /* list of managed vnodes */ 3545749Smckusick 3645749Smckusick #ifdef DEBUG 3745749Smckusick int vpagerdebug = 0x00; 3845749Smckusick #define VDB_FOLLOW 0x01 3945749Smckusick #define VDB_INIT 0x02 4045749Smckusick #define VDB_IO 0x04 4145749Smckusick #define VDB_FAIL 0x08 4245749Smckusick #define VDB_ALLOC 0x10 4345749Smckusick #define VDB_SIZE 0x20 4445749Smckusick #endif 4545749Smckusick 4664827Storek static vm_pager_t vnode_pager_alloc 4764827Storek __P((caddr_t, vm_size_t, vm_prot_t, vm_offset_t)); 4865695Shibler static void vnode_pager_cluster 4965695Shibler __P((vm_pager_t, vm_offset_t, 5065695Shibler vm_offset_t *, vm_offset_t *)); 5153342Sbostic static void vnode_pager_dealloc __P((vm_pager_t)); 5253342Sbostic static int vnode_pager_getpage 5365695Shibler __P((vm_pager_t, vm_page_t *, int, boolean_t)); 5453342Sbostic static boolean_t vnode_pager_haspage __P((vm_pager_t, vm_offset_t)); 5553342Sbostic static void vnode_pager_init __P((void)); 5653342Sbostic static int vnode_pager_io 5765695Shibler __P((vn_pager_t, vm_page_t *, int, 5865695Shibler boolean_t, enum uio_rw)); 5953342Sbostic static boolean_t vnode_pager_putpage 6065695Shibler __P((vm_pager_t, vm_page_t *, int, boolean_t)); 6153342Sbostic 6253342Sbostic struct pagerops vnodepagerops = { 6353342Sbostic vnode_pager_init, 6453342Sbostic vnode_pager_alloc, 6553342Sbostic vnode_pager_dealloc, 6653342Sbostic vnode_pager_getpage, 6753342Sbostic vnode_pager_putpage, 6865695Shibler vnode_pager_haspage, 6965695Shibler vnode_pager_cluster 7053342Sbostic }; 7153342Sbostic 7253342Sbostic static void 7345749Smckusick vnode_pager_init() 7445749Smckusick { 7545749Smckusick #ifdef DEBUG 7645749Smckusick if (vpagerdebug & VDB_FOLLOW) 7745749Smckusick printf("vnode_pager_init()\n"); 7845749Smckusick #endif 7965231Smckusick TAILQ_INIT(&vnode_pager_list); 8045749Smckusick } 8145749Smckusick 8245749Smckusick /* 8345749Smckusick * Allocate (or lookup) pager for a vnode. 8445749Smckusick * Handle is a vnode pointer. 8545749Smckusick */ 8653342Sbostic static vm_pager_t 8764827Storek vnode_pager_alloc(handle, size, prot, foff) 8845749Smckusick caddr_t handle; 8945749Smckusick vm_size_t size; 9045749Smckusick vm_prot_t prot; 9164827Storek vm_offset_t foff; 9245749Smckusick { 9345749Smckusick register vm_pager_t pager; 9445749Smckusick register vn_pager_t vnp; 9545749Smckusick vm_object_t object; 9645749Smckusick struct vattr vattr; 9745749Smckusick struct vnode *vp; 9848042Smckusick struct proc *p = curproc; /* XXX */ 9945749Smckusick 10045749Smckusick #ifdef DEBUG 10145749Smckusick if (vpagerdebug & (VDB_FOLLOW|VDB_ALLOC)) 10245749Smckusick printf("vnode_pager_alloc(%x, %x, %x)\n", handle, size, prot); 10345749Smckusick #endif 10445749Smckusick /* 10545749Smckusick * Pageout to vnode, no can do yet. 10645749Smckusick */ 10745749Smckusick if (handle == NULL) 10848397Skarels return(NULL); 10945749Smckusick 11045749Smckusick /* 11145749Smckusick * Vnodes keep a pointer to any associated pager so no need to 11245749Smckusick * lookup with vm_pager_lookup. 11345749Smckusick */ 11445749Smckusick vp = (struct vnode *)handle; 11545749Smckusick pager = (vm_pager_t)vp->v_vmdata; 11648397Skarels if (pager == NULL) { 11745749Smckusick /* 11845749Smckusick * Allocate pager structures 11945749Smckusick */ 12045749Smckusick pager = (vm_pager_t)malloc(sizeof *pager, M_VMPAGER, M_WAITOK); 12148397Skarels if (pager == NULL) 12248397Skarels return(NULL); 12345749Smckusick vnp = (vn_pager_t)malloc(sizeof *vnp, M_VMPGDATA, M_WAITOK); 12448397Skarels if (vnp == NULL) { 12545749Smckusick free((caddr_t)pager, M_VMPAGER); 12648397Skarels return(NULL); 12745749Smckusick } 12845749Smckusick /* 12945749Smckusick * And an object of the appropriate size 13045749Smckusick */ 13148042Smckusick if (VOP_GETATTR(vp, &vattr, p->p_ucred, p) == 0) { 13245749Smckusick object = vm_object_allocate(round_page(vattr.va_size)); 13345749Smckusick vm_object_enter(object, pager); 13445749Smckusick vm_object_setpager(object, pager, 0, TRUE); 13545749Smckusick } else { 13645749Smckusick free((caddr_t)vnp, M_VMPGDATA); 13745749Smckusick free((caddr_t)pager, M_VMPAGER); 13848397Skarels return(NULL); 13945749Smckusick } 14045749Smckusick /* 14145749Smckusick * Hold a reference to the vnode and initialize pager data. 14245749Smckusick */ 14345749Smckusick VREF(vp); 14445749Smckusick vnp->vnp_flags = 0; 14545749Smckusick vnp->vnp_vp = vp; 14645749Smckusick vnp->vnp_size = vattr.va_size; 14765231Smckusick TAILQ_INSERT_TAIL(&vnode_pager_list, pager, pg_list); 14845749Smckusick pager->pg_handle = handle; 14945749Smckusick pager->pg_type = PG_VNODE; 15065695Shibler pager->pg_flags = 0; 15145749Smckusick pager->pg_ops = &vnodepagerops; 15264858Shibler pager->pg_data = vnp; 15345749Smckusick vp->v_vmdata = (caddr_t)pager; 15445749Smckusick } else { 15545749Smckusick /* 15645749Smckusick * vm_object_lookup() will remove the object from the 15745749Smckusick * cache if found and also gain a reference to the object. 15845749Smckusick */ 15945749Smckusick object = vm_object_lookup(pager); 16047977Skarels #ifdef DEBUG 16145749Smckusick vnp = (vn_pager_t)pager->pg_data; 16247977Skarels #endif 16345749Smckusick } 16445749Smckusick #ifdef DEBUG 16545749Smckusick if (vpagerdebug & VDB_ALLOC) 16645749Smckusick printf("vnode_pager_setup: vp %x sz %x pager %x object %x\n", 16745749Smckusick vp, vnp->vnp_size, pager, object); 16845749Smckusick #endif 16945749Smckusick return(pager); 17045749Smckusick } 17145749Smckusick 17253342Sbostic static void 17345749Smckusick vnode_pager_dealloc(pager) 17445749Smckusick vm_pager_t pager; 17545749Smckusick { 17645749Smckusick register vn_pager_t vnp = (vn_pager_t)pager->pg_data; 17745749Smckusick register struct vnode *vp; 17865722Sbostic #ifdef NOTDEF 17948042Smckusick struct proc *p = curproc; /* XXX */ 18065722Sbostic #endif 18145749Smckusick 18245749Smckusick #ifdef DEBUG 18345749Smckusick if (vpagerdebug & VDB_FOLLOW) 18445749Smckusick printf("vnode_pager_dealloc(%x)\n", pager); 18545749Smckusick #endif 18645749Smckusick if (vp = vnp->vnp_vp) { 18745749Smckusick vp->v_vmdata = NULL; 18845749Smckusick vp->v_flag &= ~VTEXT; 18965722Sbostic #if NOTDEF 19045749Smckusick /* can hang if done at reboot on NFS FS */ 19148042Smckusick (void) VOP_FSYNC(vp, p->p_ucred, p); 19245749Smckusick #endif 19345749Smckusick vrele(vp); 19445749Smckusick } 19565231Smckusick TAILQ_REMOVE(&vnode_pager_list, pager, pg_list); 19645749Smckusick free((caddr_t)vnp, M_VMPGDATA); 19745749Smckusick free((caddr_t)pager, M_VMPAGER); 19845749Smckusick } 19945749Smckusick 20053342Sbostic static int 20165695Shibler vnode_pager_getpage(pager, mlist, npages, sync) 20245749Smckusick vm_pager_t pager; 20365695Shibler vm_page_t *mlist; 20465695Shibler int npages; 20545749Smckusick boolean_t sync; 20645749Smckusick { 20745749Smckusick 20845749Smckusick #ifdef DEBUG 20945749Smckusick if (vpagerdebug & VDB_FOLLOW) 21065695Shibler printf("vnode_pager_getpage(%x, %x, %x, %x)\n", 21165695Shibler pager, mlist, npages, sync); 21245749Smckusick #endif 21365695Shibler return(vnode_pager_io((vn_pager_t)pager->pg_data, 21465695Shibler mlist, npages, sync, UIO_READ)); 21545749Smckusick } 21645749Smckusick 21753342Sbostic static boolean_t 21865695Shibler vnode_pager_putpage(pager, mlist, npages, sync) 21945749Smckusick vm_pager_t pager; 22065695Shibler vm_page_t *mlist; 22165695Shibler int npages; 22245749Smckusick boolean_t sync; 22345749Smckusick { 22445749Smckusick int err; 22545749Smckusick 22645749Smckusick #ifdef DEBUG 22745749Smckusick if (vpagerdebug & VDB_FOLLOW) 22865695Shibler printf("vnode_pager_putpage(%x, %x, %x, %x)\n", 22965695Shibler pager, mlist, npages, sync); 23045749Smckusick #endif 23148397Skarels if (pager == NULL) 23254818Storek return (FALSE); /* ??? */ 23365695Shibler err = vnode_pager_io((vn_pager_t)pager->pg_data, 23465695Shibler mlist, npages, sync, UIO_WRITE); 23565695Shibler /* 23665695Shibler * If the operation was successful, mark the pages clean. 23765695Shibler */ 23845749Smckusick if (err == VM_PAGER_OK) { 23965695Shibler while (npages--) { 24065695Shibler (*mlist)->flags |= PG_CLEAN; 24165695Shibler pmap_clear_modify(VM_PAGE_TO_PHYS(*mlist)); 24265695Shibler mlist++; 24365695Shibler } 24445749Smckusick } 24545749Smckusick return(err); 24645749Smckusick } 24745749Smckusick 24853342Sbostic static boolean_t 24945749Smckusick vnode_pager_haspage(pager, offset) 25045749Smckusick vm_pager_t pager; 25145749Smckusick vm_offset_t offset; 25245749Smckusick { 25345749Smckusick register vn_pager_t vnp = (vn_pager_t)pager->pg_data; 25445749Smckusick daddr_t bn; 25545749Smckusick int err; 25645749Smckusick 25745749Smckusick #ifdef DEBUG 25845749Smckusick if (vpagerdebug & VDB_FOLLOW) 25945749Smckusick printf("vnode_pager_haspage(%x, %x)\n", pager, offset); 26045749Smckusick #endif 26145749Smckusick 26245749Smckusick /* 26345749Smckusick * Offset beyond end of file, do not have the page 264*66075Shibler * Lock the vnode first to make sure we have the most recent 265*66075Shibler * version of the size. 26645749Smckusick */ 267*66075Shibler VOP_LOCK(vnp->vnp_vp); 26845749Smckusick if (offset >= vnp->vnp_size) { 269*66075Shibler VOP_UNLOCK(vnp->vnp_vp); 27045749Smckusick #ifdef DEBUG 27145749Smckusick if (vpagerdebug & (VDB_FAIL|VDB_SIZE)) 27245749Smckusick printf("vnode_pager_haspage: pg %x, off %x, size %x\n", 27345749Smckusick pager, offset, vnp->vnp_size); 27445749Smckusick #endif 27545749Smckusick return(FALSE); 27645749Smckusick } 27745749Smckusick 27845749Smckusick /* 27945749Smckusick * Read the index to find the disk block to read 28045749Smckusick * from. If there is no block, report that we don't 28145749Smckusick * have this data. 28245749Smckusick * 28345749Smckusick * Assumes that the vnode has whole page or nothing. 28445749Smckusick */ 28545749Smckusick err = VOP_BMAP(vnp->vnp_vp, 28651941Smckusick offset / vnp->vnp_vp->v_mount->mnt_stat.f_iosize, 28756457Smargo (struct vnode **)0, &bn, NULL); 28865695Shibler VOP_UNLOCK(vnp->vnp_vp); 28945749Smckusick if (err) { 29045749Smckusick #ifdef DEBUG 29145749Smckusick if (vpagerdebug & VDB_FAIL) 29245749Smckusick printf("vnode_pager_haspage: BMAP err %d, pg %x, off %x\n", 29345749Smckusick err, pager, offset); 29445749Smckusick #endif 29545749Smckusick return(TRUE); 29645749Smckusick } 29745749Smckusick return((long)bn < 0 ? FALSE : TRUE); 29845749Smckusick } 29945749Smckusick 30065695Shibler static void 30165695Shibler vnode_pager_cluster(pager, offset, loffset, hoffset) 30265695Shibler vm_pager_t pager; 30365695Shibler vm_offset_t offset; 30465695Shibler vm_offset_t *loffset; 30565695Shibler vm_offset_t *hoffset; 30665695Shibler { 30765695Shibler vn_pager_t vnp = (vn_pager_t)pager->pg_data; 30865695Shibler vm_offset_t loff, hoff; 30965695Shibler 31065695Shibler #ifdef DEBUG 31165695Shibler if (vpagerdebug & VDB_FOLLOW) 31265695Shibler printf("vnode_pager_cluster(%x, %x) ", pager, offset); 31365695Shibler #endif 31465695Shibler loff = offset; 31565695Shibler if (loff >= vnp->vnp_size) 31665695Shibler panic("vnode_pager_cluster: bad offset"); 31765695Shibler /* 31865695Shibler * XXX could use VOP_BMAP to get maxcontig value 31965695Shibler */ 32065695Shibler hoff = loff + MAXBSIZE; 32165695Shibler if (hoff > round_page(vnp->vnp_size)) 32265695Shibler hoff = round_page(vnp->vnp_size); 32365695Shibler 32465695Shibler *loffset = loff; 32565695Shibler *hoffset = hoff; 32665695Shibler #ifdef DEBUG 32765695Shibler if (vpagerdebug & VDB_FOLLOW) 32865695Shibler printf("returns [%x-%x]\n", loff, hoff); 32965695Shibler #endif 33065695Shibler } 33165695Shibler 33245749Smckusick /* 33345749Smckusick * (XXX) 33445749Smckusick * Lets the VM system know about a change in size for a file. 33545749Smckusick * If this vnode is mapped into some address space (i.e. we have a pager 33645749Smckusick * for it) we adjust our own internal size and flush any cached pages in 33745749Smckusick * the associated object that are affected by the size change. 33845749Smckusick * 33945749Smckusick * Note: this routine may be invoked as a result of a pager put 34045749Smckusick * operation (possibly at object termination time), so we must be careful. 34145749Smckusick */ 34253480Smckusick void 34345749Smckusick vnode_pager_setsize(vp, nsize) 34445749Smckusick struct vnode *vp; 34545749Smckusick u_long nsize; 34645749Smckusick { 34745749Smckusick register vn_pager_t vnp; 34845749Smckusick register vm_object_t object; 34945749Smckusick vm_pager_t pager; 35045749Smckusick 35145749Smckusick /* 35245749Smckusick * Not a mapped vnode 35345749Smckusick */ 35445749Smckusick if (vp == NULL || vp->v_type != VREG || vp->v_vmdata == NULL) 35545749Smckusick return; 35645749Smckusick /* 35745749Smckusick * Hasn't changed size 35845749Smckusick */ 35945749Smckusick pager = (vm_pager_t)vp->v_vmdata; 36045749Smckusick vnp = (vn_pager_t)pager->pg_data; 36145749Smckusick if (nsize == vnp->vnp_size) 36245749Smckusick return; 36345749Smckusick /* 36445749Smckusick * No object. 36545749Smckusick * This can happen during object termination since 36645749Smckusick * vm_object_page_clean is called after the object 36745749Smckusick * has been removed from the hash table, and clean 36845749Smckusick * may cause vnode write operations which can wind 36945749Smckusick * up back here. 37045749Smckusick */ 37145749Smckusick object = vm_object_lookup(pager); 37248397Skarels if (object == NULL) 37345749Smckusick return; 37445749Smckusick 37545749Smckusick #ifdef DEBUG 37645749Smckusick if (vpagerdebug & (VDB_FOLLOW|VDB_SIZE)) 37745749Smckusick printf("vnode_pager_setsize: vp %x obj %x osz %d nsz %d\n", 37845749Smckusick vp, object, vnp->vnp_size, nsize); 37945749Smckusick #endif 38045749Smckusick /* 38145749Smckusick * File has shrunk. 38245749Smckusick * Toss any cached pages beyond the new EOF. 38345749Smckusick */ 38445749Smckusick if (nsize < vnp->vnp_size) { 38545749Smckusick vm_object_lock(object); 38645749Smckusick vm_object_page_remove(object, 38745749Smckusick (vm_offset_t)nsize, vnp->vnp_size); 38845749Smckusick vm_object_unlock(object); 38945749Smckusick } 39045749Smckusick vnp->vnp_size = (vm_offset_t)nsize; 39145749Smckusick vm_object_deallocate(object); 39245749Smckusick } 39345749Smckusick 39453480Smckusick void 39545749Smckusick vnode_pager_umount(mp) 39645749Smckusick register struct mount *mp; 39745749Smckusick { 39845749Smckusick register vm_pager_t pager, npager; 39945749Smckusick struct vnode *vp; 40045749Smckusick 40165231Smckusick for (pager = vnode_pager_list.tqh_first; pager != NULL; pager = npager){ 40245749Smckusick /* 40345749Smckusick * Save the next pointer now since uncaching may 40445749Smckusick * terminate the object and render pager invalid 40545749Smckusick */ 40665231Smckusick npager = pager->pg_list.tqe_next; 40745749Smckusick vp = ((vn_pager_t)pager->pg_data)->vnp_vp; 40865695Shibler if (mp == (struct mount *)0 || vp->v_mount == mp) { 40965695Shibler VOP_LOCK(vp); 41045749Smckusick (void) vnode_pager_uncache(vp); 41165695Shibler VOP_UNLOCK(vp); 41265695Shibler } 41345749Smckusick } 41445749Smckusick } 41545749Smckusick 41645749Smckusick /* 41745749Smckusick * Remove vnode associated object from the object cache. 41845749Smckusick * 41965695Shibler * XXX unlock the vnode if it is currently locked. 42065695Shibler * We must do this since uncaching the object may result in its 42165695Shibler * destruction which may initiate paging activity which may necessitate 42265695Shibler * re-locking the vnode. 42345749Smckusick */ 42453480Smckusick boolean_t 42545749Smckusick vnode_pager_uncache(vp) 42645749Smckusick register struct vnode *vp; 42745749Smckusick { 42845749Smckusick register vm_object_t object; 42965695Shibler boolean_t uncached; 43045749Smckusick vm_pager_t pager; 43145749Smckusick 43245749Smckusick /* 43345749Smckusick * Not a mapped vnode 43445749Smckusick */ 43545749Smckusick pager = (vm_pager_t)vp->v_vmdata; 43648397Skarels if (pager == NULL) 43745749Smckusick return (TRUE); 43865695Shibler #ifdef DEBUG 43965695Shibler if (!VOP_ISLOCKED(vp)) { 44065695Shibler extern int (**nfsv2_vnodeop_p)(); 44165695Shibler 44265695Shibler if (vp->v_op != nfsv2_vnodeop_p) 44365695Shibler panic("vnode_pager_uncache: vnode not locked!"); 44465695Shibler } 44565695Shibler #endif 44645749Smckusick /* 44745749Smckusick * Must use vm_object_lookup() as it actually removes 44845749Smckusick * the object from the cache list. 44945749Smckusick */ 45045749Smckusick object = vm_object_lookup(pager); 45145749Smckusick if (object) { 45245749Smckusick uncached = (object->ref_count <= 1); 45365695Shibler VOP_UNLOCK(vp); 45445749Smckusick pager_cache(object, FALSE); 45565695Shibler VOP_LOCK(vp); 45645749Smckusick } else 45745749Smckusick uncached = TRUE; 45845749Smckusick return(uncached); 45945749Smckusick } 46045749Smckusick 46153342Sbostic static int 46265695Shibler vnode_pager_io(vnp, mlist, npages, sync, rw) 46345749Smckusick register vn_pager_t vnp; 46465695Shibler vm_page_t *mlist; 46565695Shibler int npages; 46665695Shibler boolean_t sync; 46745749Smckusick enum uio_rw rw; 46845749Smckusick { 46945749Smckusick struct uio auio; 47045749Smckusick struct iovec aiov; 47145749Smckusick vm_offset_t kva, foff; 47245749Smckusick int error, size; 47348042Smckusick struct proc *p = curproc; /* XXX */ 47445749Smckusick 47565695Shibler /* XXX */ 47665695Shibler vm_page_t m; 47765695Shibler if (npages != 1) 47865695Shibler panic("vnode_pager_io: cannot handle multiple pages"); 47965695Shibler m = *mlist; 48065695Shibler /* XXX */ 48165695Shibler 48245749Smckusick #ifdef DEBUG 48345749Smckusick if (vpagerdebug & VDB_FOLLOW) 48445749Smckusick printf("vnode_pager_io(%x, %x, %c): vnode %x\n", 48545749Smckusick vnp, m, rw == UIO_READ ? 'R' : 'W', vnp->vnp_vp); 48645749Smckusick #endif 48745749Smckusick foff = m->offset + m->object->paging_offset; 48845749Smckusick /* 489*66075Shibler * Allocate a kernel virtual address and initialize so that 490*66075Shibler * we can use VOP_READ/WRITE routines. 49145749Smckusick */ 492*66075Shibler kva = vm_pager_map_pages(mlist, npages, sync); 493*66075Shibler if (kva == NULL) 494*66075Shibler return(VM_PAGER_AGAIN); 495*66075Shibler /* 496*66075Shibler * After all of the potentially blocking operations have been 497*66075Shibler * performed, we can do the size checks: 498*66075Shibler * read beyond EOF (returns error) 499*66075Shibler * short read 500*66075Shibler */ 501*66075Shibler VOP_LOCK(vnp->vnp_vp); 50245749Smckusick if (foff >= vnp->vnp_size) { 503*66075Shibler VOP_UNLOCK(vnp->vnp_vp); 504*66075Shibler vm_pager_unmap_pages(kva, npages); 50545749Smckusick #ifdef DEBUG 50645749Smckusick if (vpagerdebug & VDB_SIZE) 50745749Smckusick printf("vnode_pager_io: vp %x, off %d size %d\n", 50845749Smckusick vnp->vnp_vp, foff, vnp->vnp_size); 50945749Smckusick #endif 51045749Smckusick return(VM_PAGER_BAD); 51145749Smckusick } 51245749Smckusick if (foff + PAGE_SIZE > vnp->vnp_size) 51345749Smckusick size = vnp->vnp_size - foff; 51445749Smckusick else 51545749Smckusick size = PAGE_SIZE; 51645749Smckusick aiov.iov_base = (caddr_t)kva; 51745749Smckusick aiov.iov_len = size; 51845749Smckusick auio.uio_iov = &aiov; 51945749Smckusick auio.uio_iovcnt = 1; 52045749Smckusick auio.uio_offset = foff; 52145749Smckusick auio.uio_segflg = UIO_SYSSPACE; 52245749Smckusick auio.uio_rw = rw; 52345749Smckusick auio.uio_resid = size; 52448042Smckusick auio.uio_procp = (struct proc *)0; 52545749Smckusick #ifdef DEBUG 52645749Smckusick if (vpagerdebug & VDB_IO) 52745749Smckusick printf("vnode_pager_io: vp %x kva %x foff %x size %x", 52845749Smckusick vnp->vnp_vp, kva, foff, size); 52945749Smckusick #endif 53045749Smckusick if (rw == UIO_READ) 53148042Smckusick error = VOP_READ(vnp->vnp_vp, &auio, 0, p->p_ucred); 53245749Smckusick else 53348042Smckusick error = VOP_WRITE(vnp->vnp_vp, &auio, 0, p->p_ucred); 53465695Shibler VOP_UNLOCK(vnp->vnp_vp); 53545749Smckusick #ifdef DEBUG 53645749Smckusick if (vpagerdebug & VDB_IO) { 53745749Smckusick if (error || auio.uio_resid) 53845749Smckusick printf(" returns error %x, resid %x", 53945749Smckusick error, auio.uio_resid); 54045749Smckusick printf("\n"); 54145749Smckusick } 54245749Smckusick #endif 54345749Smckusick if (!error) { 54445749Smckusick register int count = size - auio.uio_resid; 54545749Smckusick 54645749Smckusick if (count == 0) 54745749Smckusick error = EINVAL; 54845749Smckusick else if (count != PAGE_SIZE && rw == UIO_READ) 54953342Sbostic bzero((void *)(kva + count), PAGE_SIZE - count); 55045749Smckusick } 55165695Shibler vm_pager_unmap_pages(kva, npages); 55256321Shibler return (error ? VM_PAGER_ERROR : VM_PAGER_OK); 55345749Smckusick } 554