summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorPedro Martelletto <pedro@cvs.openbsd.org>2005-01-10 11:58:35 +0000
committerPedro Martelletto <pedro@cvs.openbsd.org>2005-01-10 11:58:35 +0000
commit904907a5fdbb96650fa67391bc667417cfdfd2f4 (patch)
treeb63b916f208613932b4760e899923ea91e2002bd /sys/kern
parentba6cd06600e1a01263181dfa72b329ba670594d5 (diff)
change vget() to only put a vnode back on the free lists if it actually
was there. should fix a (rare) corner case introduced by my last commit. ok tedu@, testing by joris, moritz@, danh@, otto@ and krw@. many thanks.
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/vfs_subr.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 4c1eda42b50..1068ce3d8e7 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_subr.c,v 1.108 2004/12/31 15:28:40 pedro Exp $ */
+/* $OpenBSD: vfs_subr.c,v 1.109 2005/01/10 11:58:34 pedro Exp $ */
/* $NetBSD: vfs_subr.c,v 1.53 1996/04/22 01:39:13 christos Exp $ */
/*
@@ -661,8 +661,7 @@ vget(vp, flags, p)
int flags;
struct proc *p;
{
- int error;
- int s;
+ int error, s, onfreelist;
/*
* If the vnode is in the process of being cleaned out for
@@ -686,8 +685,8 @@ vget(vp, flags, p)
return (ENOENT);
}
- if (vp->v_usecount == 0 &&
- (vp->v_bioflag & VBIOONFREELIST)) {
+ onfreelist = vp->v_bioflag & VBIOONFREELIST;
+ if (vp->v_usecount == 0 && onfreelist) {
s = splbio();
simple_lock(&vnode_free_list_slock);
if (vp->v_holdcnt > 0)
@@ -698,18 +697,21 @@ vget(vp, flags, p)
vp->v_bioflag &= ~VBIOONFREELIST;
splx(s);
}
+
vp->v_usecount++;
if (flags & LK_TYPE_MASK) {
if ((error = vn_lock(vp, flags, p)) != 0) {
vp->v_usecount--;
- if (vp->v_usecount == 0)
+ if (vp->v_usecount == 0 && onfreelist)
vputonfreelist(vp);
simple_unlock(&vp->v_interlock);
}
return (error);
}
+
simple_unlock(&vp->v_interlock);
+
return (0);
}