Index: vfs_lookup.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/kern/vfs_lookup.c,v retrieving revision 1.101 diff -u -p -r1.101 vfs_lookup.c --- vfs_lookup.c 27 May 2007 20:50:23 -0000 1.101 +++ vfs_lookup.c 29 Aug 2007 09:54:14 -0000 @@ -772,6 +772,14 @@ nextname: if ((cnp->cn_flags & LOCKLEAF) == 0) VOP_UNLOCK(dp, 0, td); success: + /* + * Because of lookup_shared we may have the vnode shared locked, but + * the caller may want it to be exclusively locked. + */ + if ((cnp->cn_flags & (ISLASTCN | LOCKSHARED | LOCKLEAF)) == + (ISLASTCN | LOCKLEAF) && VOP_ISLOCKED(dp, td) != LK_EXCLUSIVE) { + vn_lock(dp, LK_UPGRADE | LK_RETRY, td); + } if (vfslocked && dvfslocked) VFS_UNLOCK_GIANT(dvfslocked); /* Only need one */ if (vfslocked || dvfslocked) Index: vfs_cache.c =================================================================== RCS file: /zoo/pjd/repo/src/sys/kern/vfs_cache.c,v retrieving revision 1.113 diff -u -p -r1.113 vfs_cache.c --- vfs_cache.c 18 Jun 2007 09:28:24 -0000 1.113 +++ vfs_cache.c 29 Aug 2007 09:55:33 -0000 @@ -314,6 +314,7 @@ cache_lookup(dvp, vpp, cnp) struct componentname *cnp; { struct namecache *ncp; + struct thread *td; u_int32_t hash; int error, ltype; @@ -321,6 +322,7 @@ cache_lookup(dvp, vpp, cnp) cnp->cn_flags &= ~MAKEENTRY; return (0); } + td = cnp->cn_thread; retry: CACHE_LOCK(); numcalls++; @@ -419,18 +421,29 @@ success: if (dvp == *vpp) { /* lookup on "." */ VREF(*vpp); CACHE_UNLOCK(); + /* + * When we lookup "." we still can be asked to lock it + * differently... + */ + ltype = cnp->cn_lkflags & (LK_SHARED | LK_EXCLUSIVE); + if (ltype == VOP_ISLOCKED(*vpp, td)) + return (-1); + else if (ltype == LK_EXCLUSIVE) + vn_lock(*vpp, LK_UPGRADE | LK_RETRY, td); return (-1); } ltype = 0; /* silence gcc warning */ if (cnp->cn_flags & ISDOTDOT) { - ltype = VOP_ISLOCKED(dvp, cnp->cn_thread); - VOP_UNLOCK(dvp, 0, cnp->cn_thread); + ltype = VOP_ISLOCKED(dvp, td); + VOP_UNLOCK(dvp, 0, td); } VI_LOCK(*vpp); CACHE_UNLOCK(); - error = vget(*vpp, cnp->cn_lkflags | LK_INTERLOCK, cnp->cn_thread); + error = vget(*vpp, cnp->cn_lkflags | LK_INTERLOCK, td); if (cnp->cn_flags & ISDOTDOT) - vn_lock(dvp, ltype | LK_RETRY, cnp->cn_thread); + vn_lock(dvp, ltype | LK_RETRY, td); + if ((cnp->cn_flags & ISLASTCN) && (cnp->cn_lkflags & LK_EXCLUSIVE)) + ASSERT_VOP_ELOCKED(*vpp, "cache_lookup"); if (error) { *vpp = NULL; goto retry;