mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-13 14:40:22 +00:00
Fixed an object allocation race condition that was causing a "object
deallocated too many times" panic when using NFS. Reviewed by: John Dyson
This commit is contained in:
parent
bea0b497a1
commit
39d38f93e2
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=9411
@ -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 */
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
||||
/*
|
||||
* Vnodes keep a pointer to any associated pager so no need to lookup
|
||||
* with vm_pager_lookup.
|
||||
*/
|
||||
vp = (struct vnode *) handle;
|
||||
while ((object = vp->v_object) &&
|
||||
(object->flags & OBJ_DEAD))
|
||||
|
||||
/*
|
||||
* Prevent race condition when allocating the object. This
|
||||
* can happen with NFS vnodes since the nfsnode isn't locked.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user