summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/vfs_bio.c9
-rw-r--r--sys/kern/vfs_export.c59
-rw-r--r--sys/kern/vfs_subr.c59
-rw-r--r--sys/kern/vfs_vnops.c6
-rw-r--r--sys/sys/vnode.h12
-rw-r--r--sys/vm/vm_fault.c4
-rw-r--r--sys/vm/vm_map.c154
-rw-r--r--sys/vm/vm_object.c4
-rw-r--r--sys/vm/vm_page.c20
-rw-r--r--sys/vm/vm_pageout.c40
-rw-r--r--sys/vm/vm_pageout.h3
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
OpenPOWER on IntegriCloud