diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index b612c9f37f14..0efa7d8cbb1b 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 -__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. * diff --git a/sys/sys/namei.h b/sys/sys/namei.h index e33cdd7f0e33..c902d431ffd3 100644 --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -1,4 +1,4 @@ -/* $NetBSD: namei.h,v 1.36 2004/04/17 15:24:22 christos Exp $ */ +/* $NetBSD: namei.h,v 1.37 2004/06/27 08:50:44 yamt Exp $ */ /* * Copyright (c) 1985, 1989, 1991, 1993 @@ -193,6 +193,8 @@ void cache_purge1 __P((struct vnode *, const struct componentname *, int)); #define PURGE_CHILDREN 2 #define cache_purge(vp) cache_purge1((vp), NULL, PURGE_PARENTS|PURGE_CHILDREN) int cache_lookup __P((struct vnode *, struct vnode **, struct componentname *)); +int cache_lookup_raw __P((struct vnode *, struct vnode **, + struct componentname *)); int cache_revlookup __P((struct vnode *, struct vnode **, char **, char *)); void cache_enter __P((struct vnode *, struct vnode *, struct componentname *)); void nchinit __P((void));