summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_lookup.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2009-03-11 14:13:47 +0000
committerjhb <jhb@FreeBSD.org>2009-03-11 14:13:47 +0000
commit520acdaf6926bd9375ce8e27092559997f111882 (patch)
tree9729e7549d110dca0074d289abb6591d48654669 /sys/kern/vfs_lookup.c
parent8609dfd41ccae53505ee519fd6426fc876675ebd (diff)
downloadFreeBSD-src-520acdaf6926bd9375ce8e27092559997f111882.zip
FreeBSD-src-520acdaf6926bd9375ce8e27092559997f111882.tar.gz
Add a new internal mount flag (MNTK_EXTENDED_SHARED) to indicate that a
filesystem supports additional operations using shared vnode locks. Currently this is used to enable shared locks for open() and close() of read-only file descriptors. - When an ISOPEN namei() request is performed with LOCKSHARED, use a shared vnode lock for the leaf vnode only if the mount point has the extended shared flag set. - Set LOCKSHARED in vn_open_cred() for requests that specify O_RDONLY but not O_CREAT. - Use a shared vnode lock around VOP_CLOSE() if the file was opened with O_RDONLY and the mountpoint has the extended shared flag set. - Adjust md(4) to upgrade the vnode lock on the vnode it gets back from vn_open() since it now may only have a shared vnode lock. - Don't enable shared vnode locks on FIFO vnodes in ZFS and UFS since FIFO's require exclusive vnode locks for their open() and close() routines. (My recent MPSAFE patches for UDF and cd9660 already included this change.) - Enable extended shared operations on UFS, cd9660, and UDF. Submitted by: ups Reviewed by: pjd (ZFS bits) MFC after: 1 month
Diffstat (limited to 'sys/kern/vfs_lookup.c')
-rw-r--r--sys/kern/vfs_lookup.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index c4840ce..a21af4f 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -353,6 +353,41 @@ compute_cn_lkflags(struct mount *mp, int lkflags)
return (lkflags);
}
+static __inline int
+needs_exclusive_leaf(struct mount *mp, int flags)
+{
+
+ /*
+ * Intermediate nodes can use shared locks, we only need to
+ * force an exclusive lock for leaf nodes.
+ */
+ if ((flags & (ISLASTCN | LOCKLEAF)) != (ISLASTCN | LOCKLEAF))
+ return (0);
+
+ /* Always use exclusive locks if LOCKSHARED isn't set. */
+ if (!(flags & LOCKSHARED))
+ return (1);
+
+ /*
+ * For lookups during open(), if the mount point supports
+ * extended shared operations, then use a shared lock for the
+ * leaf node, otherwise use an exclusive lock.
+ */
+ if (flags & ISOPEN) {
+ if (mp != NULL &&
+ (mp->mnt_kern_flag & MNTK_EXTENDED_SHARED))
+ return (0);
+ else
+ return (1);
+ }
+
+ /*
+ * Lookup requests outside of open() that specify LOCKSHARED
+ * only need a shared lock on the leaf vnode.
+ */
+ return (1);
+}
+
/*
* Search a pathname.
* This is a very central and rather complicated routine.
@@ -610,8 +645,7 @@ unionlookup:
* 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))
+ if (needs_exclusive_leaf(dp->v_mount, cnp->cn_flags))
cnp->cn_lkflags = LK_EXCLUSIVE;
#ifdef NAMEI_DIAGNOSTIC
vprint("lookup in", dp);
@@ -811,8 +845,8 @@ 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) != LK_EXCLUSIVE) {
+ if (needs_exclusive_leaf(dp->v_mount, cnp->cn_flags) &&
+ VOP_ISLOCKED(dp) != LK_EXCLUSIVE) {
vn_lock(dp, LK_UPGRADE | LK_RETRY);
if (dp->v_iflag & VI_DOOMED) {
error = ENOENT;
OpenPOWER on IntegriCloud