Subject: cache_purge
To: None <tech-kern@netbsd.org>
From: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
List: tech-kern
Date: 03/20/2004 16:03:36
--NextPart-20040320154242-0151500
Content-Type: Text/Plain; charset=us-ascii
hi,
currently cache_purge() is a sledgehammer that purge all entries
related the given vnode.
the attached diff (cache_purge1.diff) makes it a little more controlable.
eg. purge only an entry, only child entries, etc.
i'd like to commit it if there's no objection.
YAMAMOTO Takashi
--NextPart-20040320154242-0151500
Content-Type: Text/Plain; charset=us-ascii
Content-Disposition: attachment; filename="cache_purge1.diff"
Index: sys/namei.h
===================================================================
--- sys/namei.h (revision 630)
+++ sys/namei.h (revision 640)
@@ -189,6 +189,10 @@ uint32_t namei_hash __P((const char *, c
int lookup __P((struct nameidata *));
int relookup __P((struct vnode *, struct vnode **, struct componentname *));
void cache_purge __P((struct vnode *));
+void cache_purge1 __P((struct vnode *, const struct componentname *, int));
+#define PURGE_PARENTS 1
+#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_revlookup __P((struct vnode *, struct vnode **, char **, char *));
void cache_enter __P((struct vnode *, struct vnode *, struct componentname *));
Index: kern/vfs_cache.c
===================================================================
--- kern/vfs_cache.c (revision 630)
+++ kern/vfs_cache.c (revision 640)
@@ -96,6 +96,8 @@ static struct simplelock namecache_slock
static void cache_remove(struct namecache *);
static void cache_free(struct namecache *);
+static __inline struct namecache *cache_lookup_entry(
+ const struct vnode *, const struct componentname *);
static void
cache_remove(struct namecache *ncp)
@@ -133,6 +135,26 @@ cache_free(struct namecache *ncp)
numcache--; /* XXX MP */
}
+static __inline struct namecache *
+cache_lookup_entry(const struct vnode *dvp, const struct componentname *cnp)
+{
+ struct nchashhead *ncpp;
+ struct namecache *ncp;
+
+ LOCK_ASSERT(simple_lock_held(&namecache_slock));
+
+ ncpp = &nchashtbl[NCHASH(cnp, dvp)];
+
+ LIST_FOREACH(ncp, ncpp, nc_hash) {
+ if (ncp->nc_dvp == dvp &&
+ ncp->nc_nlen == cnp->cn_namelen &&
+ !memcmp(ncp->nc_name, cnp->cn_nameptr, (u_int)ncp->nc_nlen))
+ break;
+ }
+
+ return ncp;
+}
+
/*
* Look for a the name in the cache. We don't do this
* if the segment name is long, simply so the cache can avoid
@@ -153,7 +175,6 @@ int
cache_lookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp)
{
struct namecache *ncp;
- struct nchashhead *ncpp;
struct vnode *vp;
int error;
@@ -169,15 +190,9 @@ cache_lookup(struct vnode *dvp, struct v
cnp->cn_flags &= ~MAKEENTRY;
goto fail;
}
- ncpp = &nchashtbl[NCHASH(cnp, dvp)];
simple_lock(&namecache_slock);
- LIST_FOREACH(ncp, ncpp, nc_hash) {
- if (ncp->nc_dvp == dvp &&
- ncp->nc_nlen == cnp->cn_namelen &&
- !memcmp(ncp->nc_name, cnp->cn_nameptr, (u_int)ncp->nc_nlen))
- break;
- }
- if (ncp == 0) {
+ ncp = cache_lookup_entry(dvp, cnp);
+ if (ncp == NULL) {
nchstats.ncs_miss++;
goto fail_wlock;
}
@@ -304,14 +319,8 @@ remove:
* the cache entry is invalid, or otherwise don't
* want cache entry to exist.
*/
- TAILQ_REMOVE(&nclruhead, ncp, nc_lru);
- LIST_REMOVE(ncp, nc_hash);
- ncp->nc_hash.le_prev = NULL;
- if (ncp->nc_vhash.le_prev != NULL) {
- LIST_REMOVE(ncp, nc_vhash);
- ncp->nc_vhash.le_prev = NULL;
- }
- TAILQ_INSERT_HEAD(&nclruhead, ncp, nc_lru);
+ cache_remove(ncp);
+ cache_free(ncp);
fail_wlock:
simple_unlock(&namecache_slock);
@@ -408,6 +417,7 @@ cache_enter(struct vnode *dvp, struct vn
* Free the cache slot at head of lru chain.
*/
simple_lock(&namecache_slock);
+ KASSERT(cache_lookup_entry(dvp, cnp) == NULL);
if (numcache < numvnodes) {
numcache++;
simple_unlock(&namecache_slock);
@@ -529,20 +539,33 @@ nchreinit(void)
* hide entries that would now be invalid
*/
void
-cache_purge(struct vnode *vp)
+cache_purge1(struct vnode *vp, const struct componentname *cnp, int flags)
{
struct namecache *ncp, *ncnext;
simple_lock(&namecache_slock);
- for (ncp = LIST_FIRST(&vp->v_nclist); ncp != NULL; ncp = ncnext) {
- ncnext = LIST_NEXT(ncp, nc_vlist);
- cache_remove(ncp);
- cache_free(ncp);
+ if (flags & PURGE_PARENTS) {
+ for (ncp = LIST_FIRST(&vp->v_nclist); ncp != NULL;
+ ncp = ncnext) {
+ ncnext = LIST_NEXT(ncp, nc_vlist);
+ cache_remove(ncp);
+ cache_free(ncp);
+ }
}
- for (ncp = LIST_FIRST(&vp->v_dnclist); ncp != NULL; ncp = ncnext) {
- ncnext = LIST_NEXT(ncp, nc_dvlist);
- cache_remove(ncp);
- cache_free(ncp);
+ if (flags & PURGE_CHILDREN) {
+ for (ncp = LIST_FIRST(&vp->v_dnclist); ncp != NULL;
+ ncp = ncnext) {
+ ncnext = LIST_NEXT(ncp, nc_dvlist);
+ cache_remove(ncp);
+ cache_free(ncp);
+ }
+ }
+ if (cnp != NULL) {
+ ncp = cache_lookup_entry(vp, cnp);
+ if (ncp) {
+ cache_remove(ncp);
+ cache_free(ncp);
+ }
}
simple_unlock(&namecache_slock);
}
--NextPart-20040320154242-0151500--