xref: /csrg-svn/sys/kern/vfs_cache.c (revision 68581)
137487Smckusick /*
268534Smckusick  * Copyright (c) 1989, 1993, 1995
363180Sbostic  *	The Regents of the University of California.  All rights reserved.
437487Smckusick  *
568534Smckusick  * This code is derived from software contributed to Berkeley by
668534Smckusick  * Poul-Henning Kamp of the FreeBSD Project.
768534Smckusick  *
844455Sbostic  * %sccs.include.redist.c%
937487Smckusick  *
1068534Smckusick  * from: vfs_cache.c,v 1.11 1995/03/12 02:01:20 phk Exp $
1168534Smckusick  *
12*68581Smckusick  *	@(#)vfs_cache.c	8.5 (Berkeley) 03/22/95
1337487Smckusick  */
1437487Smckusick 
1556517Sbostic #include <sys/param.h>
1656517Sbostic #include <sys/systm.h>
1756517Sbostic #include <sys/time.h>
1856517Sbostic #include <sys/mount.h>
1956517Sbostic #include <sys/vnode.h>
2056517Sbostic #include <sys/namei.h>
2156517Sbostic #include <sys/errno.h>
2256517Sbostic #include <sys/malloc.h>
2337487Smckusick 
2437487Smckusick /*
2537487Smckusick  * Name caching works as follows:
2637487Smckusick  *
2737487Smckusick  * Names found by directory scans are retained in a cache
2837487Smckusick  * for future reference.  It is managed LRU, so frequently
2937487Smckusick  * used names will hang around.  Cache is indexed by hash value
3038768Smckusick  * obtained from (vp, name) where vp refers to the directory
3138768Smckusick  * containing name.
3237487Smckusick  *
3368534Smckusick  * If it is a "negative" entry, (i.e. for a name that is known NOT to
3468534Smckusick  * exist) the vnode pointer will be NULL.
3568534Smckusick  *
3637487Smckusick  * For simplicity (and economy of storage), names longer than
3737487Smckusick  * a maximum length of NCHNAMLEN are not cached; they occur
3837487Smckusick  * infrequently in any case, and are almost never of interest.
3937487Smckusick  *
4037487Smckusick  * Upon reaching the last segment of a path, if the reference
4137487Smckusick  * is for DELETE, or NOCACHE is set (rewrite), and the
4237487Smckusick  * name is located in the cache, it will be dropped.
4337487Smckusick  */
4437487Smckusick 
4537487Smckusick /*
4637487Smckusick  * Structures associated with name cacheing.
4737487Smckusick  */
4868534Smckusick #define NCHHASH(dvp, cnp) \
4968534Smckusick 	(&nchashtbl[((dvp)->v_id + (cnp)->cn_hash) & nchash])
5068534Smckusick LIST_HEAD(nchashhead, namecache) *nchashtbl;	/* Hash Table */
5140881Smckusick u_long	nchash;				/* size of hash table - 1 */
5240881Smckusick long	numcache;			/* number of cache entries allocated */
5368534Smckusick TAILQ_HEAD(, namecache) nclruhead;	/* LRU chain */
5437487Smckusick struct	nchstats nchstats;		/* cache effectiveness statistics */
5537487Smckusick 
5638768Smckusick int doingcache = 1;			/* 1 => enable the cache */
5738768Smckusick 
5837487Smckusick /*
5968534Smckusick  * Delete an entry from its hash list and move it to the front
6068534Smckusick  * of the LRU list for immediate reuse.
6168534Smckusick  */
6268534Smckusick #define PURGE(ncp)  {						\
6368534Smckusick 	LIST_REMOVE(ncp, nc_hash);				\
6468534Smckusick 	ncp->nc_hash.le_prev = 0;				\
6568534Smckusick 	TAILQ_REMOVE(&nclruhead, ncp, nc_lru);			\
6668534Smckusick 	TAILQ_INSERT_HEAD(&nclruhead, ncp, nc_lru);		\
6768534Smckusick }
6868534Smckusick 
6968534Smckusick /*
7068534Smckusick  * Move an entry that has been used to the tail of the LRU list
7168534Smckusick  * so that it will be preserved for future use.
7268534Smckusick  */
7368534Smckusick #define TOUCH(ncp)  {						\
7468534Smckusick 	if (ncp->nc_lru.tqe_next != 0) {			\
7568534Smckusick 		TAILQ_REMOVE(&nclruhead, ncp, nc_lru);		\
7668534Smckusick 		TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru);	\
7768534Smckusick 	}							\
7868534Smckusick }
7968534Smckusick 
8068534Smckusick /*
8168534Smckusick  * Lookup an entry in the cache
8268534Smckusick  *
8368534Smckusick  * We don't do this if the segment name is long, simply so the cache
8468534Smckusick  * can avoid holding long names (which would either waste space, or
8537487Smckusick  * add greatly to the complexity).
8638768Smckusick  *
8768534Smckusick  * Lookup is called with dvp pointing to the directory to search,
8868534Smckusick  * cnp pointing to the name of the entry being sought. If the lookup
8968534Smckusick  * succeeds, the vnode is returned in *vpp, and a status of -1 is
9068534Smckusick  * returned. If the lookup determines that the name does not exist
9168534Smckusick  * (negative cacheing), a status of ENOENT is returned. If the lookup
9268534Smckusick  * fails, a status of zero is returned.
9337487Smckusick  */
9468534Smckusick 
9552231Sheideman int
cache_lookup(dvp,vpp,cnp)9652306Sheideman cache_lookup(dvp, vpp, cnp)
9752231Sheideman 	struct vnode *dvp;
9852231Sheideman 	struct vnode **vpp;
9952231Sheideman 	struct componentname *cnp;
10037487Smckusick {
10168534Smckusick 	register struct namecache *ncp, *nnp;
10267732Smckusick 	register struct nchashhead *ncpp;
10337487Smckusick 
10467490Smckusick 	if (!doingcache) {
10567490Smckusick 		cnp->cn_flags &= ~MAKEENTRY;
10638768Smckusick 		return (0);
10767490Smckusick 	}
10852231Sheideman 	if (cnp->cn_namelen > NCHNAMLEN) {
10937487Smckusick 		nchstats.ncs_long++;
11052231Sheideman 		cnp->cn_flags &= ~MAKEENTRY;
11137487Smckusick 		return (0);
11237487Smckusick 	}
11368534Smckusick 
11468534Smckusick 	ncpp = NCHHASH(dvp, cnp);
11568534Smckusick 	for (ncp = ncpp->lh_first; ncp != 0; ncp = nnp) {
11668534Smckusick 		nnp = ncp->nc_hash.le_next;
11768534Smckusick 		/* If one of the vp's went stale, don't bother anymore. */
11868534Smckusick 		if ((ncp->nc_dvpid != ncp->nc_dvp->v_id) ||
11968534Smckusick 		    (ncp->nc_vp && ncp->nc_vpid != ncp->nc_vp->v_id)) {
12068534Smckusick 			nchstats.ncs_falsehits++;
12168534Smckusick 			PURGE(ncp);
12268534Smckusick 			continue;
12368534Smckusick 		}
12468534Smckusick 		/* Now that we know the vp's to be valid, is it ours ? */
12538768Smckusick 		if (ncp->nc_dvp == dvp &&
12652231Sheideman 		    ncp->nc_nlen == cnp->cn_namelen &&
12755544Smckusick 		    !bcmp(ncp->nc_name, cnp->cn_nameptr, (u_int)ncp->nc_nlen))
12837487Smckusick 			break;
12937487Smckusick 	}
13068534Smckusick 
13168534Smckusick 	/* We failed to find an entry */
13267732Smckusick 	if (ncp == 0) {
13337487Smckusick 		nchstats.ncs_miss++;
13437487Smckusick 		return (0);
13537487Smckusick 	}
13668534Smckusick 
13768534Smckusick 	/* We don't want to have an entry, so dump it */
13867732Smckusick 	if ((cnp->cn_flags & MAKEENTRY) == 0) {
13938768Smckusick 		nchstats.ncs_badhits++;
14068534Smckusick 		PURGE(ncp);
14168534Smckusick 		return (0);
14268534Smckusick 	}
14368534Smckusick 
14468534Smckusick 	/* We found a "positive" match, return the vnode */
14568534Smckusick         if (ncp->nc_vp) {
14637487Smckusick 		nchstats.ncs_goodhits++;
14768534Smckusick 		TOUCH(ncp);
14852231Sheideman 		*vpp = ncp->nc_vp;
14938768Smckusick 		return (-1);
15037487Smckusick 	}
15137487Smckusick 
15268534Smckusick 	/* We found a negative match, and want to create it, so purge */
15368534Smckusick 	if (cnp->cn_nameiop == CREATE) {
15468534Smckusick 		nchstats.ncs_badhits++;
15568534Smckusick 		PURGE(ncp);
15668534Smckusick 		return (0);
15768534Smckusick 	}
15868534Smckusick 
159*68581Smckusick 	/*
160*68581Smckusick 	 * We found a "negative" match, ENOENT notifies client of this match.
161*68581Smckusick 	 * The nc_vpid field records whether this is a whiteout.
162*68581Smckusick 	 */
16368534Smckusick 	nchstats.ncs_neghits++;
16468534Smckusick 	TOUCH(ncp);
165*68581Smckusick 	cnp->cn_flags |= ncp->nc_vpid;
16668534Smckusick 	return (ENOENT);
16737487Smckusick }
16837487Smckusick 
16937487Smckusick /*
17068534Smckusick  * Add an entry to the cache.
17137487Smckusick  */
17268534Smckusick void
cache_enter(dvp,vp,cnp)17352306Sheideman cache_enter(dvp, vp, cnp)
17452231Sheideman 	struct vnode *dvp;
17552231Sheideman 	struct vnode *vp;
17652231Sheideman 	struct componentname *cnp;
17737487Smckusick {
17867732Smckusick 	register struct namecache *ncp;
17967732Smckusick 	register struct nchashhead *ncpp;
18037487Smckusick 
18168534Smckusick 	if (!doingcache)
18268534Smckusick 		return;
18368534Smckusick 
18455185Smckusick #ifdef DIAGNOSTIC
18555185Smckusick 	if (cnp->cn_namelen > NCHNAMLEN)
18655185Smckusick 		panic("cache_enter: name too long");
18755185Smckusick #endif
18868534Smckusick 
18937487Smckusick 	/*
19068534Smckusick 	 * We allocate a new entry if we are less than the maximum
19168534Smckusick 	 * allowed and the one at the front of the LRU list is in use.
19268534Smckusick 	 * Otherwise we use the one at the front of the LRU list.
19337487Smckusick 	 */
19468534Smckusick 	if (numcache < desiredvnodes &&
19568534Smckusick 	    ((ncp = nclruhead.tqh_first) == NULL ||
19668534Smckusick 	    ncp->nc_hash.le_prev != 0)) {
19768534Smckusick 		/* Add one more entry */
19840881Smckusick 		ncp = (struct namecache *)
19945117Smckusick 			malloc((u_long)sizeof *ncp, M_CACHE, M_WAITOK);
20040881Smckusick 		bzero((char *)ncp, sizeof *ncp);
20140881Smckusick 		numcache++;
20267732Smckusick 	} else if (ncp = nclruhead.tqh_first) {
20368534Smckusick 		/* reuse an old entry */
20467732Smckusick 		TAILQ_REMOVE(&nclruhead, ncp, nc_lru);
20567732Smckusick 		if (ncp->nc_hash.le_prev != 0) {
20667732Smckusick 			LIST_REMOVE(ncp, nc_hash);
20767732Smckusick 			ncp->nc_hash.le_prev = 0;
20855699Smckusick 		}
20968534Smckusick 	} else {
21068534Smckusick 		/* give up */
21140881Smckusick 		return;
21268534Smckusick 	}
21368534Smckusick 
214*68581Smckusick 	/*
215*68581Smckusick 	 * Fill in cache info, if vp is NULL this is a "negative" cache entry.
216*68581Smckusick 	 * For negative entries, we have to record whether it is a whiteout.
217*68581Smckusick 	 * the whiteout flag is stored in the nc_vpid field which is
218*68581Smckusick 	 * otherwise unused.
219*68581Smckusick 	 */
22052231Sheideman 	ncp->nc_vp = vp;
22152231Sheideman 	if (vp)
22252231Sheideman 		ncp->nc_vpid = vp->v_id;
22340881Smckusick 	else
224*68581Smckusick 		ncp->nc_vpid = cnp->cn_flags & ISWHITEOUT;
22552231Sheideman 	ncp->nc_dvp = dvp;
22652231Sheideman 	ncp->nc_dvpid = dvp->v_id;
22752231Sheideman 	ncp->nc_nlen = cnp->cn_namelen;
22852231Sheideman 	bcopy(cnp->cn_nameptr, ncp->nc_name, (unsigned)ncp->nc_nlen);
22967732Smckusick 	TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru);
23068534Smckusick 	ncpp = NCHHASH(dvp, cnp);
23167732Smckusick 	LIST_INSERT_HEAD(ncpp, ncp, nc_hash);
23237487Smckusick }
23337487Smckusick 
23437487Smckusick /*
23540881Smckusick  * Name cache initialization, from vfs_init() when we are booting
23637487Smckusick  */
23768534Smckusick void
nchinit()23837487Smckusick nchinit()
23937487Smckusick {
24037487Smckusick 
24167732Smckusick 	TAILQ_INIT(&nclruhead);
24255544Smckusick 	nchashtbl = hashinit(desiredvnodes, M_CACHE, &nchash);
24337487Smckusick }
24437487Smckusick 
24537487Smckusick /*
24668534Smckusick  * Invalidate a all entries to particular vnode.
24768534Smckusick  *
24868534Smckusick  * We actually just increment the v_id, that will do it. The entries will
24968534Smckusick  * be purged by lookup as they get found. If the v_id wraps around, we
25068534Smckusick  * need to ditch the entire cache, to avoid confusion. No valid vnode will
25168534Smckusick  * ever have (v_id == 0).
25237487Smckusick  */
25368534Smckusick void
cache_purge(vp)25437487Smckusick cache_purge(vp)
25538768Smckusick 	struct vnode *vp;
25637487Smckusick {
25767732Smckusick 	struct namecache *ncp;
25867732Smckusick 	struct nchashhead *ncpp;
25937487Smckusick 
26038768Smckusick 	vp->v_id = ++nextvnodeid;
26138768Smckusick 	if (nextvnodeid != 0)
26238768Smckusick 		return;
26355544Smckusick 	for (ncpp = &nchashtbl[nchash]; ncpp >= nchashtbl; ncpp--) {
26468534Smckusick 		while (ncp = ncpp->lh_first)
26568534Smckusick 			PURGE(ncp);
26637487Smckusick 	}
26738768Smckusick 	vp->v_id = ++nextvnodeid;
26837487Smckusick }
26937487Smckusick 
27037487Smckusick /*
27168534Smckusick  * Flush all entries referencing a particular filesystem.
27237487Smckusick  *
27368534Smckusick  * Since we need to check it anyway, we will flush all the invalid
27468534Smckusick  * entriess at the same time.
27537487Smckusick  */
27668534Smckusick void
cache_purgevfs(mp)27737487Smckusick cache_purgevfs(mp)
27845117Smckusick 	struct mount *mp;
27937487Smckusick {
28068534Smckusick 	struct nchashhead *ncpp;
28168534Smckusick 	struct namecache *ncp, *nnp;
28237487Smckusick 
28368534Smckusick 	/* Scan hash tables for applicable entries */
28468534Smckusick 	for (ncpp = &nchashtbl[nchash]; ncpp >= nchashtbl; ncpp--) {
28568534Smckusick 		for (ncp = ncpp->lh_first; ncp != 0; ncp = nnp) {
28668534Smckusick 			nnp = ncp->nc_hash.le_next;
28768534Smckusick 			if (ncp->nc_dvpid != ncp->nc_dvp->v_id ||
28868534Smckusick 			    (ncp->nc_vp && ncp->nc_vpid != ncp->nc_vp->v_id) ||
28968534Smckusick 			    ncp->nc_dvp->v_mount == mp) {
29068534Smckusick 				PURGE(ncp);
29168534Smckusick 			}
29255544Smckusick 		}
29337487Smckusick 	}
29437487Smckusick }
295