xref: /csrg-svn/sys/kern/vfs_cache.c (revision 68534)
137487Smckusick /*
2*68534Smckusick  * Copyright (c) 1989, 1993, 1995
363180Sbostic  *	The Regents of the University of California.  All rights reserved.
437487Smckusick  *
5*68534Smckusick  * This code is derived from software contributed to Berkeley by
6*68534Smckusick  * Poul-Henning Kamp of the FreeBSD Project.
7*68534Smckusick  *
844455Sbostic  * %sccs.include.redist.c%
937487Smckusick  *
10*68534Smckusick  * from: vfs_cache.c,v 1.11 1995/03/12 02:01:20 phk Exp $
11*68534Smckusick  *
12*68534Smckusick  *	@(#)vfs_cache.c	8.4 (Berkeley) 03/18/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  *
33*68534Smckusick  * If it is a "negative" entry, (i.e. for a name that is known NOT to
34*68534Smckusick  * exist) the vnode pointer will be NULL.
35*68534Smckusick  *
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  */
48*68534Smckusick #define NCHHASH(dvp, cnp) \
49*68534Smckusick 	(&nchashtbl[((dvp)->v_id + (cnp)->cn_hash) & nchash])
50*68534Smckusick LIST_HEAD(nchashhead, namecache) *nchashtbl;	/* Hash Table */
5140881Smckusick u_long	nchash;				/* size of hash table - 1 */
5240881Smckusick long	numcache;			/* number of cache entries allocated */
53*68534Smckusick TAILQ_HEAD(, namecache) nclruhead;	/* LRU chain */
5437487Smckusick struct	nchstats nchstats;		/* cache effectiveness statistics */
5537487Smckusick 
5638768Smckusick int doingcache = 1;			/* 1 => enable the cache */
5738768Smckusick 
5837487Smckusick /*
59*68534Smckusick  * Delete an entry from its hash list and move it to the front
60*68534Smckusick  * of the LRU list for immediate reuse.
61*68534Smckusick  */
62*68534Smckusick #define PURGE(ncp)  {						\
63*68534Smckusick 	LIST_REMOVE(ncp, nc_hash);				\
64*68534Smckusick 	ncp->nc_hash.le_prev = 0;				\
65*68534Smckusick 	TAILQ_REMOVE(&nclruhead, ncp, nc_lru);			\
66*68534Smckusick 	TAILQ_INSERT_HEAD(&nclruhead, ncp, nc_lru);		\
67*68534Smckusick }
68*68534Smckusick 
69*68534Smckusick /*
70*68534Smckusick  * Move an entry that has been used to the tail of the LRU list
71*68534Smckusick  * so that it will be preserved for future use.
72*68534Smckusick  */
73*68534Smckusick #define TOUCH(ncp)  {						\
74*68534Smckusick 	if (ncp->nc_lru.tqe_next != 0) {			\
75*68534Smckusick 		TAILQ_REMOVE(&nclruhead, ncp, nc_lru);		\
76*68534Smckusick 		TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru);	\
77*68534Smckusick 	}							\
78*68534Smckusick }
79*68534Smckusick 
80*68534Smckusick /*
81*68534Smckusick  * Lookup an entry in the cache
82*68534Smckusick  *
83*68534Smckusick  * We don't do this if the segment name is long, simply so the cache
84*68534Smckusick  * can avoid holding long names (which would either waste space, or
8537487Smckusick  * add greatly to the complexity).
8638768Smckusick  *
87*68534Smckusick  * Lookup is called with dvp pointing to the directory to search,
88*68534Smckusick  * cnp pointing to the name of the entry being sought. If the lookup
89*68534Smckusick  * succeeds, the vnode is returned in *vpp, and a status of -1 is
90*68534Smckusick  * returned. If the lookup determines that the name does not exist
91*68534Smckusick  * (negative cacheing), a status of ENOENT is returned. If the lookup
92*68534Smckusick  * fails, a status of zero is returned.
9337487Smckusick  */
94*68534Smckusick 
9552231Sheideman int
9652306Sheideman cache_lookup(dvp, vpp, cnp)
9752231Sheideman 	struct vnode *dvp;
9852231Sheideman 	struct vnode **vpp;
9952231Sheideman 	struct componentname *cnp;
10037487Smckusick {
101*68534Smckusick 	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 	}
113*68534Smckusick 
114*68534Smckusick 	ncpp = NCHHASH(dvp, cnp);
115*68534Smckusick 	for (ncp = ncpp->lh_first; ncp != 0; ncp = nnp) {
116*68534Smckusick 		nnp = ncp->nc_hash.le_next;
117*68534Smckusick 		/* If one of the vp's went stale, don't bother anymore. */
118*68534Smckusick 		if ((ncp->nc_dvpid != ncp->nc_dvp->v_id) ||
119*68534Smckusick 		    (ncp->nc_vp && ncp->nc_vpid != ncp->nc_vp->v_id)) {
120*68534Smckusick 			nchstats.ncs_falsehits++;
121*68534Smckusick 			PURGE(ncp);
122*68534Smckusick 			continue;
123*68534Smckusick 		}
124*68534Smckusick 		/* 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 	}
130*68534Smckusick 
131*68534Smckusick 	/* We failed to find an entry */
13267732Smckusick 	if (ncp == 0) {
13337487Smckusick 		nchstats.ncs_miss++;
13437487Smckusick 		return (0);
13537487Smckusick 	}
136*68534Smckusick 
137*68534Smckusick 	/* We don't want to have an entry, so dump it */
13867732Smckusick 	if ((cnp->cn_flags & MAKEENTRY) == 0) {
13938768Smckusick 		nchstats.ncs_badhits++;
140*68534Smckusick 		PURGE(ncp);
141*68534Smckusick 		return (0);
142*68534Smckusick 	}
143*68534Smckusick 
144*68534Smckusick 	/* We found a "positive" match, return the vnode */
145*68534Smckusick         if (ncp->nc_vp) {
14637487Smckusick 		nchstats.ncs_goodhits++;
147*68534Smckusick 		TOUCH(ncp);
14852231Sheideman 		*vpp = ncp->nc_vp;
14938768Smckusick 		return (-1);
15037487Smckusick 	}
15137487Smckusick 
152*68534Smckusick 	/* We found a negative match, and want to create it, so purge */
153*68534Smckusick 	if (cnp->cn_nameiop == CREATE) {
154*68534Smckusick 		nchstats.ncs_badhits++;
155*68534Smckusick 		PURGE(ncp);
156*68534Smckusick 		return (0);
157*68534Smckusick 	}
158*68534Smckusick 
159*68534Smckusick 	/* We found a "negative" match, ENOENT notifies client of this match */
160*68534Smckusick 	nchstats.ncs_neghits++;
161*68534Smckusick 	TOUCH(ncp);
162*68534Smckusick 	return (ENOENT);
16337487Smckusick }
16437487Smckusick 
16537487Smckusick /*
166*68534Smckusick  * Add an entry to the cache.
16737487Smckusick  */
168*68534Smckusick void
16952306Sheideman cache_enter(dvp, vp, cnp)
17052231Sheideman 	struct vnode *dvp;
17152231Sheideman 	struct vnode *vp;
17252231Sheideman 	struct componentname *cnp;
17337487Smckusick {
17467732Smckusick 	register struct namecache *ncp;
17567732Smckusick 	register struct nchashhead *ncpp;
17637487Smckusick 
177*68534Smckusick 	if (!doingcache)
178*68534Smckusick 		return;
179*68534Smckusick 
18055185Smckusick #ifdef DIAGNOSTIC
18155185Smckusick 	if (cnp->cn_namelen > NCHNAMLEN)
18255185Smckusick 		panic("cache_enter: name too long");
18355185Smckusick #endif
184*68534Smckusick 
18537487Smckusick 	/*
186*68534Smckusick 	 * We allocate a new entry if we are less than the maximum
187*68534Smckusick 	 * allowed and the one at the front of the LRU list is in use.
188*68534Smckusick 	 * Otherwise we use the one at the front of the LRU list.
18937487Smckusick 	 */
190*68534Smckusick 	if (numcache < desiredvnodes &&
191*68534Smckusick 	    ((ncp = nclruhead.tqh_first) == NULL ||
192*68534Smckusick 	    ncp->nc_hash.le_prev != 0)) {
193*68534Smckusick 		/* Add one more entry */
19440881Smckusick 		ncp = (struct namecache *)
19545117Smckusick 			malloc((u_long)sizeof *ncp, M_CACHE, M_WAITOK);
19640881Smckusick 		bzero((char *)ncp, sizeof *ncp);
19740881Smckusick 		numcache++;
19867732Smckusick 	} else if (ncp = nclruhead.tqh_first) {
199*68534Smckusick 		/* reuse an old entry */
20067732Smckusick 		TAILQ_REMOVE(&nclruhead, ncp, nc_lru);
20167732Smckusick 		if (ncp->nc_hash.le_prev != 0) {
20267732Smckusick 			LIST_REMOVE(ncp, nc_hash);
20367732Smckusick 			ncp->nc_hash.le_prev = 0;
20455699Smckusick 		}
205*68534Smckusick 	} else {
206*68534Smckusick 		/* give up */
20740881Smckusick 		return;
208*68534Smckusick 	}
209*68534Smckusick 
210*68534Smckusick 	/* fill in cache info, if vp is NULL this is a "negative" cache entry */
21152231Sheideman 	ncp->nc_vp = vp;
21252231Sheideman 	if (vp)
21352231Sheideman 		ncp->nc_vpid = vp->v_id;
21440881Smckusick 	else
21540881Smckusick 		ncp->nc_vpid = 0;
21652231Sheideman 	ncp->nc_dvp = dvp;
21752231Sheideman 	ncp->nc_dvpid = dvp->v_id;
21852231Sheideman 	ncp->nc_nlen = cnp->cn_namelen;
21952231Sheideman 	bcopy(cnp->cn_nameptr, ncp->nc_name, (unsigned)ncp->nc_nlen);
22067732Smckusick 	TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru);
221*68534Smckusick 	ncpp = NCHHASH(dvp, cnp);
22267732Smckusick 	LIST_INSERT_HEAD(ncpp, ncp, nc_hash);
22337487Smckusick }
22437487Smckusick 
22537487Smckusick /*
22640881Smckusick  * Name cache initialization, from vfs_init() when we are booting
22737487Smckusick  */
228*68534Smckusick void
22937487Smckusick nchinit()
23037487Smckusick {
23137487Smckusick 
23267732Smckusick 	TAILQ_INIT(&nclruhead);
23355544Smckusick 	nchashtbl = hashinit(desiredvnodes, M_CACHE, &nchash);
23437487Smckusick }
23537487Smckusick 
23637487Smckusick /*
237*68534Smckusick  * Invalidate a all entries to particular vnode.
238*68534Smckusick  *
239*68534Smckusick  * We actually just increment the v_id, that will do it. The entries will
240*68534Smckusick  * be purged by lookup as they get found. If the v_id wraps around, we
241*68534Smckusick  * need to ditch the entire cache, to avoid confusion. No valid vnode will
242*68534Smckusick  * ever have (v_id == 0).
24337487Smckusick  */
244*68534Smckusick void
24537487Smckusick cache_purge(vp)
24638768Smckusick 	struct vnode *vp;
24737487Smckusick {
24867732Smckusick 	struct namecache *ncp;
24967732Smckusick 	struct nchashhead *ncpp;
25037487Smckusick 
25138768Smckusick 	vp->v_id = ++nextvnodeid;
25238768Smckusick 	if (nextvnodeid != 0)
25338768Smckusick 		return;
25455544Smckusick 	for (ncpp = &nchashtbl[nchash]; ncpp >= nchashtbl; ncpp--) {
255*68534Smckusick 		while (ncp = ncpp->lh_first)
256*68534Smckusick 			PURGE(ncp);
25737487Smckusick 	}
25838768Smckusick 	vp->v_id = ++nextvnodeid;
25937487Smckusick }
26037487Smckusick 
26137487Smckusick /*
262*68534Smckusick  * Flush all entries referencing a particular filesystem.
26337487Smckusick  *
264*68534Smckusick  * Since we need to check it anyway, we will flush all the invalid
265*68534Smckusick  * entriess at the same time.
26637487Smckusick  */
267*68534Smckusick void
26837487Smckusick cache_purgevfs(mp)
26945117Smckusick 	struct mount *mp;
27037487Smckusick {
271*68534Smckusick 	struct nchashhead *ncpp;
272*68534Smckusick 	struct namecache *ncp, *nnp;
27337487Smckusick 
274*68534Smckusick 	/* Scan hash tables for applicable entries */
275*68534Smckusick 	for (ncpp = &nchashtbl[nchash]; ncpp >= nchashtbl; ncpp--) {
276*68534Smckusick 		for (ncp = ncpp->lh_first; ncp != 0; ncp = nnp) {
277*68534Smckusick 			nnp = ncp->nc_hash.le_next;
278*68534Smckusick 			if (ncp->nc_dvpid != ncp->nc_dvp->v_id ||
279*68534Smckusick 			    (ncp->nc_vp && ncp->nc_vpid != ncp->nc_vp->v_id) ||
280*68534Smckusick 			    ncp->nc_dvp->v_mount == mp) {
281*68534Smckusick 				PURGE(ncp);
282*68534Smckusick 			}
28355544Smckusick 		}
28437487Smckusick 	}
28537487Smckusick }
286