summaryrefslogtreecommitdiff
path: root/sys/kern/vfs_lookup.c
diff options
context:
space:
mode:
authorJeff Roberson <jeff@FreeBSD.org>2006-02-01 09:34:32 +0000
committerJeff Roberson <jeff@FreeBSD.org>2006-02-01 09:34:32 +0000
commit9157b485f0d13758354a85f7c535d2d7444bac2f (patch)
tree31148bcc2771afc3b68a4e8012573dcabc717e68 /sys/kern/vfs_lookup.c
parent0ac72424f09c0f1f5f903f78e53f8d26ef45c675 (diff)
Notes
Diffstat (limited to 'sys/kern/vfs_lookup.c')
-rw-r--r--sys/kern/vfs_lookup.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index 8ad90bbcf7c9..42327ca6a0e4 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -60,7 +60,7 @@ __FBSDID("$FreeBSD$");
#include <vm/uma.h>
-#define NAMEI_DIAGNOSTIC 1
+#define NAMEI_DIAGNOSTIC 1
#undef NAMEI_DIAGNOSTIC
/*
@@ -352,11 +352,13 @@ lookup(ndp)
struct thread *td = cnp->cn_thread;
int vfslocked;
int tvfslocked;
+ int dvfslocked;
/*
* Setup: break out flag bits into variables.
*/
vfslocked = (ndp->ni_cnd.cn_flags & GIANTHELD) != 0;
+ dvfslocked = 0;
ndp->ni_cnd.cn_flags &= ~GIANTHELD;
wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
KASSERT(cnp->cn_nameiop == LOOKUP || wantparent,
@@ -623,9 +625,8 @@ unionlookup:
if (vfs_busy(mp, 0, 0, td))
continue;
vput(dp);
- tvfslocked = VFS_LOCK_GIANT(mp);
- VFS_UNLOCK_GIANT(vfslocked);
- vfslocked = tvfslocked;
+ dvfslocked = vfslocked;
+ vfslocked = VFS_LOCK_GIANT(mp);
VOP_UNLOCK(ndp->ni_dvp, 0, td);
error = VFS_ROOT(mp, cnp->cn_lkflags, &tdp, td);
VOP_LOCK(ndp->ni_dvp, cnp->cn_lkflags | LK_RETRY, td);
@@ -687,6 +688,8 @@ nextname:
vput(ndp->ni_dvp);
else
vrele(ndp->ni_dvp);
+ VFS_UNLOCK_GIANT(dvfslocked);
+ dvfslocked = 0;
goto dirloop;
}
/*
@@ -706,13 +709,17 @@ nextname:
vput(ndp->ni_dvp);
else
vrele(ndp->ni_dvp);
+ VFS_UNLOCK_GIANT(dvfslocked);
+ dvfslocked = 0;
} else if ((cnp->cn_flags & LOCKPARENT) == 0 && ndp->ni_dvp != dp)
VOP_UNLOCK(ndp->ni_dvp, 0, td);
if ((cnp->cn_flags & LOCKLEAF) == 0)
VOP_UNLOCK(dp, 0, td);
success:
- if (vfslocked)
+ if (vfslocked && dvfslocked)
+ VFS_UNLOCK_GIANT(dvfslocked); /* Only need one */
+ if (vfslocked || dvfslocked)
ndp->ni_cnd.cn_flags |= GIANTHELD;
return (0);
@@ -725,6 +732,7 @@ bad:
if (!dpunlocked)
vput(dp);
VFS_UNLOCK_GIANT(vfslocked);
+ VFS_UNLOCK_GIANT(dvfslocked);
ndp->ni_cnd.cn_flags &= ~GIANTHELD;
ndp->ni_vp = NULL;
return (error);