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*65722Sbostic * @(#)vnode_pager.c 8.6 (Berkeley) 01/13/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)); 4965695Shibler static void vnode_pager_cluster 5065695Shibler __P((vm_pager_t, vm_offset_t, 5165695Shibler vm_offset_t *, vm_offset_t *)); 5253342Sbostic static void vnode_pager_dealloc __P((vm_pager_t)); 5353342Sbostic static int vnode_pager_getpage 5465695Shibler __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 5865695Shibler __P((vn_pager_t, vm_page_t *, int, 5965695Shibler boolean_t, enum uio_rw)); 6053342Sbostic static boolean_t vnode_pager_putpage 6165695Shibler __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, 6965695Shibler vnode_pager_haspage, 7065695Shibler 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; 15165695Shibler 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; 179*65722Sbostic #ifdef NOTDEF 18048042Smckusick struct proc *p = curproc; /* XXX */ 181*65722Sbostic #endif 18245749Smckusick 18345749Smckusick #ifdef DEBUG 18445749Smckusick if (vpagerdebug & VDB_FOLLOW) 18545749Smckusick printf("vnode_pager_dealloc(%x)\n", pager); 18645749Smckusick #endif 18745749Smckusick if (vp = vnp->vnp_vp) { 18845749Smckusick vp->v_vmdata = NULL; 18945749Smckusick vp->v_flag &= ~VTEXT; 190*65722Sbostic #if NOTDEF 19145749Smckusick /* can hang if done at reboot on NFS FS */ 19248042Smckusick (void) VOP_FSYNC(vp, p->p_ucred, p); 19345749Smckusick #endif 19445749Smckusick vrele(vp); 19545749Smckusick } 19665231Smckusick TAILQ_REMOVE(&vnode_pager_list, pager, pg_list); 19745749Smckusick free((caddr_t)vnp, M_VMPGDATA); 19845749Smckusick free((caddr_t)pager, M_VMPAGER); 19945749Smckusick } 20045749Smckusick 20153342Sbostic static int 20265695Shibler vnode_pager_getpage(pager, mlist, npages, sync) 20345749Smckusick vm_pager_t pager; 20465695Shibler vm_page_t *mlist; 20565695Shibler int npages; 20645749Smckusick boolean_t sync; 20745749Smckusick { 20845749Smckusick 20945749Smckusick #ifdef DEBUG 21045749Smckusick if (vpagerdebug & VDB_FOLLOW) 21165695Shibler printf("vnode_pager_getpage(%x, %x, %x, %x)\n", 21265695Shibler pager, mlist, npages, sync); 21345749Smckusick #endif 21465695Shibler return(vnode_pager_io((vn_pager_t)pager->pg_data, 21565695Shibler mlist, npages, sync, UIO_READ)); 21645749Smckusick } 21745749Smckusick 21853342Sbostic static boolean_t 21965695Shibler vnode_pager_putpage(pager, mlist, npages, sync) 22045749Smckusick vm_pager_t pager; 22165695Shibler vm_page_t *mlist; 22265695Shibler int npages; 22345749Smckusick boolean_t sync; 22445749Smckusick { 22545749Smckusick int err; 22645749Smckusick 22745749Smckusick #ifdef DEBUG 22845749Smckusick if (vpagerdebug & VDB_FOLLOW) 22965695Shibler printf("vnode_pager_putpage(%x, %x, %x, %x)\n", 23065695Shibler pager, mlist, npages, sync); 23145749Smckusick #endif 23248397Skarels if (pager == NULL) 23354818Storek return (FALSE); /* ??? */ 23465695Shibler err = vnode_pager_io((vn_pager_t)pager->pg_data, 23565695Shibler mlist, npages, sync, UIO_WRITE); 23665695Shibler /* 23765695Shibler * If the operation was successful, mark the pages clean. 23865695Shibler */ 23945749Smckusick if (err == VM_PAGER_OK) { 24065695Shibler while (npages--) { 24165695Shibler (*mlist)->flags |= PG_CLEAN; 24265695Shibler pmap_clear_modify(VM_PAGE_TO_PHYS(*mlist)); 24365695Shibler mlist++; 24465695Shibler } 24545749Smckusick } 24645749Smckusick return(err); 24745749Smckusick } 24845749Smckusick 24953342Sbostic static boolean_t 25045749Smckusick vnode_pager_haspage(pager, offset) 25145749Smckusick vm_pager_t pager; 25245749Smckusick vm_offset_t offset; 25345749Smckusick { 25445749Smckusick register vn_pager_t vnp = (vn_pager_t)pager->pg_data; 25545749Smckusick daddr_t bn; 25645749Smckusick int err; 25745749Smckusick 25845749Smckusick #ifdef DEBUG 25945749Smckusick if (vpagerdebug & VDB_FOLLOW) 26045749Smckusick printf("vnode_pager_haspage(%x, %x)\n", pager, offset); 26145749Smckusick #endif 26245749Smckusick 26345749Smckusick /* 26445749Smckusick * Offset beyond end of file, do not have the page 26545749Smckusick */ 26645749Smckusick if (offset >= vnp->vnp_size) { 26745749Smckusick #ifdef DEBUG 26845749Smckusick if (vpagerdebug & (VDB_FAIL|VDB_SIZE)) 26945749Smckusick printf("vnode_pager_haspage: pg %x, off %x, size %x\n", 27045749Smckusick pager, offset, vnp->vnp_size); 27145749Smckusick #endif 27245749Smckusick return(FALSE); 27345749Smckusick } 27445749Smckusick 27545749Smckusick /* 27645749Smckusick * Read the index to find the disk block to read 27745749Smckusick * from. If there is no block, report that we don't 27845749Smckusick * have this data. 27945749Smckusick * 28045749Smckusick * Assumes that the vnode has whole page or nothing. 28145749Smckusick */ 28265695Shibler VOP_LOCK(vnp->vnp_vp); 28345749Smckusick err = VOP_BMAP(vnp->vnp_vp, 28451941Smckusick offset / vnp->vnp_vp->v_mount->mnt_stat.f_iosize, 28556457Smargo (struct vnode **)0, &bn, NULL); 28665695Shibler VOP_UNLOCK(vnp->vnp_vp); 28745749Smckusick if (err) { 28845749Smckusick #ifdef DEBUG 28945749Smckusick if (vpagerdebug & VDB_FAIL) 29045749Smckusick printf("vnode_pager_haspage: BMAP err %d, pg %x, off %x\n", 29145749Smckusick err, pager, offset); 29245749Smckusick #endif 29345749Smckusick return(TRUE); 29445749Smckusick } 29545749Smckusick return((long)bn < 0 ? FALSE : TRUE); 29645749Smckusick } 29745749Smckusick 29865695Shibler static void 29965695Shibler vnode_pager_cluster(pager, offset, loffset, hoffset) 30065695Shibler vm_pager_t pager; 30165695Shibler vm_offset_t offset; 30265695Shibler vm_offset_t *loffset; 30365695Shibler vm_offset_t *hoffset; 30465695Shibler { 30565695Shibler vn_pager_t vnp = (vn_pager_t)pager->pg_data; 30665695Shibler vm_offset_t loff, hoff; 30765695Shibler 30865695Shibler #ifdef DEBUG 30965695Shibler if (vpagerdebug & VDB_FOLLOW) 31065695Shibler printf("vnode_pager_cluster(%x, %x) ", pager, offset); 31165695Shibler #endif 31265695Shibler loff = offset; 31365695Shibler if (loff >= vnp->vnp_size) 31465695Shibler panic("vnode_pager_cluster: bad offset"); 31565695Shibler /* 31665695Shibler * XXX could use VOP_BMAP to get maxcontig value 31765695Shibler */ 31865695Shibler hoff = loff + MAXBSIZE; 31965695Shibler if (hoff > round_page(vnp->vnp_size)) 32065695Shibler hoff = round_page(vnp->vnp_size); 32165695Shibler 32265695Shibler *loffset = loff; 32365695Shibler *hoffset = hoff; 32465695Shibler #ifdef DEBUG 32565695Shibler if (vpagerdebug & VDB_FOLLOW) 32665695Shibler printf("returns [%x-%x]\n", loff, hoff); 32765695Shibler #endif 32865695Shibler } 32965695Shibler 33045749Smckusick /* 33145749Smckusick * (XXX) 33245749Smckusick * Lets the VM system know about a change in size for a file. 33345749Smckusick * If this vnode is mapped into some address space (i.e. we have a pager 33445749Smckusick * for it) we adjust our own internal size and flush any cached pages in 33545749Smckusick * the associated object that are affected by the size change. 33645749Smckusick * 33745749Smckusick * Note: this routine may be invoked as a result of a pager put 33845749Smckusick * operation (possibly at object termination time), so we must be careful. 33945749Smckusick */ 34053480Smckusick void 34145749Smckusick vnode_pager_setsize(vp, nsize) 34245749Smckusick struct vnode *vp; 34345749Smckusick u_long nsize; 34445749Smckusick { 34545749Smckusick register vn_pager_t vnp; 34645749Smckusick register vm_object_t object; 34745749Smckusick vm_pager_t pager; 34845749Smckusick 34945749Smckusick /* 35045749Smckusick * Not a mapped vnode 35145749Smckusick */ 35245749Smckusick if (vp == NULL || vp->v_type != VREG || vp->v_vmdata == NULL) 35345749Smckusick return; 35445749Smckusick /* 35545749Smckusick * Hasn't changed size 35645749Smckusick */ 35745749Smckusick pager = (vm_pager_t)vp->v_vmdata; 35845749Smckusick vnp = (vn_pager_t)pager->pg_data; 35945749Smckusick if (nsize == vnp->vnp_size) 36045749Smckusick return; 36145749Smckusick /* 36245749Smckusick * No object. 36345749Smckusick * This can happen during object termination since 36445749Smckusick * vm_object_page_clean is called after the object 36545749Smckusick * has been removed from the hash table, and clean 36645749Smckusick * may cause vnode write operations which can wind 36745749Smckusick * up back here. 36845749Smckusick */ 36945749Smckusick object = vm_object_lookup(pager); 37048397Skarels if (object == NULL) 37145749Smckusick return; 37245749Smckusick 37345749Smckusick #ifdef DEBUG 37445749Smckusick if (vpagerdebug & (VDB_FOLLOW|VDB_SIZE)) 37545749Smckusick printf("vnode_pager_setsize: vp %x obj %x osz %d nsz %d\n", 37645749Smckusick vp, object, vnp->vnp_size, nsize); 37745749Smckusick #endif 37845749Smckusick /* 37945749Smckusick * File has shrunk. 38045749Smckusick * Toss any cached pages beyond the new EOF. 38145749Smckusick */ 38245749Smckusick if (nsize < vnp->vnp_size) { 38345749Smckusick vm_object_lock(object); 38445749Smckusick vm_object_page_remove(object, 38545749Smckusick (vm_offset_t)nsize, vnp->vnp_size); 38645749Smckusick vm_object_unlock(object); 38745749Smckusick } 38845749Smckusick vnp->vnp_size = (vm_offset_t)nsize; 38945749Smckusick vm_object_deallocate(object); 39045749Smckusick } 39145749Smckusick 39253480Smckusick void 39345749Smckusick vnode_pager_umount(mp) 39445749Smckusick register struct mount *mp; 39545749Smckusick { 39645749Smckusick register vm_pager_t pager, npager; 39745749Smckusick struct vnode *vp; 39845749Smckusick 39965231Smckusick for (pager = vnode_pager_list.tqh_first; pager != NULL; pager = npager){ 40045749Smckusick /* 40145749Smckusick * Save the next pointer now since uncaching may 40245749Smckusick * terminate the object and render pager invalid 40345749Smckusick */ 40465231Smckusick npager = pager->pg_list.tqe_next; 40545749Smckusick vp = ((vn_pager_t)pager->pg_data)->vnp_vp; 40665695Shibler if (mp == (struct mount *)0 || vp->v_mount == mp) { 40765695Shibler VOP_LOCK(vp); 40845749Smckusick (void) vnode_pager_uncache(vp); 40965695Shibler VOP_UNLOCK(vp); 41065695Shibler } 41145749Smckusick } 41245749Smckusick } 41345749Smckusick 41445749Smckusick /* 41545749Smckusick * Remove vnode associated object from the object cache. 41645749Smckusick * 41765695Shibler * XXX unlock the vnode if it is currently locked. 41865695Shibler * We must do this since uncaching the object may result in its 41965695Shibler * destruction which may initiate paging activity which may necessitate 42065695Shibler * re-locking the vnode. 42145749Smckusick */ 42253480Smckusick boolean_t 42345749Smckusick vnode_pager_uncache(vp) 42445749Smckusick register struct vnode *vp; 42545749Smckusick { 42645749Smckusick register vm_object_t object; 42765695Shibler boolean_t uncached; 42845749Smckusick vm_pager_t pager; 42945749Smckusick 43045749Smckusick /* 43145749Smckusick * Not a mapped vnode 43245749Smckusick */ 43345749Smckusick pager = (vm_pager_t)vp->v_vmdata; 43448397Skarels if (pager == NULL) 43545749Smckusick return (TRUE); 43665695Shibler #ifdef DEBUG 43765695Shibler if (!VOP_ISLOCKED(vp)) { 43865695Shibler extern int (**nfsv2_vnodeop_p)(); 43965695Shibler 44065695Shibler if (vp->v_op != nfsv2_vnodeop_p) 44165695Shibler panic("vnode_pager_uncache: vnode not locked!"); 44265695Shibler } 44365695Shibler #endif 44445749Smckusick /* 44545749Smckusick * Must use vm_object_lookup() as it actually removes 44645749Smckusick * the object from the cache list. 44745749Smckusick */ 44845749Smckusick object = vm_object_lookup(pager); 44945749Smckusick if (object) { 45045749Smckusick uncached = (object->ref_count <= 1); 45165695Shibler VOP_UNLOCK(vp); 45245749Smckusick pager_cache(object, FALSE); 45365695Shibler VOP_LOCK(vp); 45445749Smckusick } else 45545749Smckusick uncached = TRUE; 45645749Smckusick return(uncached); 45745749Smckusick } 45845749Smckusick 45953342Sbostic static int 46065695Shibler vnode_pager_io(vnp, mlist, npages, sync, rw) 46145749Smckusick register vn_pager_t vnp; 46265695Shibler vm_page_t *mlist; 46365695Shibler int npages; 46465695Shibler boolean_t sync; 46545749Smckusick enum uio_rw rw; 46645749Smckusick { 46745749Smckusick struct uio auio; 46845749Smckusick struct iovec aiov; 46945749Smckusick vm_offset_t kva, foff; 47045749Smckusick int error, size; 47148042Smckusick struct proc *p = curproc; /* XXX */ 47245749Smckusick 47365695Shibler /* XXX */ 47465695Shibler vm_page_t m; 47565695Shibler if (npages != 1) 47665695Shibler panic("vnode_pager_io: cannot handle multiple pages"); 47765695Shibler m = *mlist; 47865695Shibler /* XXX */ 47965695Shibler 48045749Smckusick #ifdef DEBUG 48145749Smckusick if (vpagerdebug & VDB_FOLLOW) 48245749Smckusick printf("vnode_pager_io(%x, %x, %c): vnode %x\n", 48345749Smckusick vnp, m, rw == UIO_READ ? 'R' : 'W', vnp->vnp_vp); 48445749Smckusick #endif 48545749Smckusick foff = m->offset + m->object->paging_offset; 48645749Smckusick /* 48745749Smckusick * Return failure if beyond current EOF 48845749Smckusick */ 48945749Smckusick if (foff >= vnp->vnp_size) { 49045749Smckusick #ifdef DEBUG 49145749Smckusick if (vpagerdebug & VDB_SIZE) 49245749Smckusick printf("vnode_pager_io: vp %x, off %d size %d\n", 49345749Smckusick vnp->vnp_vp, foff, vnp->vnp_size); 49445749Smckusick #endif 49545749Smckusick return(VM_PAGER_BAD); 49645749Smckusick } 49745749Smckusick if (foff + PAGE_SIZE > vnp->vnp_size) 49845749Smckusick size = vnp->vnp_size - foff; 49945749Smckusick else 50045749Smckusick size = PAGE_SIZE; 50145749Smckusick /* 50245749Smckusick * Allocate a kernel virtual address and initialize so that 50345749Smckusick * we can use VOP_READ/WRITE routines. 50445749Smckusick */ 50565695Shibler kva = vm_pager_map_pages(mlist, npages, sync); 50665695Shibler if (kva == NULL) 50765695Shibler return(VM_PAGER_AGAIN); 50845749Smckusick aiov.iov_base = (caddr_t)kva; 50945749Smckusick aiov.iov_len = size; 51045749Smckusick auio.uio_iov = &aiov; 51145749Smckusick auio.uio_iovcnt = 1; 51245749Smckusick auio.uio_offset = foff; 51345749Smckusick auio.uio_segflg = UIO_SYSSPACE; 51445749Smckusick auio.uio_rw = rw; 51545749Smckusick auio.uio_resid = size; 51648042Smckusick auio.uio_procp = (struct proc *)0; 51745749Smckusick #ifdef DEBUG 51845749Smckusick if (vpagerdebug & VDB_IO) 51945749Smckusick printf("vnode_pager_io: vp %x kva %x foff %x size %x", 52045749Smckusick vnp->vnp_vp, kva, foff, size); 52145749Smckusick #endif 52265695Shibler VOP_LOCK(vnp->vnp_vp); 52345749Smckusick if (rw == UIO_READ) 52448042Smckusick error = VOP_READ(vnp->vnp_vp, &auio, 0, p->p_ucred); 52545749Smckusick else 52648042Smckusick error = VOP_WRITE(vnp->vnp_vp, &auio, 0, p->p_ucred); 52765695Shibler VOP_UNLOCK(vnp->vnp_vp); 52845749Smckusick #ifdef DEBUG 52945749Smckusick if (vpagerdebug & VDB_IO) { 53045749Smckusick if (error || auio.uio_resid) 53145749Smckusick printf(" returns error %x, resid %x", 53245749Smckusick error, auio.uio_resid); 53345749Smckusick printf("\n"); 53445749Smckusick } 53545749Smckusick #endif 53645749Smckusick if (!error) { 53745749Smckusick register int count = size - auio.uio_resid; 53845749Smckusick 53945749Smckusick if (count == 0) 54045749Smckusick error = EINVAL; 54145749Smckusick else if (count != PAGE_SIZE && rw == UIO_READ) 54253342Sbostic bzero((void *)(kva + count), PAGE_SIZE - count); 54345749Smckusick } 54465695Shibler vm_pager_unmap_pages(kva, npages); 54556321Shibler return (error ? VM_PAGER_ERROR : VM_PAGER_OK); 54645749Smckusick } 547