summaryrefslogtreecommitdiff
path: root/sys/kern/vfs_cache.c
diff options
context:
space:
mode:
authoryamt <yamt@NetBSD.org>2004-06-27 08:50:44 +0000
committeryamt <yamt@NetBSD.org>2004-06-27 08:50:44 +0000
commitce02ffbc6814e9666ebff7eef3c48df40ad4ea17 (patch)
tree1b334c530a139f72d53efae36e014dd85dab7953 /sys/kern/vfs_cache.c
parent2c83b7a91b7d5436e010d714d85bba81069dea0f (diff)
introduce a new function, cache_lookup_raw(), for filesystems which
want more flexible namecache handling. it just looks up a dnlc entry and vget() the result vnode. ie. no automatic entry removal, no automatic vnode locking. discussed on tech-kern@.
Diffstat (limited to 'sys/kern/vfs_cache.c')
-rw-r--r--sys/kern/vfs_cache.c75
1 files changed, 73 insertions, 2 deletions
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index b612c9f37f1..0efa7d8cbb1 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_cache.c,v 1.60 2004/06/19 18:49:47 yamt Exp $ */
+/* $NetBSD: vfs_cache.c,v 1.61 2004/06/27 08:50:44 yamt Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.60 2004/06/19 18:49:47 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.61 2004/06/27 08:50:44 yamt Exp $");
#include "opt_ddb.h"
#include "opt_revcache.h"
@@ -328,6 +328,77 @@ fail:
return (-1);
}
+int
+cache_lookup_raw(struct vnode *dvp, struct vnode **vpp,
+ struct componentname *cnp)
+{
+ struct namecache *ncp;
+ struct vnode *vp;
+ int error;
+
+ if (!doingcache) {
+ cnp->cn_flags &= ~MAKEENTRY;
+ *vpp = NULL;
+ return (-1);
+ }
+
+ if (cnp->cn_namelen > NCHNAMLEN) {
+ /* XXXSMP - updating stats without lock; do we care? */
+ nchstats.ncs_long++;
+ cnp->cn_flags &= ~MAKEENTRY;
+ goto fail;
+ }
+ simple_lock(&namecache_slock);
+ ncp = cache_lookup_entry(dvp, cnp);
+ if (ncp == NULL) {
+ nchstats.ncs_miss++;
+ goto fail_wlock;
+ }
+ /*
+ * Move this slot to end of LRU chain,
+ * if not already there.
+ */
+ if (TAILQ_NEXT(ncp, nc_lru) != 0) {
+ TAILQ_REMOVE(&nclruhead, ncp, nc_lru);
+ TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru);
+ }
+
+ vp = ncp->nc_vp;
+ if (vp == NULL) {
+ /*
+ * Restore the ISWHITEOUT flag saved earlier.
+ */
+ cnp->cn_flags |= ncp->nc_flags;
+ nchstats.ncs_neghits++;
+ simple_unlock(&namecache_slock);
+ return (ENOENT);
+ }
+
+ error = vget(vp, LK_NOWAIT);
+
+ /* Release the name cache mutex while we get reference to the vnode */
+ simple_unlock(&namecache_slock);
+
+ if (error) {
+ KASSERT(error == EBUSY);
+ /*
+ * this vnode is being cleaned out.
+ */
+ nchstats.ncs_falsehits++; /* XXX badhits? */
+ goto fail;
+ }
+
+ *vpp = vp;
+
+ return 0;
+
+fail_wlock:
+ simple_unlock(&namecache_slock);
+fail:
+ *vpp = NULL;
+ return -1;
+}
+
/*
* Scan cache looking for name of directory entry pointing at vp.
*