summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2005-03-29 10:07:15 +0000
committerjeff <jeff@FreeBSD.org>2005-03-29 10:07:15 +0000
commit4a949bda2b74c7182c22451d4943553ca5005957 (patch)
tree8f1fccca262dbdec310aa51f13d913fb6d9567e6 /sys/kern
parent969761f8daae59964da04616d7b72c868759df58 (diff)
downloadFreeBSD-src-4a949bda2b74c7182c22451d4943553ca5005957.zip
FreeBSD-src-4a949bda2b74c7182c22451d4943553ca5005957.tar.gz
- Set cn_lkflags to LK_SHARED in the LOOKUP_SHARED case so that we only
acquire shared locks on intermediate directories. - For the LASTCN, we may have to LK_UPGRADE the parent directory before we lookup the last component. - Acquire VFS_ROOT and dp locks based on the cn_lkflag. Sponsored by: Isilon Systems, Inc.
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/vfs_lookup.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index 6b8b806..9177cee 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -360,11 +360,20 @@ lookup(ndp)
cnp->cn_nameiop != LOOKUP))
docache = 0;
rdonly = cnp->cn_flags & RDONLY;
- ndp->ni_dvp = NULL;
cnp->cn_flags &= ~ISSYMLINK;
+ ndp->ni_dvp = NULL;
+#ifdef LOOKUP_SHARED
+ /*
+ * We use shared locks until we hit the parent of the last cn then
+ * we adjust based on the requesting flags.
+ */
+ cnp->cn_lkflags = LK_SHARED;
+#else
+ cnp->cn_lkflags = LK_EXCLUSIVE;
+#endif
dp = ndp->ni_startdir;
ndp->ni_startdir = NULLVP;
- vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
+ vn_lock(dp, cnp->cn_lkflags | LK_RETRY, td);
dirloop:
/*
@@ -487,7 +496,7 @@ dirloop:
vfslocked = VFS_LOCK_GIANT(dp->v_mount);
VFS_UNLOCK_GIANT(tvfslocked);
VREF(dp);
- vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
+ vn_lock(dp, cnp->cn_lkflags | LK_RETRY, td);
}
}
@@ -505,6 +514,20 @@ unionlookup:
ndp->ni_dvp = dp;
ndp->ni_vp = NULL;
ASSERT_VOP_LOCKED(dp, "lookup");
+ /*
+ * If we have a shared lock we may need to upgrade the lock for the
+ * last operation.
+ */
+ if (VOP_ISLOCKED(dp, td) == LK_SHARED &&
+ (cnp->cn_flags & ISLASTCN) && (cnp->cn_flags & LOCKPARENT))
+ vn_lock(dp, LK_UPGRADE|LK_RETRY, td);
+ /*
+ * If we're looking up the last component and we need an exclusive
+ * lock, adjust our lkflags.
+ */
+ if ((cnp->cn_flags & (ISLASTCN|LOCKSHARED|LOCKLEAF)) ==
+ (ISLASTCN|LOCKLEAF))
+ cnp->cn_lkflags = LK_EXCLUSIVE;
#ifdef NAMEI_DIAGNOSTIC
vprint("lookup in", dp);
#endif
@@ -523,7 +546,7 @@ unionlookup:
vfslocked = VFS_LOCK_GIANT(dp->v_mount);
VFS_UNLOCK_GIANT(tvfslocked);
VREF(dp);
- vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
+ vn_lock(dp, cnp->cn_lkflags | LK_RETRY, td);
goto unionlookup;
}
@@ -604,7 +627,7 @@ unionlookup:
continue;
VOP_UNLOCK(dp, 0, td);
tvfslocked = VFS_LOCK_GIANT(mp);
- error = VFS_ROOT(mp, LK_EXCLUSIVE, &tdp, td);
+ error = VFS_ROOT(mp, cnp->cn_lkflags, &tdp, td);
vfs_unbusy(mp, td);
if (error) {
VFS_UNLOCK_GIANT(tvfslocked);
@@ -725,6 +748,7 @@ relookup(dvp, vpp, cnp)
rdonly = cnp->cn_flags & RDONLY;
cnp->cn_flags &= ~ISSYMLINK;
dp = dvp;
+ cnp->cn_lkflags = LK_EXCLUSIVE;
vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
/*
OpenPOWER on IntegriCloud