diff options
author | dg <dg@FreeBSD.org> | 1995-07-06 11:48:48 +0000 |
---|---|---|
committer | dg <dg@FreeBSD.org> | 1995-07-06 11:48:48 +0000 |
commit | 21036bccfd267479c2ca00a9753138d46d94d41e (patch) | |
tree | ce873fc5ea1381810ca2b25a516e0da6f4c2366b /sys | |
parent | fa8de9933bb206fd1d26887990a414aa1b781904 (diff) | |
download | FreeBSD-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.h | 22 | ||||
-rw-r--r-- | sys/vm/vnode_pager.c | 47 |
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); } |