xref: /original-bsd/sys/kern/vfs_cache.c (revision deff14a8)
1 /*
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)vfs_cache.c	8.3 (Berkeley) 08/22/94
8  */
9 
10 #include <sys/param.h>
11 #include <sys/systm.h>
12 #include <sys/time.h>
13 #include <sys/mount.h>
14 #include <sys/vnode.h>
15 #include <sys/namei.h>
16 #include <sys/errno.h>
17 #include <sys/malloc.h>
18 
19 /*
20  * Name caching works as follows:
21  *
22  * Names found by directory scans are retained in a cache
23  * for future reference.  It is managed LRU, so frequently
24  * used names will hang around.  Cache is indexed by hash value
25  * obtained from (vp, name) where vp refers to the directory
26  * containing name.
27  *
28  * For simplicity (and economy of storage), names longer than
29  * a maximum length of NCHNAMLEN are not cached; they occur
30  * infrequently in any case, and are almost never of interest.
31  *
32  * Upon reaching the last segment of a path, if the reference
33  * is for DELETE, or NOCACHE is set (rewrite), and the
34  * name is located in the cache, it will be dropped.
35  */
36 
37 /*
38  * Structures associated with name cacheing.
39  */
40 LIST_HEAD(nchashhead, namecache) *nchashtbl;
41 u_long	nchash;				/* size of hash table - 1 */
42 long	numcache;			/* number of cache entries allocated */
43 TAILQ_HEAD(, namecache) nclruhead;		/* LRU chain */
44 struct	nchstats nchstats;		/* cache effectiveness statistics */
45 
46 int doingcache = 1;			/* 1 => enable the cache */
47 
48 /*
49  * Look for a the name in the cache. We don't do this
50  * if the segment name is long, simply so the cache can avoid
51  * holding long names (which would either waste space, or
52  * add greatly to the complexity).
53  *
54  * Lookup is called with ni_dvp pointing to the directory to search,
55  * ni_ptr pointing to the name of the entry being sought, ni_namelen
56  * tells the length of the name, and ni_hash contains a hash of
57  * the name. If the lookup succeeds, the vnode is returned in ni_vp
58  * and a status of -1 is returned. If the lookup determines that
59  * the name does not exist (negative cacheing), a status of ENOENT
60  * is returned. If the lookup fails, a status of zero is returned.
61  */
62 int
63 cache_lookup(dvp, vpp, cnp)
64 	struct vnode *dvp;
65 	struct vnode **vpp;
66 	struct componentname *cnp;
67 {
68 	register struct namecache *ncp;
69 	register struct nchashhead *ncpp;
70 
71 	if (!doingcache) {
72 		cnp->cn_flags &= ~MAKEENTRY;
73 		return (0);
74 	}
75 	if (cnp->cn_namelen > NCHNAMLEN) {
76 		nchstats.ncs_long++;
77 		cnp->cn_flags &= ~MAKEENTRY;
78 		return (0);
79 	}
80 	ncpp = &nchashtbl[cnp->cn_hash & nchash];
81 	for (ncp = ncpp->lh_first; ncp != 0; ncp = ncp->nc_hash.le_next) {
82 		if (ncp->nc_dvp == dvp &&
83 		    ncp->nc_dvpid == dvp->v_id &&
84 		    ncp->nc_nlen == cnp->cn_namelen &&
85 		    !bcmp(ncp->nc_name, cnp->cn_nameptr, (u_int)ncp->nc_nlen))
86 			break;
87 	}
88 	if (ncp == 0) {
89 		nchstats.ncs_miss++;
90 		return (0);
91 	}
92 	if ((cnp->cn_flags & MAKEENTRY) == 0) {
93 		nchstats.ncs_badhits++;
94 	} else if (ncp->nc_vp == NULL) {
95 		if (cnp->cn_nameiop != CREATE) {
96 			nchstats.ncs_neghits++;
97 			/*
98 			 * Move this slot to end of LRU chain,
99 			 * if not already there.
100 			 */
101 			if (ncp->nc_lru.tqe_next != 0) {
102 				TAILQ_REMOVE(&nclruhead, ncp, nc_lru);
103 				TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru);
104 			}
105 			return (ENOENT);
106 		}
107 	} else if (ncp->nc_vpid != ncp->nc_vp->v_id) {
108 		nchstats.ncs_falsehits++;
109 	} else {
110 		nchstats.ncs_goodhits++;
111 		/*
112 		 * move this slot to end of LRU chain, if not already there
113 		 */
114 		if (ncp->nc_lru.tqe_next != 0) {
115 			TAILQ_REMOVE(&nclruhead, ncp, nc_lru);
116 			TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru);
117 		}
118 		*vpp = ncp->nc_vp;
119 		return (-1);
120 	}
121 
122 	/*
123 	 * Last component and we are renaming or deleting,
124 	 * the cache entry is invalid, or otherwise don't
125 	 * want cache entry to exist.
126 	 */
127 	TAILQ_REMOVE(&nclruhead, ncp, nc_lru);
128 	LIST_REMOVE(ncp, nc_hash);
129 	ncp->nc_hash.le_prev = 0;
130 	TAILQ_INSERT_HEAD(&nclruhead, ncp, nc_lru);
131 	return (0);
132 }
133 
134 /*
135  * Add an entry to the cache
136  */
137 cache_enter(dvp, vp, cnp)
138 	struct vnode *dvp;
139 	struct vnode *vp;
140 	struct componentname *cnp;
141 {
142 	register struct namecache *ncp;
143 	register struct nchashhead *ncpp;
144 
145 #ifdef DIAGNOSTIC
146 	if (cnp->cn_namelen > NCHNAMLEN)
147 		panic("cache_enter: name too long");
148 #endif
149 	if (!doingcache)
150 		return;
151 	/*
152 	 * Free the cache slot at head of lru chain.
153 	 */
154 	if (numcache < desiredvnodes) {
155 		ncp = (struct namecache *)
156 			malloc((u_long)sizeof *ncp, M_CACHE, M_WAITOK);
157 		bzero((char *)ncp, sizeof *ncp);
158 		numcache++;
159 	} else if (ncp = nclruhead.tqh_first) {
160 		TAILQ_REMOVE(&nclruhead, ncp, nc_lru);
161 		if (ncp->nc_hash.le_prev != 0) {
162 			LIST_REMOVE(ncp, nc_hash);
163 			ncp->nc_hash.le_prev = 0;
164 		}
165 	} else
166 		return;
167 	/* grab the vnode we just found */
168 	ncp->nc_vp = vp;
169 	if (vp)
170 		ncp->nc_vpid = vp->v_id;
171 	else
172 		ncp->nc_vpid = 0;
173 	/* fill in cache info */
174 	ncp->nc_dvp = dvp;
175 	ncp->nc_dvpid = dvp->v_id;
176 	ncp->nc_nlen = cnp->cn_namelen;
177 	bcopy(cnp->cn_nameptr, ncp->nc_name, (unsigned)ncp->nc_nlen);
178 	TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru);
179 	ncpp = &nchashtbl[cnp->cn_hash & nchash];
180 	LIST_INSERT_HEAD(ncpp, ncp, nc_hash);
181 }
182 
183 /*
184  * Name cache initialization, from vfs_init() when we are booting
185  */
186 nchinit()
187 {
188 
189 	TAILQ_INIT(&nclruhead);
190 	nchashtbl = hashinit(desiredvnodes, M_CACHE, &nchash);
191 }
192 
193 /*
194  * Cache flush, a particular vnode; called when a vnode is renamed to
195  * hide entries that would now be invalid
196  */
197 cache_purge(vp)
198 	struct vnode *vp;
199 {
200 	struct namecache *ncp;
201 	struct nchashhead *ncpp;
202 
203 	vp->v_id = ++nextvnodeid;
204 	if (nextvnodeid != 0)
205 		return;
206 	for (ncpp = &nchashtbl[nchash]; ncpp >= nchashtbl; ncpp--) {
207 		for (ncp = ncpp->lh_first; ncp != 0; ncp = ncp->nc_hash.le_next) {
208 			ncp->nc_vpid = 0;
209 			ncp->nc_dvpid = 0;
210 		}
211 	}
212 	vp->v_id = ++nextvnodeid;
213 }
214 
215 /*
216  * Cache flush, a whole filesystem; called when filesys is umounted to
217  * remove entries that would now be invalid
218  *
219  * The line "nxtcp = nchhead" near the end is to avoid potential problems
220  * if the cache lru chain is modified while we are dumping the
221  * inode.  This makes the algorithm O(n^2), but do you think I care?
222  */
223 cache_purgevfs(mp)
224 	struct mount *mp;
225 {
226 	register struct namecache *ncp, *nxtcp;
227 
228 	for (ncp = nclruhead.tqh_first; ncp != 0; ncp = nxtcp) {
229 		if (ncp->nc_dvp == NULL || ncp->nc_dvp->v_mount != mp) {
230 			nxtcp = ncp->nc_lru.tqe_next;
231 			continue;
232 		}
233 		/* free the resources we had */
234 		ncp->nc_vp = NULL;
235 		ncp->nc_dvp = NULL;
236 		TAILQ_REMOVE(&nclruhead, ncp, nc_lru);
237 		if (ncp->nc_hash.le_prev != 0) {
238 			LIST_REMOVE(ncp, nc_hash);
239 			ncp->nc_hash.le_prev = 0;
240 		}
241 		/* cause rescan of list, it may have altered */
242 		nxtcp = nclruhead.tqh_first;
243 		TAILQ_INSERT_HEAD(&nclruhead, ncp, nc_lru);
244 	}
245 }
246