summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_cache.c
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2002-03-12 04:00:11 +0000
committerjeff <jeff@FreeBSD.org>2002-03-12 04:00:11 +0000
commite6d26e8880ff741e6a936a20fbcab7c5df6443c0 (patch)
treedb3ad14ad172419e9392e38ccefc609f619092d3 /sys/kern/vfs_cache.c
parentb6412800f5692591eb5568403f073bc55cc762ff (diff)
downloadFreeBSD-src-e6d26e8880ff741e6a936a20fbcab7c5df6443c0.zip
FreeBSD-src-e6d26e8880ff741e6a936a20fbcab7c5df6443c0.tar.gz
This patch adds the "LOCKSHARED" option to namei which causes it to only acquire shared locks on leafs.
The stat() and open() calls have been changed to make use of this new functionality. Using shared locks in these cases is sufficient and can significantly reduce their latency if IO is pending to these vnodes. Also, this reduces the number of exclusive locks that are floating around in the system, which helps reduce the number of deadlocks that occur. A new kernel option "LOOKUP_SHARED" has been added. It defaults to off so this patch can be turned on for testing, and should eventually go away once it is proven to be stable. I have personally been running this patch for over a year now, so it is believed to be fully stable. Reviewed by: jake, obrien Approved by: jake
Diffstat (limited to 'sys/kern/vfs_cache.c')
-rw-r--r--sys/kern/vfs_cache.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index 08e0397..529efd1 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -570,8 +570,35 @@ vfs_cache_lookup(ap)
error = cache_lookup(dvp, vpp, cnp);
+#ifdef LOOKUP_SHARED
+ if (!error) {
+ /* We do this because the rest of the system now expects to get
+ * a shared lock, which is later upgraded if LOCKSHARED is not
+ * set. We have so many cases here because of bugs that yield
+ * inconsistant lock states. This all badly needs to be fixed
+ */
+ error = VOP_CACHEDLOOKUP(dvp, vpp, cnp);
+ if (!error) {
+ int flock;
+
+ flock = VOP_ISLOCKED(*vpp, td);
+ if (flock != LK_EXCLUSIVE) {
+ if (flock == 0) {
+ if ((flags & ISLASTCN) &&
+ (flags & LOCKSHARED))
+ VOP_LOCK(*vpp, LK_SHARED, td);
+ else
+ VOP_LOCK(*vpp, LK_EXCLUSIVE, td);
+ }
+ } else if ((flags & ISLASTCN) && (flags & LOCKSHARED))
+ VOP_LOCK(*vpp, LK_DOWNGRADE, td);
+ }
+ return (error);
+ }
+#else
if (!error)
return (VOP_CACHEDLOOKUP(dvp, vpp, cnp));
+#endif
if (error == ENOENT)
return (error);
@@ -585,13 +612,28 @@ vfs_cache_lookup(ap)
} else if (flags & ISDOTDOT) {
VOP_UNLOCK(dvp, 0, td);
cnp->cn_flags |= PDIRUNLOCK;
+#ifdef LOOKUP_SHARED
+ if ((flags & ISLASTCN) && (flags & LOCKSHARED))
+ error = vget(vp, LK_SHARED, td);
+ else
+ error = vget(vp, LK_EXCLUSIVE, td);
+#else
error = vget(vp, LK_EXCLUSIVE, td);
+#endif
+
if (!error && lockparent && (flags & ISLASTCN)) {
if ((error = vn_lock(dvp, LK_EXCLUSIVE, td)) == 0)
cnp->cn_flags &= ~PDIRUNLOCK;
}
} else {
+#ifdef LOOKUP_SHARED
+ if ((flags & ISLASTCN) && (flags & LOCKSHARED))
+ error = vget(vp, LK_SHARED, td);
+ else
+ error = vget(vp, LK_EXCLUSIVE, td);
+#else
error = vget(vp, LK_EXCLUSIVE, td);
+#endif
if (!lockparent || error || !(flags & ISLASTCN)) {
VOP_UNLOCK(dvp, 0, td);
cnp->cn_flags |= PDIRUNLOCK;
@@ -616,7 +658,28 @@ vfs_cache_lookup(ap)
return (error);
cnp->cn_flags &= ~PDIRUNLOCK;
}
+#ifdef LOOKUP_SHARED
+ error = VOP_CACHEDLOOKUP(dvp, vpp, cnp);
+
+ if (!error) {
+ int flock = 0;
+
+ flock = VOP_ISLOCKED(*vpp, td);
+ if (flock != LK_EXCLUSIVE) {
+ if (flock == 0) {
+ if ((flags & ISLASTCN) && (flags & LOCKSHARED))
+ VOP_LOCK(*vpp, LK_SHARED, td);
+ else
+ VOP_LOCK(*vpp, LK_EXCLUSIVE, td);
+ }
+ } else if ((flags & ISLASTCN) && (flags & LOCKSHARED))
+ VOP_LOCK(*vpp, LK_DOWNGRADE, td);
+ }
+
+ return (error);
+#else
return (VOP_CACHEDLOOKUP(dvp, vpp, cnp));
+#endif
}
OpenPOWER on IntegriCloud