summaryrefslogtreecommitdiffstats
path: root/sys
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
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')
-rw-r--r--sys/sys/vnode.h22
-rw-r--r--sys/vm/vnode_pager.c47
2 files changed, 46 insertions, 23 deletions
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 0cb607a..26d2f9a 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.20 1995/04/20 03:18:19 julian Exp $
+ * $Id: vnode.h,v 1.21 1995/06/28 12:01:07 davidg Exp $
*/
#ifndef _SYS_VNODE_H_
@@ -107,16 +107,18 @@ struct vnode {
/*
* Vnode flags.
*/
-#define VROOT 0x0001 /* root of its file system */
-#define VTEXT 0x0002 /* vnode is a pure text prototype */
-#define VSYSTEM 0x0004 /* vnode being used by kernel */
-#define VXLOCK 0x0100 /* vnode is locked to change underlying type */
-#define VXWANT 0x0200 /* process is waiting for vnode */
-#define VBWAIT 0x0400 /* waiting for output to complete */
-#define VALIASED 0x0800 /* vnode has an alias */
-#define VDIROP 0x1000 /* LFS: vnode is involved in a directory op */
+#define VROOT 0x0001 /* root of its file system */
+#define VTEXT 0x0002 /* vnode is a pure text prototype */
+#define VSYSTEM 0x0004 /* vnode being used by kernel */
+#define VOLOCK 0x0008 /* vnode is locked waiting for an object */
+#define VOWANT 0x0010 /* a process is waiting for VOLOCK */
+#define VXLOCK 0x0100 /* vnode is locked to change underlying type */
+#define VXWANT 0x0200 /* process is waiting for vnode */
+#define VBWAIT 0x0400 /* waiting for output to complete */
+#define VALIASED 0x0800 /* vnode has an alias */
+#define VDIROP 0x1000 /* LFS: vnode is involved in a directory op */
#define VVMIO 0x2000 /* VMIO flag */
-#define VNINACT 0x4000 /* LFS: skip ufs_inactive() in lfs_vunref */
+#define VNINACT 0x4000 /* LFS: skip ufs_inactive() in lfs_vunref */
#define VAGE 0x8000 /* Insert vnode at head of free list */
/*
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