summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPedro Martelletto <pedro@cvs.openbsd.org>2004-12-31 12:13:54 +0000
committerPedro Martelletto <pedro@cvs.openbsd.org>2004-12-31 12:13:54 +0000
commitfb6cfb1631e571a75b46eee018090f520a968e69 (patch)
treecb407c56a86bb2f17ffaff9e06270020a8c315e2 /sys
parent0ab76b64e9cb1fc5178245a899daa9ff20f5da89 (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.c26
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);