summaryrefslogtreecommitdiffstats
path: root/sys/vm/vnode_pager.c
diff options
context:
space:
mode:
authordg <dg@FreeBSD.org>1995-07-06 11:48:48 +0000
committerdg <dg@FreeBSD.org>1995-07-06 11:48:48 +0000
commit21036bccfd267479c2ca00a9753138d46d94d41e (patch)
treece873fc5ea1381810ca2b25a516e0da6f4c2366b /sys/vm/vnode_pager.c
parentfa8de9933bb206fd1d26887990a414aa1b781904 (diff)
downloadFreeBSD-src-21036bccfd267479c2ca00a9753138d46d94d41e.zip
FreeBSD-src-21036bccfd267479c2ca00a9753138d46d94d41e.tar.gz
Fixed an object allocation race condition that was causing a "object
deallocated too many times" panic when using NFS. Reviewed by: John Dyson
Diffstat (limited to 'sys/vm/vnode_pager.c')
-rw-r--r--sys/vm/vnode_pager.c47
1 files changed, 34 insertions, 13 deletions
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index ed785f9..b29b4ff 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.40 1995/05/30 08:16:23 rgrimes Exp $
+ * $Id: vnode_pager.c,v 1.41 1995/06/28 12:01:13 davidg Exp $
*/
/*
@@ -136,13 +136,23 @@ vnode_pager_alloc(handle, size, prot, offset)
if (handle == NULL)
return (NULL);
+ vp = (struct vnode *) handle;
+
/*
- * Vnodes keep a pointer to any associated pager so no need to lookup
- * with vm_pager_lookup.
+ * Prevent race condition when allocating the object. This
+ * can happen with NFS vnodes since the nfsnode isn't locked.
*/
- vp = (struct vnode *) handle;
- while ((object = vp->v_object) &&
- (object->flags & OBJ_DEAD))
+ while (vp->v_flag & VOLOCK) {
+ vp->v_flag |= VOWANT;
+ tsleep(vp, PVM, "vnpobj", 0);
+ }
+ vp->v_flag |= VOLOCK;
+
+ /*
+ * If the object is being terminated, wait for it to
+ * go away.
+ */
+ while (((object = vp->v_object) != NULL) && (object->flags & OBJ_DEAD))
tsleep(object, PVM, "vadead", 0);
pager = NULL;
@@ -154,13 +164,8 @@ vnode_pager_alloc(handle, size, prot, offset)
* Allocate pager structures
*/
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);
- if (vnp == NULL) {
- free((caddr_t) pager, M_VMPAGER);
- return (NULL);
- }
+
/*
* And an object of the appropriate size
*/
@@ -170,6 +175,15 @@ vnode_pager_alloc(handle, size, prot, offset)
vm_object_enter(object, pager);
object->pager = pager;
} else {
+ /*
+ * The VOP_GETATTR failed...
+ * Unlock, wakeup any waiters, free pagers, and exit.
+ */
+ vp->v_flag &= ~VOLOCK;
+ if (vp->v_flag & VOWANT) {
+ vp->v_flag &= ~VOWANT;
+ wakeup(vp);
+ }
free((caddr_t) vnp, M_VMPGDATA);
free((caddr_t) pager, M_VMPAGER);
return (NULL);
@@ -197,8 +211,15 @@ vnode_pager_alloc(handle, size, prot, offset)
*/
(void) vm_object_lookup(pager);
}
- if( vp->v_type == VREG)
+
+ if (vp->v_type == VREG)
vp->v_flag |= VVMIO;
+
+ vp->v_flag &= ~VOLOCK;
+ if (vp->v_flag & VOWANT) {
+ vp->v_flag &= ~VOWANT;
+ wakeup(vp);
+ }
return (pager);
}
OpenPOWER on IntegriCloud