summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorbp <bp@FreeBSD.org>2000-09-13 08:57:56 +0000
committerbp <bp@FreeBSD.org>2000-09-13 08:57:56 +0000
commitd21670b5d5b0f29eada55081ca0cd79ecfed6031 (patch)
tree10bbe7310488f7a7d08ac2ae0201a798e935e47c /sys/kern
parent93a57684b220722f62f6cd9fc69fbb7b8b269dc7 (diff)
downloadFreeBSD-src-d21670b5d5b0f29eada55081ca0cd79ecfed6031.zip
FreeBSD-src-d21670b5d5b0f29eada55081ca0cd79ecfed6031.tar.gz
Unlock current directory when calling VFS_ROOT() because underlying
filesystem may hold the lock. Otherwise unavoidable deadlock will occur. This shouldn't have any side effects as long as we hold vfs lock. Obtained from: NetBSD
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/vfs_lookup.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index 4cdec9e..c9f43d4 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -274,6 +274,7 @@ lookup(ndp)
int rdonly; /* lookup read-only flag bit */
int trailing_slash;
int error = 0;
+ int dpunlocked = 0; /* dp has already been unlocked */
struct componentname *cnp = &ndp->ni_cnd;
struct proc *p = cnp->cn_proc;
@@ -487,11 +488,14 @@ unionlookup:
(cnp->cn_flags & NOCROSSMOUNT) == 0) {
if (vfs_busy(mp, 0, 0, p))
continue;
+ VOP_UNLOCK(dp, 0, p);
error = VFS_ROOT(mp, &tdp);
vfs_unbusy(mp, p);
- if (error)
+ if (error) {
+ dpunlocked = 1;
goto bad2;
- vput(dp);
+ }
+ vrele(dp);
ndp->ni_vp = dp = tdp;
}
@@ -557,7 +561,10 @@ bad2:
VOP_UNLOCK(ndp->ni_dvp, 0, p);
vrele(ndp->ni_dvp);
bad:
- vput(dp);
+ if (dpunlocked)
+ vrele(dp);
+ else
+ vput(dp);
ndp->ni_vp = NULL;
return (error);
}
OpenPOWER on IntegriCloud