summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_cache.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1997-08-26 07:32:51 +0000
committerphk <phk@FreeBSD.org>1997-08-26 07:32:51 +0000
commitfddfc9d5bb4c35d88417fa80a062219876186593 (patch)
tree7f29931e5661e3731f6b972dc3a9508534617833 /sys/kern/vfs_cache.c
parentf320b3a30651cae7b34067561adb48f2b6f57621 (diff)
downloadFreeBSD-src-fddfc9d5bb4c35d88417fa80a062219876186593.zip
FreeBSD-src-fddfc9d5bb4c35d88417fa80a062219876186593.tar.gz
Uncut&paste cache_lookup().
This unifies several times in theory indentical 50 lines of code. The filesystems have a new method: vop_cachedlookup, which is the meat of the lookup, and use vfs_cache_lookup() for their vop_lookup method. vfs_cache_lookup() will check the namecache and pass on to the vop_cachedlookup method in case of a miss. It's still the task of the individual filesystems to populate the namecache with cache_enter(). Filesystems that do not use the namecache will just provide the vop_lookup method as usual.
Diffstat (limited to 'sys/kern/vfs_cache.c')
-rw-r--r--sys/kern/vfs_cache.c85
1 files changed, 84 insertions, 1 deletions
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index 0e55914..a1f94f4 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95
- * $Id: vfs_cache.c,v 1.25 1997/05/04 09:17:28 phk Exp $
+ * $Id: vfs_cache.c,v 1.26 1997/08/04 07:31:36 phk Exp $
*/
#include <sys/param.h>
@@ -336,3 +336,86 @@ cache_purgevfs(mp)
}
}
}
+
+/*
+ * Perform canonical checks and cache lookup and pass on to filesystem
+ * through the vop_cachedlookup only if needed.
+ */
+
+int
+vfs_cache_lookup(ap)
+ struct vop_lookup_args /* {
+ struct vnode *a_dvp;
+ struct vnode **a_vpp;
+ struct componentname *a_cnp;
+ } */ *ap;
+{
+ struct vnode *vdp;
+ struct vnode *pdp;
+ int lockparent;
+ int error;
+ struct vnode **vpp = ap->a_vpp;
+ struct componentname *cnp = ap->a_cnp;
+ struct ucred *cred = cnp->cn_cred;
+ int flags = cnp->cn_flags;
+ struct proc *p = cnp->cn_proc;
+ u_long vpid; /* capability number of vnode */
+
+ *vpp = NULL;
+ vdp = ap->a_dvp;
+ lockparent = flags & LOCKPARENT;
+
+ if (vdp->v_type != VDIR)
+ return (ENOTDIR);
+
+ if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) &&
+ (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
+ return (EROFS);
+
+ error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc);
+
+ if (error)
+ return (error);
+
+ error = cache_lookup(vdp, vpp, cnp);
+
+ if (!error)
+ return (VCALL(vdp, VOFFSET(vop_cachedlookup),
+ (struct vop_cachedlookup_args *)ap));
+
+ if (error == ENOENT)
+ return (error);
+
+ pdp = vdp;
+ vdp = *vpp;
+ vpid = vdp->v_id;
+ if (pdp == vdp) { /* lookup on "." */
+ VREF(vdp);
+ error = 0;
+ } else if (flags & ISDOTDOT) {
+ VOP_UNLOCK(pdp, 0, p);
+ error = vget(vdp, LK_EXCLUSIVE, p);
+ if (!error && lockparent && (flags & ISLASTCN))
+ error = vn_lock(pdp, LK_EXCLUSIVE, p);
+ } else {
+ error = vget(vdp, LK_EXCLUSIVE, p);
+ if (!lockparent || error || !(flags & ISLASTCN))
+ VOP_UNLOCK(pdp, 0, p);
+ }
+ /*
+ * Check that the capability number did not change
+ * while we were waiting for the lock.
+ */
+ if (!error) {
+ if (vpid == vdp->v_id)
+ return (0);
+ vput(vdp);
+ if (lockparent && pdp != vdp && (flags & ISLASTCN))
+ VOP_UNLOCK(pdp, 0, p);
+ }
+ error = vn_lock(pdp, LK_EXCLUSIVE, p);
+ if (error)
+ return (error);
+ return (VCALL(vdp, VOFFSET(vop_cachedlookup),
+ (struct vop_cachedlookup_args *)ap));
+}
OpenPOWER on IntegriCloud