From 1e39ba86206301d7f569b3f402577d596d55faa0 Mon Sep 17 00:00:00 2001 From: jeff Date: Thu, 22 Aug 2002 06:51:06 +0000 Subject: - Fix interlock handling in vn_lock(). Previously, vn_lock() could return with interlock held in error conditions when the caller did not specify LK_INTERLOCK. - Add several comments to vn_lock() describing the rational behind the code flow since it was not immediately obvious. --- sys/kern/vfs_subr.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 2fe2d00..96f902a 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -931,17 +931,6 @@ getnewvnode(tag, mp, vops, vpp) splx(s); -#if 0 - mp_fixme("This code does not lock access to numvnodes && freevnodes."); - vnodeallocs++; - if (vnodeallocs % vnoderecycleperiod == 0 && - freevnodes < vnoderecycleminfreevn && - vnoderecyclemintotalvn < numvnodes) { - /* Recycle vnodes. */ - cache_purgeleafdirs(vnoderecyclenumber); - } -#endif - return (0); } @@ -2183,12 +2172,12 @@ loop: nvp = TAILQ_NEXT(vp, v_nmntvnodes); mtx_unlock(&mntvnode_mtx); - VI_LOCK(vp); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* * Skip over a vnodes marked VV_SYSTEM. */ if ((flags & SKIPSYSTEM) && (vp->v_vflag & VV_SYSTEM)) { - VI_UNLOCK(vp); + VOP_UNLOCK(vp, 0, td); mtx_lock(&mntvnode_mtx); continue; } @@ -2197,17 +2186,20 @@ loop: * files (even if open only for reading) and regular file * vnodes open for writing. */ - mp_fixme("Getattr called with interlock held!"); + error = VOP_GETATTR(vp, &vattr, td->td_ucred, td); + VI_LOCK(vp); + if ((flags & WRITECLOSE) && (vp->v_type == VNON || - (VOP_GETATTR(vp, &vattr, td->td_ucred, td) == 0 && - vattr.va_nlink > 0)) && + (error == 0 && vattr.va_nlink > 0)) && (vp->v_writecount == 0 || vp->v_type != VREG)) { - mtx_unlock(&vp->v_interlock); + VOP_UNLOCK(vp, LK_INTERLOCK, td); mtx_lock(&mntvnode_mtx); continue; } + VOP_UNLOCK(vp, 0, td); + /* * With v_usecount == 0, all we need to do is clear out the * vnode data structures and we are done. -- cgit v1.1