diff options
author | Pedro Martelletto <pedro@cvs.openbsd.org> | 2004-12-31 12:13:54 +0000 |
---|---|---|
committer | Pedro Martelletto <pedro@cvs.openbsd.org> | 2004-12-31 12:13:54 +0000 |
commit | fb6cfb1631e571a75b46eee018090f520a968e69 (patch) | |
tree | cb407c56a86bb2f17ffaff9e06270020a8c315e2 /sys | |
parent | 0ab76b64e9cb1fc5178245a899daa9ff20f5da89 (diff) |
when releasing a vnode, make it inactive before sticking it to one of
the free lists. should fix some races on filesystems that don't have
locks, such as nfs. also, it allows for a more straightforward way of
releasing vnodes (nodes that are going to be recycled don't have to be
moved to the head of the list). tested by many, thanks.
ok tedu@ deraadt@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/vfs_subr.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 1e1150a044b..bf376248b66 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_subr.c,v 1.106 2004/12/28 15:14:37 deraadt Exp $ */ +/* $OpenBSD: vfs_subr.c,v 1.107 2004/12/31 12:13:53 pedro Exp $ */ /* $NetBSD: vfs_subr.c,v 1.53 1996/04/22 01:39:13 christos Exp $ */ /* @@ -796,11 +796,16 @@ vput(vp) panic("vput: v_writecount != 0"); } #endif - vputonfreelist(vp); - simple_unlock(&vp->v_interlock); VOP_INACTIVE(vp, p); + + simple_lock(&vp->v_interlock); + + if (vp->v_usecount == 0) + vputonfreelist(vp); + + simple_unlock(&vp->v_interlock); } /* @@ -836,10 +841,19 @@ vrele(vp) panic("vrele: v_writecount != 0"); } #endif - vputonfreelist(vp); + if (vn_lock(vp, LK_EXCLUSIVE|LK_INTERLOCK, p)) { + vprint("vrele: cannot lock", vp); + return; + } - if (vn_lock(vp, LK_EXCLUSIVE|LK_INTERLOCK, p) == 0) - VOP_INACTIVE(vp, p); + VOP_INACTIVE(vp, p); + + simple_lock(&vp->v_interlock); + + if (vp->v_usecount == 0) + vputonfreelist(vp); + + simple_unlock(&vp->v_interlock); } void vhold(struct vnode *vp); |