diff options
-rw-r--r-- | sys/kern/vfs_bio.c | 9 | ||||
-rw-r--r-- | sys/kern/vfs_export.c | 59 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 59 | ||||
-rw-r--r-- | sys/kern/vfs_vnops.c | 6 | ||||
-rw-r--r-- | sys/sys/vnode.h | 12 | ||||
-rw-r--r-- | sys/vm/vm_fault.c | 4 | ||||
-rw-r--r-- | sys/vm/vm_map.c | 154 | ||||
-rw-r--r-- | sys/vm/vm_object.c | 4 | ||||
-rw-r--r-- | sys/vm/vm_page.c | 20 | ||||
-rw-r--r-- | sys/vm/vm_pageout.c | 40 | ||||
-rw-r--r-- | sys/vm/vm_pageout.h | 3 |
11 files changed, 291 insertions, 79 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 98cf7aa..5a1633a 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -11,7 +11,7 @@ * 2. Absolutely no warranty of function or purpose is made by the author * John S. Dyson. * - * $Id: vfs_bio.c,v 1.140 1997/12/22 11:54:00 dyson Exp $ + * $Id: vfs_bio.c,v 1.141 1998/01/06 05:15:55 dyson Exp $ */ /* @@ -789,8 +789,15 @@ vfs_vmio_release(bp) else vm_page_deactivate(m); } else if (m->hold_count == 0) { + struct vnode *vp; + vp = bp->b_vp; vm_page_protect(m, VM_PROT_NONE); vm_page_free(m); + if (vp && VSHOULDFREE(vp) && + (vp->v_flag & (VFREE|VTBFREE)) == 0) { + TAILQ_INSERT_TAIL(&vnode_tobefree_list, vp, v_freelist); + vp->v_flag |= VTBFREE; + } } } else { /* diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c index ce2b9e1..90f2144 100644 --- a/sys/kern/vfs_export.c +++ b/sys/kern/vfs_export.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95 - * $Id: vfs_subr.c,v 1.120 1998/01/06 05:16:18 dyson Exp $ + * $Id: vfs_subr.c,v 1.121 1998/01/07 09:26:29 dyson Exp $ */ /* @@ -101,13 +101,16 @@ int vttoif_tab[9] = { LIST_REMOVE(bp, b_vnbufs); \ (bp)->b_vnbufs.le_next = NOLIST; \ } + TAILQ_HEAD(freelst, vnode) vnode_free_list; /* vnode free list */ +struct tobefreelist vnode_tobefree_list; /* vnode free list */ + static u_long wantfreevnodes = 25; SYSCTL_INT(_debug, OID_AUTO, wantfreevnodes, CTLFLAG_RW, &wantfreevnodes, 0, ""); static u_long freevnodes = 0; SYSCTL_INT(_debug, OID_AUTO, freevnodes, CTLFLAG_RD, &freevnodes, 0, ""); -int vfs_ioopt = 0; +int vfs_ioopt = 2; SYSCTL_INT(_vfs, OID_AUTO, ioopt, CTLFLAG_RW, &vfs_ioopt, 0, ""); struct mntlist mountlist; /* mounted filesystem list */ @@ -138,6 +141,7 @@ vntblinit() simple_lock_init(&mntid_slock); simple_lock_init(&spechash_slock); TAILQ_INIT(&vnode_free_list); + TAILQ_INIT(&vnode_tobefree_list); simple_lock_init(&vnode_free_list_slock); CIRCLEQ_INIT(&mountlist); } @@ -350,8 +354,9 @@ getnewvnode(tag, mp, vops, vpp) vop_t **vops; struct vnode **vpp; { + int s; struct proc *p = curproc; /* XXX */ - struct vnode *vp, *tvp; + struct vnode *vp, *tvp, *nvp; vm_object_t object; TAILQ_HEAD(freelst, vnode) vnode_tmp_list; @@ -362,9 +367,16 @@ getnewvnode(tag, mp, vops, vpp) * Otherwise we allocate a new vnode */ + s = splbio(); simple_lock(&vnode_free_list_slock); TAILQ_INIT(&vnode_tmp_list); + for (vp = TAILQ_FIRST(&vnode_tobefree_list); vp; vp = nvp) { + nvp = TAILQ_NEXT(vp, v_freelist); + vp->v_flag &= ~VTBFREE; + TAILQ_INSERT_TAIL(&vnode_tmp_list, vp, v_freelist); + } + if (wantfreevnodes && freevnodes < wantfreevnodes) { vp = NULL; } else if (!wantfreevnodes && freevnodes <= desiredvnodes) { @@ -373,7 +385,10 @@ getnewvnode(tag, mp, vops, vpp) */ vp = NULL; } else { - TAILQ_FOREACH(vp, &vnode_free_list, v_freelist) { + for (vp = TAILQ_FIRST(&vnode_free_list); vp; vp = nvp) { + + nvp = TAILQ_NEXT(vp, v_freelist); + if (!simple_lock_try(&vp->v_interlock)) continue; if (vp->v_usecount) @@ -395,7 +410,8 @@ getnewvnode(tag, mp, vops, vpp) } } - TAILQ_FOREACH(tvp, &vnode_tmp_list, v_freelist) { + for (tvp = TAILQ_FIRST(&vnode_tmp_list); tvp; tvp = nvp) { + nvp = TAILQ_NEXT(tvp, v_freelist); TAILQ_REMOVE(&vnode_tmp_list, tvp, v_freelist); TAILQ_INSERT_TAIL(&vnode_free_list, tvp, v_freelist); simple_unlock(&tvp->v_interlock); @@ -454,6 +470,7 @@ getnewvnode(tag, mp, vops, vpp) *vpp = vp; vp->v_usecount = 1; vp->v_data = 0; + splx(s); return (0); } @@ -1341,6 +1358,7 @@ vgonel(vp, p) struct vnode *vp; struct proc *p; { + int s; struct vnode *vq; struct vnode *vx; @@ -1415,10 +1433,18 @@ vgonel(vp, p) * close the previous instance of the underlying object. */ if (vp->v_usecount == 0 && !(vp->v_flag & VDOOMED)) { + s = splbio(); simple_lock(&vnode_free_list_slock); - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + if (vp->v_flag & VFREE) { + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + } else if (vp->v_flag & VTBFREE) { + TAILQ_REMOVE(&vnode_tobefree_list, vp, v_freelist); + vp->v_flag &= ~VTBFREE; + } + vp->v_flag |= VFREE; TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); simple_unlock(&vnode_free_list_slock); + splx(s); } vp->v_type = VBAD; @@ -2138,7 +2164,14 @@ static void vfree(vp) struct vnode *vp; { + int s; + + s = splbio(); simple_lock(&vnode_free_list_slock); + if (vp->v_flag & VTBFREE) { + TAILQ_REMOVE(&vnode_tobefree_list, vp, v_freelist); + vp->v_flag &= ~VTBFREE; + } if (vp->v_flag & VAGE) { TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); } else { @@ -2148,17 +2181,27 @@ vfree(vp) simple_unlock(&vnode_free_list_slock); vp->v_flag &= ~VAGE; vp->v_flag |= VFREE; + splx(s); } static void vbusy(vp) struct vnode *vp; { + int s; + + s = splbio(); simple_lock(&vnode_free_list_slock); - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); - freevnodes--; + if (vp->v_flag & VTBFREE) { + TAILQ_REMOVE(&vnode_tobefree_list, vp, v_freelist); + vp->v_flag &= ~VTBFREE; + } else { + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + freevnodes--; + } simple_unlock(&vnode_free_list_slock); vp->v_flag &= ~VFREE; + splx(s); } /* diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index ce2b9e1..90f2144 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95 - * $Id: vfs_subr.c,v 1.120 1998/01/06 05:16:18 dyson Exp $ + * $Id: vfs_subr.c,v 1.121 1998/01/07 09:26:29 dyson Exp $ */ /* @@ -101,13 +101,16 @@ int vttoif_tab[9] = { LIST_REMOVE(bp, b_vnbufs); \ (bp)->b_vnbufs.le_next = NOLIST; \ } + TAILQ_HEAD(freelst, vnode) vnode_free_list; /* vnode free list */ +struct tobefreelist vnode_tobefree_list; /* vnode free list */ + static u_long wantfreevnodes = 25; SYSCTL_INT(_debug, OID_AUTO, wantfreevnodes, CTLFLAG_RW, &wantfreevnodes, 0, ""); static u_long freevnodes = 0; SYSCTL_INT(_debug, OID_AUTO, freevnodes, CTLFLAG_RD, &freevnodes, 0, ""); -int vfs_ioopt = 0; +int vfs_ioopt = 2; SYSCTL_INT(_vfs, OID_AUTO, ioopt, CTLFLAG_RW, &vfs_ioopt, 0, ""); struct mntlist mountlist; /* mounted filesystem list */ @@ -138,6 +141,7 @@ vntblinit() simple_lock_init(&mntid_slock); simple_lock_init(&spechash_slock); TAILQ_INIT(&vnode_free_list); + TAILQ_INIT(&vnode_tobefree_list); simple_lock_init(&vnode_free_list_slock); CIRCLEQ_INIT(&mountlist); } @@ -350,8 +354,9 @@ getnewvnode(tag, mp, vops, vpp) vop_t **vops; struct vnode **vpp; { + int s; struct proc *p = curproc; /* XXX */ - struct vnode *vp, *tvp; + struct vnode *vp, *tvp, *nvp; vm_object_t object; TAILQ_HEAD(freelst, vnode) vnode_tmp_list; @@ -362,9 +367,16 @@ getnewvnode(tag, mp, vops, vpp) * Otherwise we allocate a new vnode */ + s = splbio(); simple_lock(&vnode_free_list_slock); TAILQ_INIT(&vnode_tmp_list); + for (vp = TAILQ_FIRST(&vnode_tobefree_list); vp; vp = nvp) { + nvp = TAILQ_NEXT(vp, v_freelist); + vp->v_flag &= ~VTBFREE; + TAILQ_INSERT_TAIL(&vnode_tmp_list, vp, v_freelist); + } + if (wantfreevnodes && freevnodes < wantfreevnodes) { vp = NULL; } else if (!wantfreevnodes && freevnodes <= desiredvnodes) { @@ -373,7 +385,10 @@ getnewvnode(tag, mp, vops, vpp) */ vp = NULL; } else { - TAILQ_FOREACH(vp, &vnode_free_list, v_freelist) { + for (vp = TAILQ_FIRST(&vnode_free_list); vp; vp = nvp) { + + nvp = TAILQ_NEXT(vp, v_freelist); + if (!simple_lock_try(&vp->v_interlock)) continue; if (vp->v_usecount) @@ -395,7 +410,8 @@ getnewvnode(tag, mp, vops, vpp) } } - TAILQ_FOREACH(tvp, &vnode_tmp_list, v_freelist) { + for (tvp = TAILQ_FIRST(&vnode_tmp_list); tvp; tvp = nvp) { + nvp = TAILQ_NEXT(tvp, v_freelist); TAILQ_REMOVE(&vnode_tmp_list, tvp, v_freelist); TAILQ_INSERT_TAIL(&vnode_free_list, tvp, v_freelist); simple_unlock(&tvp->v_interlock); @@ -454,6 +470,7 @@ getnewvnode(tag, mp, vops, vpp) *vpp = vp; vp->v_usecount = 1; vp->v_data = 0; + splx(s); return (0); } @@ -1341,6 +1358,7 @@ vgonel(vp, p) struct vnode *vp; struct proc *p; { + int s; struct vnode *vq; struct vnode *vx; @@ -1415,10 +1433,18 @@ vgonel(vp, p) * close the previous instance of the underlying object. */ if (vp->v_usecount == 0 && !(vp->v_flag & VDOOMED)) { + s = splbio(); simple_lock(&vnode_free_list_slock); - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + if (vp->v_flag & VFREE) { + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + } else if (vp->v_flag & VTBFREE) { + TAILQ_REMOVE(&vnode_tobefree_list, vp, v_freelist); + vp->v_flag &= ~VTBFREE; + } + vp->v_flag |= VFREE; TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); simple_unlock(&vnode_free_list_slock); + splx(s); } vp->v_type = VBAD; @@ -2138,7 +2164,14 @@ static void vfree(vp) struct vnode *vp; { + int s; + + s = splbio(); simple_lock(&vnode_free_list_slock); + if (vp->v_flag & VTBFREE) { + TAILQ_REMOVE(&vnode_tobefree_list, vp, v_freelist); + vp->v_flag &= ~VTBFREE; + } if (vp->v_flag & VAGE) { TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); } else { @@ -2148,17 +2181,27 @@ vfree(vp) simple_unlock(&vnode_free_list_slock); vp->v_flag &= ~VAGE; vp->v_flag |= VFREE; + splx(s); } static void vbusy(vp) struct vnode *vp; { + int s; + + s = splbio(); simple_lock(&vnode_free_list_slock); - TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); - freevnodes--; + if (vp->v_flag & VTBFREE) { + TAILQ_REMOVE(&vnode_tobefree_list, vp, v_freelist); + vp->v_flag &= ~VTBFREE; + } else { + TAILQ_REMOVE(&vnode_free_list, vp, v_freelist); + freevnodes--; + } simple_unlock(&vnode_free_list_slock); vp->v_flag &= ~VFREE; + splx(s); } /* diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index c4b8d66..f47de68 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_vnops.c 8.2 (Berkeley) 1/21/94 - * $Id: vfs_vnops.c,v 1.45 1997/12/29 01:03:43 dyson Exp $ + * $Id: vfs_vnops.c,v 1.46 1998/01/06 05:16:32 dyson Exp $ */ #include <sys/param.h> @@ -511,9 +511,7 @@ vn_lock(vp, flags, p) if (vp->v_flag & VXLOCK) { vp->v_flag |= VXWANT; simple_unlock(&vp->v_interlock); - if (tsleep((caddr_t)vp, PINOD, "vn_lock", 120*hz)) { - vprint("vn_lock: timeout:", vp); - } + tsleep((caddr_t)vp, PINOD, "vn_lock", 0); error = ENOENT; } else { error = VOP_LOCK(vp, flags | LK_NOPAUSE | LK_INTERLOCK, p); diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index fa70aae..cc4fa03 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)vnode.h 8.7 (Berkeley) 2/4/94 - * $Id: vnode.h,v 1.62 1997/12/29 16:53:53 dyson Exp $ + * $Id: vnode.h,v 1.63 1998/01/06 05:23:04 dyson Exp $ */ #ifndef _SYS_VNODE_H_ @@ -153,6 +153,7 @@ struct vnode { #define VOWANT 0x20000 /* a process is waiting for VOLOCK */ #define VDOOMED 0x40000 /* This vnode is being recycled */ #define VFREE 0x80000 /* This vnode is on the freelist */ +#define VTBFREE 0x100000 /* This vnode is no the to be freelist */ /* * Vnode attributes. A field value of VNOVAL represents a field whose value @@ -275,13 +276,14 @@ extern void (*lease_updatetime) __P((int deltat)); #define VSHOULDFREE(vp) \ (!((vp)->v_flag & (VFREE|VDOOMED)) && \ - !(vp)->v_holdcnt && !(vp)->v_usecount) + !(vp)->v_holdcnt && !(vp)->v_usecount && \ + (!(vp)->v_object || \ + !((vp)->v_object->ref_count || (vp)->v_object->resident_page_count))) #define VSHOULDBUSY(vp) \ (((vp)->v_flag & VFREE) && \ ((vp)->v_holdcnt || (vp)->v_usecount)) - #endif /* KERNEL */ @@ -525,6 +527,10 @@ void vrele __P((struct vnode *vp)); void vref __P((struct vnode *vp)); extern vop_t **default_vnodeop_p; + +extern TAILQ_HEAD(tobefreelist, vnode) + vnode_tobefree_list; /* vnode free list */ + #endif /* KERNEL */ #endif /* !_SYS_VNODE_H_ */ diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index f45d377..2185e33 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -66,7 +66,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_fault.c,v 1.72 1997/12/19 09:03:10 dyson Exp $ + * $Id: vm_fault.c,v 1.73 1998/01/06 05:25:54 dyson Exp $ */ /* @@ -523,8 +523,10 @@ readrest: } } +#if defined(DIAGNOSTIC) if ((m->flags & PG_BUSY) == 0) panic("vm_fault: not busy after main loop"); +#endif /* * PAGE HAS BEEN FOUND. [Loop invariant still holds -- the object lock diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 17b0e75..67039d4 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_map.c,v 1.103 1997/12/29 01:03:34 dyson Exp $ + * $Id: vm_map.c,v 1.104 1998/01/06 05:25:58 dyson Exp $ */ /* @@ -2405,7 +2405,7 @@ RetryLookup:; vm_map_lock_downgrade(share_map); } - if (entry->object.vm_object != NULL) + if (entry->object.vm_object->type == OBJT_DEFAULT) default_pager_convert_to_swapq(entry->object.vm_object); /* * Return the object/offset from this entry. If the entry was @@ -2479,16 +2479,20 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages) vm_offset_t uaddr, start, end; vm_pindex_t first_pindex, osize, oindex; off_t ooffset; + int skipinit, allremoved; if (npages) *npages = 0; + allremoved = 0; + while (cnt > 0) { map = mapa; uaddr = uaddra; + skipinit = 0; if ((vm_map_lookup(&map, uaddr, - VM_PROT_READ|VM_PROT_WRITE, &first_entry, &first_object, + VM_PROT_READ, &first_entry, &first_object, &first_pindex, &prot, &wired, &su)) != KERN_SUCCESS) { return EFAULT; } @@ -2506,17 +2510,16 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages) osize = atop(tcnt); + oindex = OFF_TO_IDX(cp); if (npages) { - vm_pindex_t src_index, idx; - src_index = OFF_TO_IDX(cp); + vm_pindex_t idx; for (idx = 0; idx < osize; idx++) { vm_page_t m; - if ((m = vm_page_lookup(srcobject, src_index + idx)) == NULL) { + if ((m = vm_page_lookup(srcobject, oindex + idx)) == NULL) { vm_map_lookup_done(map, first_entry); return 0; } - if ((m->flags & PG_BUSY) || m->busy || - m->hold_count || m->wire_count || + if ((m->flags & PG_BUSY) || ((m->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL)) { vm_map_lookup_done(map, first_entry); return 0; @@ -2524,46 +2527,113 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages) } } - oindex = OFF_TO_IDX(first_entry->offset); - /* * If we are changing an existing map entry, just redirect * the object, and change mappings. */ - if ((first_object->ref_count == 1) && - (first_object->backing_object == srcobject) && + if (first_object->type == OBJT_VNODE) { + + if (first_object != srcobject) { + + vm_object_deallocate(first_object); + srcobject->flags |= OBJ_OPT; + vm_object_reference(srcobject); + + first_entry->object.vm_object = srcobject; + first_entry->offset = cp; + + } else if (first_entry->offset != cp) { + + first_entry->offset = cp; + + } else { + + skipinit = 1; + + } + + if (skipinit == 0) { + /* + * Remove old window into the file + */ + if (!allremoved) { + pmap_remove (map->pmap, uaddra, uaddra + cnt); + allremoved = 1; + } + + /* + * Force copy on write for mmaped regions + */ + vm_object_pmap_copy_1 (srcobject, + oindex, oindex + osize); + } + + } else if ((first_object->ref_count == 1) && (first_object->size == osize) && (first_object->resident_page_count == 0)) { + vm_object_t oldobject; - /* - * Remove old window into the file - */ - pmap_remove (map->pmap, start, end); + oldobject = first_object->backing_object; - /* - * Force copy on write for mmaped regions - */ - vm_object_pmap_copy_1 (first_object, - oindex, oindex + osize); + if ((first_object->backing_object_offset != cp) || + (oldobject != srcobject)) { + /* + * Remove old window into the file + */ + if (!allremoved) { + pmap_remove (map->pmap, uaddra, uaddra + cnt); + allremoved = 1; + } - /* - * Point the object appropriately - */ - first_object->backing_object_offset = cp; + /* + * Force copy on write for mmaped regions + */ + vm_object_pmap_copy_1 (srcobject, + oindex, oindex + osize); + + /* + * Point the object appropriately + */ + if (oldobject != srcobject) { + /* + * Set the object optimization hint flag + */ + srcobject->flags |= OBJ_OPT; + vm_object_reference(srcobject); + + if (oldobject) { + TAILQ_REMOVE(&oldobject->shadow_head, + first_object, shadow_list); + oldobject->shadow_count--; + if (oldobject->shadow_count == 0) + oldobject->flags &= ~OBJ_OPT; + vm_object_deallocate(oldobject); + } + + TAILQ_INSERT_TAIL(&srcobject->shadow_head, + first_object, shadow_list); + srcobject->shadow_count++; + + first_object->backing_object = srcobject; + } + + first_object->backing_object_offset = cp; + } else { + skipinit = 1; + } /* * Otherwise, we have to do a logical mmap. */ } else { - object = srcobject; - object->flags |= OBJ_OPT; - vm_object_reference(object); - ooffset = cp; - - vm_object_shadow(&object, &ooffset, osize); + srcobject->flags |= OBJ_OPT; + vm_object_reference(srcobject); - pmap_remove (map->pmap, start, end); - vm_object_pmap_copy_1 (first_object, + if (!allremoved) { + pmap_remove (map->pmap, uaddra, uaddra + cnt); + allremoved = 1; + } + vm_object_pmap_copy_1 (srcobject, oindex, oindex + osize); vm_map_lookup_done(map, first_entry); @@ -2578,8 +2648,8 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages) SAVE_HINT(map, first_entry->prev); vm_map_entry_delete(map, first_entry); - rv = vm_map_insert(map, object, 0, start, end, - VM_PROT_ALL, VM_PROT_ALL, MAP_COPY_ON_WRITE); + rv = vm_map_insert(map, srcobject, cp, start, end, + VM_PROT_ALL, VM_PROT_ALL, MAP_COPY_ON_WRITE | MAP_COPY_NEEDED); if (rv != KERN_SUCCESS) panic("vm_uiomove: could not insert new entry: %d", rv); @@ -2588,8 +2658,9 @@ vm_uiomove(mapa, srcobject, cp, cnt, uaddra, npages) /* * Map the window directly, if it is already in memory */ - pmap_object_init_pt(map->pmap, start, - srcobject, (vm_pindex_t) OFF_TO_IDX(cp), end - start, 1); + if (!skipinit) + pmap_object_init_pt(map->pmap, start, + srcobject, (vm_pindex_t) OFF_TO_IDX(cp), end - start, 0); vm_map_unlock(map); @@ -2663,10 +2734,14 @@ vm_freeze_copyopts(object, froma, toa) continue; vm_object_reference(robject); + + s = splvm(); while (robject->paging_in_progress) { robject->flags |= OBJ_PIPWNT; tsleep(robject, PVM, "objfrz", 0); } + splx(s); + if (robject->ref_count == 1) { vm_object_deallocate(robject); continue; @@ -2690,7 +2765,7 @@ vm_freeze_copyopts(object, froma, toa) continue; if( m_in->flags & PG_BUSY) { - s = splhigh(); + s = splvm(); while (m_in && (m_in->flags & PG_BUSY)) { m_in->flags |= PG_WANTED; tsleep(m_in, PVM, "pwtfrz", 0); @@ -2705,7 +2780,7 @@ vm_freeze_copyopts(object, froma, toa) retryout: m_out = vm_page_lookup(robject, dstpindex); if( m_out && (m_out->flags & PG_BUSY)) { - s = splhigh(); + s = splvm(); while (m_out && (m_out->flags & PG_BUSY)) { m_out->flags |= PG_WANTED; tsleep(m_out, PVM, "pwtfrz", 0); @@ -2733,6 +2808,7 @@ retryout: vm_object_pip_wakeup(robject); if (((from - bo_pindex) == 0) && ((to - bo_pindex) == robject->size)) { + object->shadow_count--; TAILQ_REMOVE(&object->shadow_head, robject, shadow_list); diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 7885534..33ec0a1 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_object.c,v 1.104 1998/01/06 05:26:04 dyson Exp $ + * $Id: vm_object.c,v 1.105 1998/01/07 03:12:19 dyson Exp $ */ /* @@ -332,12 +332,14 @@ vm_object_deallocate(object) if (robject->paging_in_progress) { robject->flags |= OBJ_PIPWNT; tsleep(robject, PVM, "objde1", 0); + splx(s); goto retry; } if (object->paging_in_progress) { object->flags |= OBJ_PIPWNT; tsleep(object, PVM, "objde2", 0); + splx(s); goto retry; } splx(s); diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 3b36526..ff824d6 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)vm_page.c 7.4 (Berkeley) 5/7/91 - * $Id: vm_page.c,v 1.83 1997/11/06 08:35:50 dyson Exp $ + * $Id: vm_page.c,v 1.84 1997/12/29 00:24:58 dyson Exp $ */ /* @@ -753,6 +753,7 @@ vm_page_alloc(object, pindex, page_req) { register vm_page_t m; struct vpgqueues *pq; + vm_object_t oldobject; int queue, qtype; int s; @@ -861,9 +862,11 @@ vm_page_alloc(object, pindex, page_req) TAILQ_REMOVE(pq->pl, m, pageq); --(*pq->cnt); --(*pq->lcnt); + oldobject = NULL; if (qtype == PQ_ZERO) { m->flags = PG_ZERO|PG_BUSY; } else if (qtype == PQ_CACHE) { + oldobject = m->object; vm_page_remove(m); m->flags = PG_BUSY; } else { @@ -891,6 +894,19 @@ vm_page_alloc(object, pindex, page_req) (cnt.v_free_count < cnt.v_pageout_free_min)) pagedaemon_wakeup(); + if (((page_req == VM_ALLOC_NORMAL) || (page_req == VM_ALLOC_ZERO)) && + oldobject && + ((oldobject->type == OBJT_VNODE) && + (oldobject->ref_count == 0) && + (oldobject->resident_page_count == 0))) { + struct vnode *vp; + vp = (struct vnode *) oldobject->handle; + if (VSHOULDFREE(vp)) { + vm_object_reference(oldobject); + vm_object_vndeallocate(oldobject); + } + } + return (m); } @@ -954,6 +970,7 @@ static int vm_page_freechk_and_unqueue(m) vm_page_t m; { +#if !defined(MAX_PERF) if (m->busy || (m->flags & PG_BUSY) || ((m->queue - m->pc) == PQ_FREE) || @@ -966,6 +983,7 @@ vm_page_freechk_and_unqueue(m) else panic("vm_page_free: freeing busy page"); } +#endif vm_page_remove(m); vm_page_unqueue_nowakeup(m); diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index eda7f30..b5669fd 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.105 1997/12/29 00:25:03 dyson Exp $ + * $Id: vm_pageout.c,v 1.106 1998/01/06 05:26:11 dyson Exp $ */ /* @@ -382,10 +382,10 @@ vm_pageout_flush(mc, count, sync) switch (pageout_status[i]) { case VM_PAGER_OK: - ++anyok; + anyok++; break; case VM_PAGER_PEND: - ++anyok; + anyok++; break; case VM_PAGER_BAD: /* @@ -592,6 +592,23 @@ vm_pageout_map_deactivate_pages(map, desired) } #endif +void +vm_pageout_page_free(vm_page_t m) { + vm_object_t objref = NULL; + + m->flags |= PG_BUSY; + if (m->object->type == OBJT_VNODE) { + objref = m->object; + vm_object_reference(objref); + } + vm_page_protect(m, VM_PROT_NONE); + PAGE_WAKEUP(m); + vm_page_free(m); + if (objref) { + vm_object_vndeallocate(objref); + } +} + /* * vm_pageout_scan does the dirty work for the pageout daemon. */ @@ -716,17 +733,16 @@ rescan0: * Invalid pages can be easily freed */ if (m->valid == 0) { - vm_page_protect(m, VM_PROT_NONE); - vm_page_free(m); + vm_pageout_page_free(m); cnt.v_dfree++; - ++pages_freed; + pages_freed++; /* * Clean pages can be placed onto the cache queue. */ } else if (m->dirty == 0) { vm_page_cache(m); - ++pages_freed; + pages_freed++; /* * Dirty pages need to be paged out. Note that we clean @@ -774,7 +790,7 @@ rescan0: splx(s); } if (object->flags & OBJ_MIGHTBEDIRTY) - ++vnodes_skipped; + vnodes_skipped++; continue; } @@ -784,7 +800,7 @@ rescan0: */ if (m->queue != PQ_INACTIVE) { if (object->flags & OBJ_MIGHTBEDIRTY) - ++vnodes_skipped; + vnodes_skipped++; vput(vp); continue; } @@ -808,7 +824,7 @@ rescan0: TAILQ_INSERT_TAIL(&vm_page_queue_inactive, m, pageq); splx(s); if (object->flags & OBJ_MIGHTBEDIRTY) - ++vnodes_skipped; + vnodes_skipped++; vput(vp); continue; } @@ -922,7 +938,7 @@ rescan0: m->act_count -= min(m->act_count, ACT_DECLINE); if (vm_pageout_algorithm_lru || (m->object->ref_count == 0) || (m->act_count == 0)) { - --page_shortage; + page_shortage--; if (m->object->ref_count == 0) { vm_page_protect(m, VM_PROT_NONE); if (m->dirty == 0) @@ -953,7 +969,7 @@ rescan0: if (!m) break; cache_rover = (cache_rover + PQ_PRIME2) & PQ_L2_MASK; - vm_page_free(m); + vm_pageout_page_free(m); cnt.v_dfree++; } splx(s); diff --git a/sys/vm/vm_pageout.h b/sys/vm/vm_pageout.h index ab2608a..4a61d12 100644 --- a/sys/vm/vm_pageout.h +++ b/sys/vm/vm_pageout.h @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_pageout.h,v 1.20 1997/02/22 09:48:34 peter Exp $ + * $Id: vm_pageout.h,v 1.21 1997/12/06 02:23:36 dyson Exp $ */ #ifndef _VM_VM_PAGEOUT_H_ @@ -105,6 +105,7 @@ extern void vm_wait __P((void)); void vm_pageout_page __P((vm_page_t, vm_object_t)); void vm_pageout_cluster __P((vm_page_t, vm_object_t)); int vm_pageout_flush __P((vm_page_t *, int, int)); +void vm_pageout_page_free __P((vm_page_t)); #endif |