From bbc0ec528448739b957050b4bcc870cc4617ac29 Mon Sep 17 00:00:00 2001 From: David Greenman Date: Thu, 4 Aug 1994 03:06:48 +0000 Subject: [PATCH] Integrated VM system improvements/fixes from FreeBSD-1.1.5. --- sys/vm/vm_glue.c | 38 ++- sys/vm/vm_mmap.c | 10 +- sys/vm/vm_page.h | 3 +- sys/vm/vm_pageout.c | 7 +- sys/vm/vnode_pager.c | 654 ++++++++++++++++++++++--------------------- 5 files changed, 363 insertions(+), 349 deletions(-) diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index e2116974f25b..70fd00d6a87f 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -59,7 +59,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id$ + * $Id: vm_glue.c,v 1.3 1994/08/02 07:55:19 davidg Exp $ */ #include @@ -109,19 +109,16 @@ useracc(addr, len, rw) vm_prot_t prot = rw == B_READ ? VM_PROT_READ : VM_PROT_WRITE; /* - * XXX - specially disallow access to user page tables - they are - * in the map. - * - * XXX - don't specially disallow access to the user area - treat - * it as incorrectly as elsewhere. + * XXX - check separately to disallow access to user area and user + * page tables - they are in the map. * * XXX - VM_MAXUSER_ADDRESS is an end address, not a max. It was - * only used (as an end address) in trap.c. Use it as an end - * address here too. + * once only used (as an end address) in trap.c. Use it as an end + * address here too. This bogusness has spread. I just fixed + * where it was used as a max in vm_mmap.c. */ - if ((vm_offset_t) addr >= VM_MAXUSER_ADDRESS - || (vm_offset_t) addr + len > VM_MAXUSER_ADDRESS - || (vm_offset_t) addr + len <= (vm_offset_t) addr) { + if ((vm_offset_t) addr + len > /* XXX */ VM_MAXUSER_ADDRESS + || (vm_offset_t) addr + len < (vm_offset_t) addr) { return (FALSE); } @@ -276,23 +273,24 @@ void vm_init_limits(p) register struct proc *p; { - int tmp; + int rss_limit; /* * Set up the initial limits on process VM. - * Set the maximum resident set size to be all - * of (reasonably) available memory. This causes - * any single, large process to start random page - * replacement once it fills memory. + * Set the maximum resident set size to be half + * of (reasonably) available memory. Since this + * is a soft limit, it comes into effect only + * when the system is out of memory - half of + * main memory helps to favor smaller processes, + * and reduces thrashing of the object cache. */ p->p_rlimit[RLIMIT_STACK].rlim_cur = DFLSSIZ; p->p_rlimit[RLIMIT_STACK].rlim_max = MAXSSIZ; p->p_rlimit[RLIMIT_DATA].rlim_cur = DFLDSIZ; p->p_rlimit[RLIMIT_DATA].rlim_max = MAXDSIZ; - tmp = ((2 * cnt.v_free_count) / 3) - 32; - if (cnt.v_free_count < 512) - tmp = cnt.v_free_count; - p->p_rlimit[RLIMIT_RSS].rlim_cur = ptoa(tmp); + /* limit the limit to no less than 128K */ + rss_limit = max(cnt.v_free_count / 2, 32); + p->p_rlimit[RLIMIT_RSS].rlim_cur = ptoa(rss_limit); p->p_rlimit[RLIMIT_RSS].rlim_max = RLIM_INFINITY; } diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index d0fb654c9549..2c1624b251cb 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -38,7 +38,7 @@ * from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$ * * @(#)vm_mmap.c 8.4 (Berkeley) 1/12/94 - * $Id$ + * $Id: vm_mmap.c,v 1.3 1994/08/02 07:55:28 davidg Exp $ */ /* @@ -216,13 +216,13 @@ mmap(p, uap, retval) * Note that VM_*_ADDRESS are not constants due to casts (argh). */ if (flags & MAP_FIXED) { - if (VM_MAXUSER_ADDRESS > 0 && addr + size >= VM_MAXUSER_ADDRESS) + if (VM_MAXUSER_ADDRESS > 0 && addr + size > VM_MAXUSER_ADDRESS) return (EINVAL); #ifndef i386 if (VM_MIN_ADDRESS > 0 && addr < VM_MIN_ADDRESS) return (EINVAL); #endif - if (addr > addr + size) + if (addr + size < addr) return (EINVAL); } /* @@ -401,13 +401,13 @@ munmap(p, uap, retval) * Check for illegal addresses. Watch out for address wrap... * Note that VM_*_ADDRESS are not constants due to casts (argh). */ - if (VM_MAXUSER_ADDRESS > 0 && addr + size >= VM_MAXUSER_ADDRESS) + if (VM_MAXUSER_ADDRESS > 0 && addr + size > VM_MAXUSER_ADDRESS) return (EINVAL); #ifndef i386 if (VM_MIN_ADDRESS > 0 && addr < VM_MIN_ADDRESS) return (EINVAL); #endif - if (addr > addr + size) + if (addr + size < addr) return (EINVAL); map = &p->p_vmspace->vm_map; /* diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h index 57ffbe843e6c..9dc605490af5 100644 --- a/sys/vm/vm_page.h +++ b/sys/vm/vm_page.h @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id$ + * $Id: vm_page.h,v 1.3 1994/08/02 07:55:32 davidg Exp $ */ /* @@ -132,6 +132,7 @@ struct vm_page { #define PG_FAKE 0x0200 /* page is placeholder for pagein (O) */ #define PG_FILLED 0x0400 /* client flag to set when filled */ #define PG_DIRTY 0x0800 /* client flag to set when dirty */ +#define PG_REFERENCED 0x1000 /* page has been referenced */ #define PG_PAGEROWNED 0x4000 /* DEBUG: async paging op in progress */ #define PG_PTPAGE 0x8000 /* DEBUG: is a user page table page */ diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 99d7365900ca..7c092bb1cf71 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -65,7 +65,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_pageout.c,v 1.4 1994/08/01 11:25:45 davidg Exp $ + * $Id: vm_pageout.c,v 1.5 1994/08/02 07:55:33 davidg Exp $ */ /* @@ -108,6 +108,7 @@ extern int swap_pager_ready(); #define LOWATER ((2048*1024)/NBPG) #define VM_PAGEOUT_PAGE_COUNT 8 +int vm_pageout_page_count = VM_PAGEOUT_PAGE_COUNT; static vm_offset_t vm_space_needed; int vm_pageout_req_do_stats; @@ -190,7 +191,7 @@ vm_pageout_clean(m, sync) ms[0] = m; if( pager = object->pager) { - for(i=1;iflags & (PG_CLEAN|PG_INACTIVE|PG_BUSY)) == PG_INACTIVE) || (( ms[i]->flags & PG_CLEAN) == 0 && sync == VM_PAGEOUT_FORCE)) @@ -619,7 +620,7 @@ vm_pageout_scan() /* * if the next page has been re-activated, start scanning again */ - if (next && (next->flags & PG_INACTIVE) == 0) + if (!next || (next->flags & PG_INACTIVE) == 0) goto rescan1; } else if (pmap_is_referenced(VM_PAGE_TO_PHYS(m))) { pmap_clear_reference(VM_PAGE_TO_PHYS(m)); diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index b8e5a192796f..6d1c37287331 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * from: @(#)vnode_pager.c 7.5 (Berkeley) 4/20/91 - * $Id: vnode_pager.c,v 1.17 1994/04/05 03:23:53 davidg Exp $ + * $Id: vnode_pager.c,v 1.2 1994/05/25 09:21:11 rgrimes Exp $ */ /* @@ -57,7 +57,7 @@ * * 1) Supports multiple - block reads * 2) Bypasses buffer cache for reads - * + * * TODO: * * 1) Totally bypass buffer cache for reads @@ -81,15 +81,15 @@ #include #include -int vnode_pager_putmulti(); +int vnode_pager_putmulti(); -void vnode_pager_init(); -vm_pager_t vnode_pager_alloc(caddr_t, vm_offset_t, vm_prot_t, vm_offset_t); -void vnode_pager_dealloc(); -int vnode_pager_getpage(); -int vnode_pager_getmulti(); -int vnode_pager_putpage(); -boolean_t vnode_pager_haspage(); +void vnode_pager_init(); +vm_pager_t vnode_pager_alloc(caddr_t, vm_offset_t, vm_prot_t, vm_offset_t); +void vnode_pager_dealloc(); +int vnode_pager_getpage(); +int vnode_pager_getmulti(); +int vnode_pager_putpage(); +boolean_t vnode_pager_haspage(); struct pagerops vnodepagerops = { vnode_pager_init, @@ -102,10 +102,10 @@ struct pagerops vnodepagerops = { vnode_pager_haspage }; -static int vnode_pager_input(vn_pager_t vnp, vm_page_t *m, int count, int reqpage); -static int vnode_pager_output(vn_pager_t vnp, vm_page_t *m, int count, int *rtvals); -struct buf * getpbuf() ; -void relpbuf(struct buf *bp) ; +static int vnode_pager_input(vn_pager_t vnp, vm_page_t * m, int count, int reqpage); +static int vnode_pager_output(vn_pager_t vnp, vm_page_t * m, int count, int *rtvals); +struct buf * getpbuf(); +void relpbuf(struct buf * bp); extern vm_map_t pager_map; @@ -141,26 +141,28 @@ vnode_pager_alloc(handle, size, prot, offset) * Pageout to vnode, no can do yet. */ if (handle == NULL) - return(NULL); + return (NULL); /* - * Vnodes keep a pointer to any associated pager so no need to - * lookup with vm_pager_lookup. + * Vnodes keep a pointer to any associated pager so no need to lookup + * with vm_pager_lookup. */ - vp = (struct vnode *)handle; - pager = (vm_pager_t)vp->v_vmdata; + vp = (struct vnode *) handle; + pager = (vm_pager_t) vp->v_vmdata; if (pager == NULL) { + /* * Allocate pager structures */ - pager = (vm_pager_t)malloc(sizeof *pager, M_VMPAGER, M_WAITOK); + pager = (vm_pager_t) malloc(sizeof *pager, M_VMPAGER, M_WAITOK); if (pager == NULL) - return(NULL); - vnp = (vn_pager_t)malloc(sizeof *vnp, M_VMPGDATA, M_WAITOK); + return (NULL); + vnp = (vn_pager_t) malloc(sizeof *vnp, M_VMPGDATA, M_WAITOK); if (vnp == NULL) { - free((caddr_t)pager, M_VMPAGER); - return(NULL); + free((caddr_t) pager, M_VMPAGER); + return (NULL); } + /* * And an object of the appropriate size */ @@ -169,10 +171,11 @@ vnode_pager_alloc(handle, size, prot, offset) vm_object_enter(object, pager); vm_object_setpager(object, pager, 0, TRUE); } else { - free((caddr_t)vnp, M_VMPGDATA); - free((caddr_t)pager, M_VMPAGER); - return(NULL); + free((caddr_t) vnp, M_VMPGDATA); + free((caddr_t) pager, M_VMPAGER); + return (NULL); } + /* * Hold a reference to the vnode and initialize pager data. */ @@ -185,25 +188,26 @@ vnode_pager_alloc(handle, size, prot, offset) pager->pg_handle = handle; pager->pg_type = PG_VNODE; pager->pg_ops = &vnodepagerops; - pager->pg_data = (caddr_t)vnp; - vp->v_vmdata = (caddr_t)pager; + pager->pg_data = (caddr_t) vnp; + vp->v_vmdata = (caddr_t) pager; } else { + /* - * vm_object_lookup() will remove the object from the - * cache if found and also gain a reference to the object. + * vm_object_lookup() will remove the object from the cache if + * found and also gain a reference to the object. */ object = vm_object_lookup(pager); } - return(pager); + return (pager); } void vnode_pager_dealloc(pager) vm_pager_t pager; { - register vn_pager_t vnp = (vn_pager_t)pager->pg_data; + register vn_pager_t vnp = (vn_pager_t) pager->pg_data; register struct vnode *vp; - struct proc *p = curproc; /* XXX */ + struct proc *p = curproc; /* XXX */ if (vp = vnp->vnp_vp) { vp->v_vmdata = NULL; @@ -214,21 +218,20 @@ vnode_pager_dealloc(pager) #endif vrele(vp); } - TAILQ_REMOVE(&vnode_pager_list, pager, pg_list); - free((caddr_t)vnp, M_VMPGDATA); - free((caddr_t)pager, M_VMPAGER); + free((caddr_t) vnp, M_VMPGDATA); + free((caddr_t) pager, M_VMPAGER); } int vnode_pager_getmulti(pager, m, count, reqpage, sync) vm_pager_t pager; vm_page_t *m; - int count; - int reqpage; + int count; + int reqpage; boolean_t sync; { - + return vnode_pager_input((vn_pager_t) pager->pg_data, m, count, reqpage); } @@ -239,13 +242,14 @@ vnode_pager_getpage(pager, m, sync) boolean_t sync; { - int err; + int err; vm_page_t marray[1]; + if (pager == NULL) return FALSE; marray[0] = m; - return vnode_pager_input((vn_pager_t)pager->pg_data, marray, 1, 0); + return vnode_pager_input((vn_pager_t) pager->pg_data, marray, 1, 0); } boolean_t @@ -254,14 +258,14 @@ vnode_pager_putpage(pager, m, sync) vm_page_t m; boolean_t sync; { - int err; + int err; vm_page_t marray[1]; - int rtvals[1]; + int rtvals[1]; if (pager == NULL) return FALSE; marray[0] = m; - vnode_pager_output((vn_pager_t)pager->pg_data, marray, 1, rtvals); + vnode_pager_output((vn_pager_t) pager->pg_data, marray, 1, rtvals); return rtvals[0]; } @@ -269,11 +273,11 @@ int vnode_pager_putmulti(pager, m, c, sync, rtvals) vm_pager_t pager; vm_page_t *m; - int c; + int c; boolean_t sync; - int *rtvals; + int *rtvals; { - return vnode_pager_output((vn_pager_t)pager->pg_data, m, c, rtvals); + return vnode_pager_output((vn_pager_t) pager->pg_data, m, c, rtvals); } @@ -282,32 +286,30 @@ vnode_pager_haspage(pager, offset) vm_pager_t pager; vm_offset_t offset; { - register vn_pager_t vnp = (vn_pager_t)pager->pg_data; + register vn_pager_t vnp = (vn_pager_t) pager->pg_data; daddr_t bn; - int run; - int err; + int err; /* * Offset beyond end of file, do not have the page */ if (offset >= vnp->vnp_size) { - return(FALSE); + return (FALSE); } /* - * Read the index to find the disk block to read - * from. If there is no block, report that we don't - * have this data. - * + * Read the index to find the disk block to read from. If there is no + * block, report that we don't have this data. + * * Assumes that the vnode has whole page or nothing. */ err = VOP_BMAP(vnp->vnp_vp, offset / vnp->vnp_vp->v_mount->mnt_stat.f_iosize, - (struct vnode **)0, &bn, 0); + (struct vnode **) 0, &bn, 0); if (err) { - return(TRUE); + return (TRUE); } - return((long)bn < 0 ? FALSE : TRUE); + return ((long) bn < 0 ? FALSE : TRUE); } /* @@ -322,7 +324,7 @@ vnode_pager_haspage(pager, offset) void vnode_pager_setsize(vp, nsize) struct vnode *vp; - u_long nsize; + u_long nsize; { register vn_pager_t vnp; register vm_object_t object; @@ -333,36 +335,73 @@ vnode_pager_setsize(vp, nsize) */ if (vp == NULL || vp->v_type != VREG || vp->v_vmdata == NULL) return; + /* * Hasn't changed size */ - pager = (vm_pager_t)vp->v_vmdata; - vnp = (vn_pager_t)pager->pg_data; + pager = (vm_pager_t) vp->v_vmdata; + vnp = (vn_pager_t) pager->pg_data; if (nsize == vnp->vnp_size) return; + /* - * No object. - * This can happen during object termination since - * vm_object_page_clean is called after the object - * has been removed from the hash table, and clean - * may cause vnode write operations which can wind - * up back here. + * No object. This can happen during object termination since + * vm_object_page_clean is called after the object has been removed + * from the hash table, and clean may cause vnode write operations + * which can wind up back here. */ object = vm_object_lookup(pager); if (object == NULL) return; /* - * File has shrunk. - * Toss any cached pages beyond the new EOF. + * File has shrunk. Toss any cached pages beyond the new EOF. */ - if (round_page(nsize) < round_page(vnp->vnp_size)) { + if (nsize < vnp->vnp_size) { vm_object_lock(object); vm_object_page_remove(object, - (vm_offset_t)round_page(nsize), round_page(vnp->vnp_size)); + round_page((vm_offset_t) nsize), vnp->vnp_size); vm_object_unlock(object); + + /* + * this gets rid of garbage at the end of a page that is now + * only partially backed by the vnode... + */ + if (nsize & PAGE_MASK) { + vm_offset_t kva; + vm_page_t m; + + m = vm_page_lookup(object, trunc_page((vm_offset_t) nsize)); + if (m) { + kva = vm_pager_map_page(m); + bzero((caddr_t) kva + (nsize & PAGE_MASK), + round_page(nsize) - nsize); + vm_pager_unmap_page(kva); + } + } + } else { + + /* + * this allows the filesystem and VM cache to stay in sync if + * the VM page hasn't been modified... After the page is + * removed -- it will be faulted back in from the filesystem + * cache. + */ + if (vnp->vnp_size & PAGE_MASK) { + vm_page_t m; + + m = vm_page_lookup(object, trunc_page(vnp->vnp_size)); + if (m && (m->flags & PG_CLEAN)) { + vm_object_lock(object); + vm_object_page_remove(object, + vnp->vnp_size, vnp->vnp_size); + vm_object_unlock(object); + } + } } - vnp->vnp_size = (vm_offset_t)nsize; + vnp->vnp_size = (vm_offset_t) nsize; + object->size = round_page(nsize); + vm_object_deallocate(object); } @@ -374,14 +413,15 @@ vnode_pager_umount(mp) struct vnode *vp; pager = vnode_pager_list.tqh_first; - while( pager) { + while (pager) { + /* - * Save the next pointer now since uncaching may - * terminate the object and render pager invalid + * Save the next pointer now since uncaching may terminate the + * object and render pager invalid */ - vp = ((vn_pager_t)pager->pg_data)->vnp_vp; + vp = ((vn_pager_t) pager->pg_data)->vnp_vp; npager = pager->pg_list.tqe_next; - if (mp == (struct mount *)0 || vp->v_mount == mp) + if (mp == (struct mount *) 0 || vp->v_mount == mp) (void) vnode_pager_uncache(vp); pager = npager; } @@ -404,21 +444,22 @@ vnode_pager_uncache(vp) /* * Not a mapped vnode */ - pager = (vm_pager_t)vp->v_vmdata; + pager = (vm_pager_t) vp->v_vmdata; if (pager == NULL) return (TRUE); + /* - * Unlock the vnode if it is currently locked. - * We do this since uncaching the object may result - * in its destruction which may initiate paging - * activity which may necessitate locking the vnode. + * Unlock the vnode if it is currently locked. We do this since + * uncaching the object may result in its destruction which may + * initiate paging activity which may necessitate locking the vnode. */ locked = VOP_ISLOCKED(vp); if (locked) VOP_UNLOCK(vp); + /* - * Must use vm_object_lookup() as it actually removes - * the object from the cache list. + * Must use vm_object_lookup() as it actually removes the object from + * the cache list. */ object = vm_object_lookup(pager); if (object) { @@ -428,46 +469,8 @@ vnode_pager_uncache(vp) uncached = TRUE; if (locked) VOP_LOCK(vp); - return(uncached); + return (uncached); } -#if 0 -/* - * Remove vnode associated object from the object cache. - * - * XXX unlock the vnode if it is currently locked. - * We must do this since uncaching the object may result in its - * destruction which may initiate paging activity which may necessitate - * re-locking the vnode. - */ -boolean_t -vnode_pager_uncache(vp) - register struct vnode *vp; -{ - register vm_object_t object; - boolean_t uncached; - vm_pager_t pager; - - /* - * Not a mapped vnode - */ - pager = (vm_pager_t)vp->v_vmdata; - if (pager == NULL) - return (TRUE); - /* - * Must use vm_object_lookup() as it actually removes - * the object from the cache list. - */ - object = vm_object_lookup(pager); - if (object) { - uncached = (object->ref_count <= 1); - VOP_UNLOCK(vp); - pager_cache(object, FALSE); - VOP_LOCK(vp); - } else - uncached = TRUE; - return(uncached); -} -#endif void @@ -487,21 +490,20 @@ vnode_pager_addr(vp, address) struct vnode *vp; vm_offset_t address; { - int rtaddress; - int bsize; + int rtaddress; + int bsize; vm_offset_t block; struct vnode *rtvp; - int err; - int vblock, voffset; - int run; + int err; + int vblock, voffset; bsize = vp->v_mount->mnt_stat.f_iosize; vblock = address / bsize; voffset = address % bsize; - err = VOP_BMAP(vp,vblock,&rtvp,&block,0); + err = VOP_BMAP(vp, vblock, &rtvp, &block, 0); - if( err) + if (err) rtaddress = -1; else rtaddress = block * DEV_BSIZE + voffset; @@ -517,7 +519,7 @@ vnode_pager_iodone(bp) struct buf *bp; { bp->b_flags |= B_DONE; - wakeup((caddr_t)bp); + wakeup((caddr_t) bp); } /* @@ -528,19 +530,18 @@ vnode_pager_input_smlfs(vnp, m) vn_pager_t vnp; vm_page_t m; { - int i; - int s; + int i; + int s; vm_offset_t paging_offset; struct vnode *dp, *vp; struct buf *bp; vm_offset_t mapsize; vm_offset_t foff; vm_offset_t kva; - int fileaddr; - int block; + int fileaddr; + int block; vm_offset_t bsize; - int error = 0; - int run; + int error = 0; paging_offset = m->object->paging_offset; vp = vnp->vnp_vp; @@ -551,88 +552,88 @@ vnode_pager_input_smlfs(vnp, m) kva = vm_pager_map_page(m); - for(i=0;ib_flags & B_BUSY) { bp->b_flags |= B_WANTED; - tsleep ((caddr_t)bp, PVM, "vnwblk", 0); + tsleep((caddr_t) bp, PVM, "vnwblk", 0); continue; } - amount = bsize; if ((foff + bsize) > vnp->vnp_size) amount = vnp->vnp_size - foff; - /* - * make sure that this page is in the buffer - */ + /* + * make sure that this page is in the buffer + */ if ((amount > 0) && amount <= bp->b_bcount) { bp->b_flags |= B_BUSY; splx(s); - /* - * copy the data from the buffer - */ - bcopy(bp->b_un.b_addr, (caddr_t)kva + i * bsize, amount); + /* + * copy the data from the buffer + */ + bcopy(bp->b_un.b_addr, (caddr_t) kva + i * bsize, amount); if (amount < bsize) { - bzero((caddr_t)kva + amount, bsize - amount); + bzero((caddr_t) kva + amount, bsize - amount); } bp->b_flags &= ~B_BUSY; - wakeup((caddr_t)bp); + wakeup((caddr_t) bp); goto nextblock; } break; } splx(s); fileaddr = vnode_pager_addr(vp, foff + i * bsize); - if( fileaddr != -1) { + if (fileaddr != -1) { bp = getpbuf(); VHOLD(vp); - /* build a minimal buffer header */ + /* build a minimal buffer header */ bp->b_flags = B_BUSY | B_READ | B_CALL; bp->b_iodone = vnode_pager_iodone; bp->b_proc = curproc; bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred; - if( bp->b_rcred != NOCRED) + if (bp->b_rcred != NOCRED) crhold(bp->b_rcred); - if( bp->b_wcred != NOCRED) + if (bp->b_wcred != NOCRED) crhold(bp->b_wcred); bp->b_un.b_addr = (caddr_t) kva + i * bsize; bp->b_blkno = fileaddr / DEV_BSIZE; bgetvp(dp, bp); bp->b_bcount = bsize; bp->b_bufsize = bsize; - - /* do the input */ + + /* do the input */ VOP_STRATEGY(bp); - /* we definitely need to be at splbio here */ + /* we definitely need to be at splbio here */ s = splbio(); while ((bp->b_flags & B_DONE) == 0) { - tsleep((caddr_t)bp, PVM, "vnsrd", 0); + tsleep((caddr_t) bp, PVM, "vnsrd", 0); } splx(s); if ((bp->b_flags & B_ERROR) != 0) error = EIO; - /* - * free the buffer header back to the swap buffer pool - */ + /* + * free the buffer header back to the swap buffer pool + */ relpbuf(bp); HOLDRELE(vp); - if( error) + if (error) break; } else { bzero((caddr_t) kva + i * bsize, bsize); @@ -640,7 +641,7 @@ vnode_pager_input_smlfs(vnp, m) nextblock: } vm_pager_unmap_page(kva); - if( error) { + if (error) { return VM_PAGER_FAIL; } pmap_clear_modify(VM_PAGE_TO_PHYS(m)); @@ -659,16 +660,17 @@ vnode_pager_input_old(vnp, m) vn_pager_t vnp; vm_page_t m; { - int i; + int i; struct uio auio; struct iovec aiov; - int error; - int size; + int error; + int size; vm_offset_t foff; vm_offset_t kva; error = 0; foff = m->offset + m->object->paging_offset; + /* * Return failure if beyond current EOF */ @@ -683,7 +685,7 @@ vnode_pager_input_old(vnp, m) * we can use VOP_READ/WRITE routines. */ kva = vm_pager_map_page(m); - aiov.iov_base = (caddr_t)kva; + aiov.iov_base = (caddr_t) kva; aiov.iov_len = size; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; @@ -691,7 +693,7 @@ vnode_pager_input_old(vnp, m) auio.uio_segflg = UIO_SYSSPACE; auio.uio_rw = UIO_READ; auio.uio_resid = size; - auio.uio_procp = (struct proc *)0; + auio.uio_procp = (struct proc *) 0; error = VOP_READ(vnp->vnp_vp, &auio, 0, curproc->p_ucred); if (!error) { @@ -700,14 +702,14 @@ vnode_pager_input_old(vnp, m) if (count == 0) error = EINVAL; else if (count != PAGE_SIZE) - bzero((caddr_t)kva + count, PAGE_SIZE - count); + bzero((caddr_t) kva + count, PAGE_SIZE - count); } vm_pager_unmap_page(kva); } pmap_clear_modify(VM_PAGE_TO_PHYS(m)); m->flags |= PG_CLEAN; m->flags &= ~PG_LAUNDRY; - return error?VM_PAGER_FAIL:VM_PAGER_OK; + return error ? VM_PAGER_FAIL : VM_PAGER_OK; } /* @@ -717,53 +719,54 @@ int vnode_pager_input(vnp, m, count, reqpage) register vn_pager_t vnp; vm_page_t *m; - int count, reqpage; + int count, reqpage; { - int i,j; + int i, j; vm_offset_t kva, foff; - int size; - struct proc *p = curproc; /* XXX */ + int size; + struct proc *p = curproc; /* XXX */ vm_object_t object; vm_offset_t paging_offset; struct vnode *dp, *vp; vm_offset_t mapsize; - int bsize; + int bsize; - int first, last; - int reqaddr, firstaddr; - int run; - int block, offset; + int first, last; + int reqaddr, firstaddr; + int block, offset; - int nbp; + int nbp; struct buf *bp; - int s; - int failflag; + int s; + int failflag; - int errtype=0; /* 0 is file type otherwise vm type */ - int error = 0; + int errtype = 0; /* 0 is file type otherwise vm type */ + int error = 0; - object = m[reqpage]->object; /* all vm_page_t items are in same object */ + object = m[reqpage]->object; /* all vm_page_t items are in same + * object */ paging_offset = object->paging_offset; vp = vnp->vnp_vp; bsize = vp->v_mount->mnt_stat.f_iosize; /* get the UNDERLYING device for the file with VOP_BMAP() */ + /* - * originally, we did not check for an error return - * value -- assuming an fs always has a bmap entry point - * -- that assumption is wrong!!! + * originally, we did not check for an error return value -- assuming + * an fs always has a bmap entry point -- that assumption is wrong!!! */ kva = 0; mapsize = 0; foff = m[reqpage]->offset + paging_offset; if (!VOP_BMAP(vp, foff, &dp, 0, 0)) { + /* * we do not block for a kva, notice we default to a kva * conservative behavior */ - kva = kmem_alloc_pageable(pager_map, (mapsize = count*PAGE_SIZE)); - if( !kva) { + kva = kmem_alloc_pageable(pager_map, (mapsize = count * PAGE_SIZE)); + if (!kva) { for (i = 0; i < count; i++) { if (i != reqpage) { vnode_pager_freepage(m[i]); @@ -786,13 +789,14 @@ vnode_pager_input(vnp, m, count, reqpage) } } return vnode_pager_input_old(vnp, m[reqpage]); - /* - * if the blocksize is smaller than a page size, then use - * special small filesystem code. NFS sometimes has a small - * blocksize, but it can handle large reads itself. - */ - } else if( (PAGE_SIZE / bsize) > 1 && - (vp->v_mount->mnt_stat.f_type != MOUNT_NFS)) { + + /* + * if the blocksize is smaller than a page size, then use + * special small filesystem code. NFS sometimes has a small + * blocksize, but it can handle large reads itself. + */ + } else if ((PAGE_SIZE / bsize) > 1 && + (vp->v_mount->mnt_stat.f_type != MOUNT_NFS)) { kmem_free_wakeup(pager_map, kva, mapsize); @@ -803,7 +807,6 @@ vnode_pager_input(vnp, m, count, reqpage) } return vnode_pager_input_smlfs(vnp, m[reqpage]); } - /* * here on direct device I/O */ @@ -811,12 +814,13 @@ vnode_pager_input(vnp, m, count, reqpage) /* * This pathetic hack gets data from the buffer cache, if it's there. - * I believe that this is not really necessary, and the ends can - * be gotten by defaulting to the normal vfs read behavior, but this + * I believe that this is not really necessary, and the ends can be + * gotten by defaulting to the normal vfs read behavior, but this * might be more efficient, because the will NOT invoke read-aheads - * and one of the purposes of this code is to bypass the buffer - * cache and keep from flushing it by reading in a program. + * and one of the purposes of this code is to bypass the buffer cache + * and keep from flushing it by reading in a program. */ + /* * calculate logical block and offset */ @@ -828,17 +832,16 @@ vnode_pager_input(vnp, m, count, reqpage) * if we have a buffer in core, then try to use it */ while (bp = incore(vp, block)) { - int amount; + int amount; - /* - * wait until the buffer is avail or gone - */ + /* + * wait until the buffer is avail or gone + */ if (bp->b_flags & B_BUSY) { bp->b_flags |= B_WANTED; - tsleep ((caddr_t)bp, PVM, "vnwblk", 0); + tsleep((caddr_t) bp, PVM, "vnwblk", 0); continue; } - amount = PAGE_SIZE; if ((foff + amount) > vnp->vnp_size) amount = vnp->vnp_size - foff; @@ -859,20 +862,23 @@ vnode_pager_input(vnp, m, count, reqpage) /* * copy the data from the buffer */ - bcopy(bp->b_un.b_addr + offset, (caddr_t)kva, amount); + bcopy(bp->b_un.b_addr + offset, (caddr_t) kva, amount); if (amount < PAGE_SIZE) { - bzero((caddr_t)kva + amount, PAGE_SIZE - amount); + bzero((caddr_t) kva + amount, PAGE_SIZE - amount); } + /* * unmap the page and free the kva */ pmap_remove(vm_map_pmap(pager_map), kva, kva + PAGE_SIZE); kmem_free_wakeup(pager_map, kva, mapsize); + /* * release the buffer back to the block subsystem */ bp->b_flags &= ~B_BUSY; - wakeup((caddr_t)bp); + wakeup((caddr_t) bp); + /* * we did not have to do any work to get the requested * page, the read behind/ahead does not justify a read @@ -891,6 +897,7 @@ vnode_pager_input(vnp, m, count, reqpage) */ goto finishup; } + /* * buffer is nowhere to be found, read from the disk */ @@ -900,18 +907,19 @@ vnode_pager_input(vnp, m, count, reqpage) reqaddr = vnode_pager_addr(vp, foff); s = splbio(); + /* - * Make sure that our I/O request is contiguous. - * Scan backward and stop for the first discontiguous - * entry or stop for a page being in buffer cache. + * Make sure that our I/O request is contiguous. Scan backward and + * stop for the first discontiguous entry or stop for a page being in + * buffer cache. */ failflag = 0; first = reqpage; for (i = reqpage - 1; i >= 0; --i) { if (failflag || - incore(vp, (foff + (i - reqpage) * PAGE_SIZE) / bsize) || - (vnode_pager_addr(vp, m[i]->offset + paging_offset)) - != reqaddr + (i - reqpage) * PAGE_SIZE) { + incore(vp, (foff + (i - reqpage) * PAGE_SIZE) / bsize) || + (vnode_pager_addr(vp, m[i]->offset + paging_offset)) + != reqaddr + (i - reqpage) * PAGE_SIZE) { vnode_pager_freepage(m[i]); failflag = 1; } else { @@ -920,16 +928,16 @@ vnode_pager_input(vnp, m, count, reqpage) } /* - * Scan forward and stop for the first non-contiguous - * entry or stop for a page being in buffer cache. + * Scan forward and stop for the first non-contiguous entry or stop + * for a page being in buffer cache. */ failflag = 0; last = reqpage + 1; for (i = reqpage + 1; i < count; i++) { if (failflag || - incore(vp, (foff + (i - reqpage) * PAGE_SIZE) / bsize) || - (vnode_pager_addr(vp, m[i]->offset + paging_offset)) - != reqaddr + (i - reqpage) * PAGE_SIZE) { + incore(vp, (foff + (i - reqpage) * PAGE_SIZE) / bsize) || + (vnode_pager_addr(vp, m[i]->offset + paging_offset)) + != reqaddr + (i - reqpage) * PAGE_SIZE) { vnode_pager_freepage(m[i]); failflag = 1; } else { @@ -939,8 +947,8 @@ vnode_pager_input(vnp, m, count, reqpage) splx(s); /* - * the first and last page have been calculated now, move input - * pages to be zero based... + * the first and last page have been calculated now, move input pages + * to be zero based... */ count = last; if (first != 0) { @@ -955,6 +963,7 @@ vnode_pager_input(vnp, m, count, reqpage) * calculate the file virtual address for the transfer */ foff = m[0]->offset + paging_offset; + /* * and get the disk physical address (in bytes) */ @@ -970,14 +979,14 @@ vnode_pager_input(vnp, m, count, reqpage) /* * round up physical size for real devices */ - if( dp->v_type == VBLK || dp->v_type == VCHR) + if (dp->v_type == VBLK || dp->v_type == VCHR) size = (size + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); /* * and map the pages to be read into the kva */ for (i = 0; i < count; i++) - pmap_kenter( kva + PAGE_SIZE * i, VM_PAGE_TO_PHYS(m[i])); + pmap_kenter(kva + PAGE_SIZE * i, VM_PAGE_TO_PHYS(m[i])); pmap_update(); bp = getpbuf(); @@ -989,9 +998,9 @@ vnode_pager_input(vnp, m, count, reqpage) /* B_PHYS is not set, but it is nice to fill this in */ bp->b_proc = curproc; bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred; - if( bp->b_rcred != NOCRED) + if (bp->b_rcred != NOCRED) crhold(bp->b_rcred); - if( bp->b_wcred != NOCRED) + if (bp->b_wcred != NOCRED) crhold(bp->b_wcred); bp->b_un.b_addr = (caddr_t) kva; bp->b_blkno = firstaddr / DEV_BSIZE; @@ -1006,7 +1015,7 @@ vnode_pager_input(vnp, m, count, reqpage) /* we definitely need to be at splbio here */ while ((bp->b_flags & B_DONE) == 0) { - tsleep((caddr_t)bp, PVM, "vnread", 0); + tsleep((caddr_t) bp, PVM, "vnread", 0); } splx(s); if ((bp->b_flags & B_ERROR) != 0) @@ -1014,9 +1023,8 @@ vnode_pager_input(vnp, m, count, reqpage) if (!error) { if (size != count * PAGE_SIZE) - bzero((caddr_t)kva + size, PAGE_SIZE * count - size); + bzero((caddr_t) kva + size, PAGE_SIZE * count - size); } - pmap_remove(vm_map_pmap(pager_map), kva, kva + PAGE_SIZE * count); kmem_free_wakeup(pager_map, kva, mapsize); @@ -1032,23 +1040,23 @@ vnode_pager_input(vnp, m, count, reqpage) m[i]->flags |= PG_CLEAN; m[i]->flags &= ~PG_LAUNDRY; if (i != reqpage) { + /* - * whether or not to leave the page activated - * is up in the air, but we should put the page - * on a page queue somewhere. (it already is in - * the object). - * Result: It appears that emperical results show - * that deactivating pages is best. + * whether or not to leave the page activated is up in + * the air, but we should put the page on a page queue + * somewhere. (it already is in the object). Result: + * It appears that emperical results show that + * deactivating pages is best. */ + /* - * just in case someone was asking for this - * page we now tell them that it is ok to use + * just in case someone was asking for this page we + * now tell them that it is ok to use */ if (!error) { vm_page_deactivate(m[i]); PAGE_WAKEUP(m[i]); m[i]->flags &= ~PG_FAKE; - m[i]->act_count = 2; } else { vnode_pager_freepage(m[i]); } @@ -1076,10 +1084,11 @@ vnode_pager_output_old(vnp, m) struct iovec aiov; struct uio auio; struct vnode *vp; - int error; + int error; vp = vnp->vnp_vp; foff = m->offset + m->object->paging_offset; + /* * Return failure if beyond current EOF */ @@ -1094,7 +1103,7 @@ vnode_pager_output_old(vnp, m) * we can use VOP_WRITE routines. */ kva = vm_pager_map_page(m); - aiov.iov_base = (caddr_t)kva; + aiov.iov_base = (caddr_t) kva; aiov.iov_len = size; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; @@ -1102,7 +1111,7 @@ vnode_pager_output_old(vnp, m) auio.uio_segflg = UIO_SYSSPACE; auio.uio_rw = UIO_WRITE; auio.uio_resid = size; - auio.uio_procp = (struct proc *)0; + auio.uio_procp = (struct proc *) 0; error = VOP_WRITE(vp, &auio, 0, curproc->p_ucred); @@ -1112,7 +1121,7 @@ vnode_pager_output_old(vnp, m) } } vm_pager_unmap_page(kva); - return error?VM_PAGER_FAIL:VM_PAGER_OK; + return error ? VM_PAGER_FAIL : VM_PAGER_OK; } } @@ -1124,19 +1133,18 @@ vnode_pager_output_smlfs(vnp, m) vn_pager_t vnp; vm_page_t m; { - int i; - int s; + int i; + int s; vm_offset_t paging_offset; struct vnode *dp, *vp; struct buf *bp; vm_offset_t mapsize; vm_offset_t foff; vm_offset_t kva; - int fileaddr; - int block; + int fileaddr; + int block; vm_offset_t bsize; - int run; - int error = 0; + int error = 0; paging_offset = m->object->paging_offset; vp = vnp->vnp_vp; @@ -1145,15 +1153,16 @@ vnode_pager_output_smlfs(vnp, m) VOP_BMAP(vp, foff, &dp, 0, 0); kva = vm_pager_map_page(m); - for(i = 0; !error && i < (PAGE_SIZE/bsize); i++) { - /* - * calculate logical block and offset - */ + for (i = 0; !error && i < (PAGE_SIZE / bsize); i++) { + + /* + * calculate logical block and offset + */ fileaddr = vnode_pager_addr(vp, foff + i * bsize); - if( fileaddr != -1) { + if (fileaddr != -1) { s = splbio(); - if( bp = incore( vp, (foff/bsize) + i)) { - bp = getblk(vp, (foff/bsize) + i, bp->b_bufsize,0, 0); + if (bp = incore(vp, (foff / bsize) + i)) { + bp = getblk(vp, (foff / bsize) + i, bp->b_bufsize, 0, 0); bp->b_flags |= B_INVAL; brelse(bp); } @@ -1162,47 +1171,47 @@ vnode_pager_output_smlfs(vnp, m) bp = getpbuf(); VHOLD(vp); - /* build a minimal buffer header */ + /* build a minimal buffer header */ bp->b_flags = B_BUSY | B_CALL | B_WRITE; bp->b_iodone = vnode_pager_iodone; bp->b_proc = curproc; bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred; - if( bp->b_rcred != NOCRED) + if (bp->b_rcred != NOCRED) crhold(bp->b_rcred); - if( bp->b_wcred != NOCRED) + if (bp->b_wcred != NOCRED) crhold(bp->b_wcred); bp->b_un.b_addr = (caddr_t) kva + i * bsize; bp->b_blkno = fileaddr / DEV_BSIZE; bgetvp(dp, bp); ++dp->v_numoutput; - /* for NFS */ + /* for NFS */ bp->b_dirtyoff = 0; bp->b_dirtyend = bsize; bp->b_bcount = bsize; bp->b_bufsize = bsize; - - /* do the input */ + + /* do the input */ VOP_STRATEGY(bp); - /* we definitely need to be at splbio here */ + /* we definitely need to be at splbio here */ s = splbio(); while ((bp->b_flags & B_DONE) == 0) { - tsleep((caddr_t)bp, PVM, "vnswrt", 0); + tsleep((caddr_t) bp, PVM, "vnswrt", 0); } splx(s); if ((bp->b_flags & B_ERROR) != 0) error = EIO; - /* - * free the buffer header back to the swap buffer pool - */ + /* + * free the buffer header back to the swap buffer pool + */ relpbuf(bp); HOLDRELE(vp); - } + } } vm_pager_unmap_page(kva); - if( error) + if (error) return VM_PAGER_FAIL; else return VM_PAGER_OK; @@ -1215,24 +1224,23 @@ int vnode_pager_output(vnp, m, count, rtvals) vn_pager_t vnp; vm_page_t *m; - int count; - int *rtvals; + int count; + int *rtvals; { - int i,j; + int i, j; vm_offset_t kva, foff; - int size; - struct proc *p = curproc; /* XXX */ + int size; + struct proc *p = curproc; /* XXX */ vm_object_t object; vm_offset_t paging_offset; struct vnode *dp, *vp; struct buf *bp; vm_offset_t mapsize; vm_offset_t reqaddr; - int run; - int bsize; - int s; + int bsize; + int s; - int error = 0; + int error = 0; retryoutput: object = m[0]->object; /* all vm_page_t items are in same object */ @@ -1241,14 +1249,13 @@ vnode_pager_output(vnp, m, count, rtvals) vp = vnp->vnp_vp; bsize = vp->v_mount->mnt_stat.f_iosize; - for(i=0;ioffset+paging_offset, &dp, 0, 0)) { + if (VOP_BMAP(vp, m[0]->offset + paging_offset, &dp, 0, 0)) { rtvals[0] = vnode_pager_output_old(vnp, m[0]); @@ -1259,15 +1266,15 @@ vnode_pager_output(vnp, m, count, rtvals) } /* - * if the filesystem has a small blocksize, then use - * the small block filesystem output code + * if the filesystem has a small blocksize, then use the small block + * filesystem output code */ if ((bsize < PAGE_SIZE) && - (vp->v_mount->mnt_stat.f_type != MOUNT_NFS)) { + (vp->v_mount->mnt_stat.f_type != MOUNT_NFS)) { - for(i=0;iflags |= PG_CLEAN; m[i]->flags &= ~PG_LAUNDRY; @@ -1279,18 +1286,17 @@ vnode_pager_output(vnp, m, count, rtvals) /* * get some kva for the output */ - kva = kmem_alloc_pageable(pager_map, (mapsize = count*PAGE_SIZE)); - if( !kva) { + kva = kmem_alloc_pageable(pager_map, (mapsize = count * PAGE_SIZE)); + if (!kva) { kva = kmem_alloc_pageable(pager_map, (mapsize = PAGE_SIZE)); count = 1; - if( !kva) + if (!kva) return rtvals[0]; } - - for(i=0;ioffset + paging_offset; if (foff >= vnp->vnp_size) { - for(j=i;joffset + paging_offset; reqaddr = vnode_pager_addr(vp, foff); + /* - * Scan forward and stop for the first non-contiguous - * entry or stop for a page being in buffer cache. + * Scan forward and stop for the first non-contiguous entry or stop + * for a page being in buffer cache. */ for (i = 1; i < count; i++) { - if ( vnode_pager_addr(vp, m[i]->offset + paging_offset) - != reqaddr + i * PAGE_SIZE) { + if (vnode_pager_addr(vp, m[i]->offset + paging_offset) + != reqaddr + i * PAGE_SIZE) { count = i; break; } @@ -1323,30 +1330,39 @@ vnode_pager_output(vnp, m, count, rtvals) /* * round up physical size for real devices */ - if( dp->v_type == VBLK || dp->v_type == VCHR) + if (dp->v_type == VBLK || dp->v_type == VCHR) size = (size + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1); /* * and map the pages to be read into the kva */ for (i = 0; i < count; i++) - pmap_kenter( kva + PAGE_SIZE * i, VM_PAGE_TO_PHYS(m[i])); + pmap_kenter(kva + PAGE_SIZE * i, VM_PAGE_TO_PHYS(m[i])); pmap_update(); /* printf("vnode: writing foff: %d, devoff: %d, size: %d\n", foff, reqaddr, size); */ + /* * next invalidate the incore vfs_bio data */ for (i = 0; i < count; i++) { - int filblock = (foff + i * PAGE_SIZE) / bsize; + int filblock = (foff + i * PAGE_SIZE) / bsize; struct buf *fbp; s = splbio(); - if( fbp = incore( vp, filblock)) { - /* printf("invalidating: %d\n", filblock); */ - fbp = getblk(vp, filblock, fbp->b_bufsize,0,0); + if (fbp = incore(vp, filblock)) { + fbp = getblk(vp, filblock, fbp->b_bufsize, 0, 0); + if (fbp->b_flags & B_DELWRI) { + if (fbp->b_bufsize <= PAGE_SIZE) + fbp->b_flags &= ~B_DELWRI; + else { + bwrite(fbp); + fbp = getblk(vp, filblock, + fbp->b_bufsize, 0, 0); + } + } fbp->b_flags |= B_INVAL; brelse(fbp); } @@ -1363,15 +1379,15 @@ vnode_pager_output(vnp, m, count, rtvals) bp->b_proc = curproc; bp->b_rcred = bp->b_wcred = bp->b_proc->p_ucred; - if( bp->b_rcred != NOCRED) + if (bp->b_rcred != NOCRED) crhold(bp->b_rcred); - if( bp->b_wcred != NOCRED) + if (bp->b_wcred != NOCRED) crhold(bp->b_wcred); bp->b_un.b_addr = (caddr_t) kva; bp->b_blkno = reqaddr / DEV_BSIZE; bgetvp(dp, bp); ++dp->v_numoutput; - + /* for NFS */ bp->b_dirtyoff = 0; bp->b_dirtyend = size; @@ -1387,7 +1403,7 @@ vnode_pager_output(vnp, m, count, rtvals) /* we definitely need to be at splbio here */ while ((bp->b_flags & B_DONE) == 0) { - tsleep((caddr_t)bp, PVM, "vnwrite", 0); + tsleep((caddr_t) bp, PVM, "vnwrite", 0); } splx(s); @@ -1403,22 +1419,20 @@ vnode_pager_output(vnp, m, count, rtvals) relpbuf(bp); HOLDRELE(vp); - if( !error) { - for(i=0;iflags |= PG_CLEAN; m[i]->flags &= ~PG_LAUNDRY; rtvals[i] = VM_PAGER_OK; } - } else if( count != 1) { + } else if (count != 1) { error = 0; count = 1; goto retryoutput; } - if (error) { printf("vnode pager write error: %d\n", error); } return (error ? VM_PAGER_FAIL : VM_PAGER_OK); } -