[prev in list] [next in list] [prev in thread] [next in thread]
List: netbsd-tech-kern
Subject: cache_purge
From: YAMAMOTO Takashi <yamt () mwd ! biglobe ! ne ! jp>
Date: 2004-03-20 7:03:36
Message-ID: 1079766216.741327.626.nullmailer () yamt ! dyndns ! org
[Download RAW message or body]
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
["cache_purge1.diff" (Text/Plain)]
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);
}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic