]> git.saurik.com Git - apple/xnu.git/blob - bsd/vfs/vfs_cache.c
e29ea4819d8575d3552b52d373d97e65e6d4afb6
[apple/xnu.git] / bsd / vfs / vfs_cache.c
1 /*
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
23 /*
24 * Copyright (c) 1989, 1993, 1995
25 * The Regents of the University of California. All rights reserved.
26 *
27 * This code is derived from software contributed to Berkeley by
28 * Poul-Henning Kamp of the FreeBSD Project.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 *
58 *
59 * @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95
60 */
61 #include <sys/param.h>
62 #include <sys/systm.h>
63 #include <sys/time.h>
64 #include <sys/mount_internal.h>
65 #include <sys/vnode_internal.h>
66 #include <sys/namei.h>
67 #include <sys/errno.h>
68 #include <sys/malloc.h>
69 #include <sys/kauth.h>
70 #include <sys/user.h>
71
72 /*
73 * Name caching works as follows:
74 *
75 * Names found by directory scans are retained in a cache
76 * for future reference. It is managed LRU, so frequently
77 * used names will hang around. Cache is indexed by hash value
78 * obtained from (vp, name) where vp refers to the directory
79 * containing name.
80 *
81 * If it is a "negative" entry, (i.e. for a name that is known NOT to
82 * exist) the vnode pointer will be NULL.
83 *
84 * Upon reaching the last segment of a path, if the reference
85 * is for DELETE, or NOCACHE is set (rewrite), and the
86 * name is located in the cache, it will be dropped.
87 */
88
89 /*
90 * Structures associated with name cacheing.
91 */
92
93 LIST_HEAD(nchashhead, namecache) *nchashtbl; /* Hash Table */
94 u_long nchashmask;
95 u_long nchash; /* size of hash table - 1 */
96 long numcache; /* number of cache entries allocated */
97 int desiredNodes;
98 int desiredNegNodes;
99 int ncs_negtotal;
100 TAILQ_HEAD(, namecache) nchead; /* chain of all name cache entries */
101 TAILQ_HEAD(, namecache) neghead; /* chain of only negative cache entries */
102
103
104 #if COLLECT_STATS
105
106 struct nchstats nchstats; /* cache effectiveness statistics */
107
108 #define NCHSTAT(v) { \
109 nchstats.v++; \
110 }
111 #define NAME_CACHE_LOCK() name_cache_lock()
112 #define NAME_CACHE_UNLOCK() name_cache_unlock()
113 #define NAME_CACHE_LOCK_SHARED() name_cache_lock()
114
115 #else
116
117 #define NCHSTAT(v)
118 #define NAME_CACHE_LOCK() name_cache_lock()
119 #define NAME_CACHE_UNLOCK() name_cache_unlock()
120 #define NAME_CACHE_LOCK_SHARED() name_cache_lock_shared()
121
122 #endif
123
124
125 /* vars for name cache list lock */
126 lck_grp_t * namecache_lck_grp;
127 lck_grp_attr_t * namecache_lck_grp_attr;
128 lck_attr_t * namecache_lck_attr;
129 lck_rw_t * namecache_rw_lock;
130
131 static vnode_t cache_lookup_locked(vnode_t dvp, struct componentname *cnp);
132 static int remove_name_locked(const char *);
133 static char *add_name_locked(const char *, size_t, u_int, u_int);
134 static void init_string_table(void);
135 static void cache_delete(struct namecache *, int);
136 static void dump_string_table(void);
137
138 static void init_crc32(void);
139 static unsigned int crc32tab[256];
140
141
142 #define NCHHASH(dvp, hash_val) \
143 (&nchashtbl[(dvp->v_id ^ (hash_val)) & nchashmask])
144
145
146
147 //
148 // This function builds the path to a filename in "buff". The
149 // length of the buffer *INCLUDING* the trailing zero byte is
150 // returned in outlen. NOTE: the length includes the trailing
151 // zero byte and thus the length is one greater than what strlen
152 // would return. This is important and lots of code elsewhere
153 // in the kernel assumes this behavior.
154 //
155 int
156 build_path(vnode_t first_vp, char *buff, int buflen, int *outlen)
157 {
158 vnode_t vp = first_vp;
159 char *end, *str;
160 int len, ret=0, counter=0;
161
162 end = &buff[buflen-1];
163 *end = '\0';
164
165 /*
166 * if this is the root dir of a file system...
167 */
168 if (vp && (vp->v_flag & VROOT) && vp->v_mount) {
169 /*
170 * then if it's the root fs, just put in a '/' and get out of here
171 */
172 if (vp->v_mount->mnt_flag & MNT_ROOTFS) {
173 *--end = '/';
174 goto out;
175 } else {
176 /*
177 * else just use the covered vnode to get the mount path
178 */
179 vp = vp->v_mount->mnt_vnodecovered;
180 }
181 }
182 NAME_CACHE_LOCK_SHARED();
183
184 while (vp && vp->v_parent != vp) {
185 /*
186 * the maximum depth of a file system hierarchy is MAXPATHLEN/2
187 * (with single-char names separated by slashes). we panic if
188 * we've ever looped more than that.
189 */
190 if (counter++ > MAXPATHLEN/2) {
191 panic("build_path: vnode parent chain is too long! vp 0x%x\n", vp);
192 }
193 str = vp->v_name;
194
195 if (str == NULL) {
196 if (vp->v_parent != NULL) {
197 ret = EINVAL;
198 }
199 break;
200 }
201 len = strlen(str);
202
203 /*
204 * check that there's enough space (make sure to include space for the '/')
205 */
206 if ((end - buff) < (len + 1)) {
207 ret = ENOSPC;
208 break;
209 }
210 /*
211 * copy it backwards
212 */
213 str += len;
214
215 for (; len > 0; len--) {
216 *--end = *--str;
217 }
218 /*
219 * put in the path separator
220 */
221 *--end = '/';
222
223 /*
224 * walk up the chain (as long as we're not the root)
225 */
226 if (vp == first_vp && (vp->v_flag & VROOT)) {
227 if (vp->v_mount && vp->v_mount->mnt_vnodecovered) {
228 vp = vp->v_mount->mnt_vnodecovered->v_parent;
229 } else {
230 vp = NULLVP;
231 }
232 } else {
233 vp = vp->v_parent;
234 }
235 /*
236 * check if we're crossing a mount point and
237 * switch the vp if we are.
238 */
239 if (vp && (vp->v_flag & VROOT) && vp->v_mount) {
240 vp = vp->v_mount->mnt_vnodecovered;
241 }
242 }
243 NAME_CACHE_UNLOCK();
244 out:
245 /*
246 * slide it down to the beginning of the buffer
247 */
248 memmove(buff, end, &buff[buflen] - end);
249
250 *outlen = &buff[buflen] - end; // length includes the trailing zero byte
251
252 return ret;
253 }
254
255
256 /*
257 * return NULLVP if vp's parent doesn't
258 * exist, or we can't get a valid iocount
259 * else return the parent of vp
260 */
261 vnode_t
262 vnode_getparent(vnode_t vp)
263 {
264 vnode_t pvp = NULLVP;
265 int pvid;
266
267 NAME_CACHE_LOCK_SHARED();
268 /*
269 * v_parent is stable behind the name_cache lock
270 * however, the only thing we can really guarantee
271 * is that we've grabbed a valid iocount on the
272 * parent of 'vp' at the time we took the name_cache lock...
273 * once we drop the lock, vp could get re-parented
274 */
275 if ( (pvp = vp->v_parent) != NULLVP ) {
276 pvid = pvp->v_id;
277
278 NAME_CACHE_UNLOCK();
279
280 if (vnode_getwithvid(pvp, pvid) != 0)
281 pvp = NULL;
282 } else
283 NAME_CACHE_UNLOCK();
284 return (pvp);
285 }
286
287 char *
288 vnode_getname(vnode_t vp)
289 {
290 char *name = NULL;
291
292 NAME_CACHE_LOCK();
293
294 if (vp->v_name)
295 name = add_name_locked(vp->v_name, strlen(vp->v_name), 0, 0);
296 NAME_CACHE_UNLOCK();
297
298 return (name);
299 }
300
301 void
302 vnode_putname(char *name)
303 {
304 NAME_CACHE_LOCK();
305
306 remove_name_locked(name);
307
308 NAME_CACHE_UNLOCK();
309 }
310
311
312 /*
313 * if VNODE_UPDATE_PARENT, and we can take
314 * a reference on dvp, then update vp with
315 * it's new parent... if vp already has a parent,
316 * then drop the reference vp held on it
317 *
318 * if VNODE_UPDATE_NAME,
319 * then drop string ref on v_name if it exists, and if name is non-NULL
320 * then pick up a string reference on name and record it in v_name...
321 * optionally pass in the length and hashval of name if known
322 *
323 * if VNODE_UPDATE_CACHE, flush the name cache entries associated with vp
324 */
325 void
326 vnode_update_identity(vnode_t vp, vnode_t dvp, char *name, int name_len, int name_hashval, int flags)
327 {
328 struct namecache *ncp;
329 vnode_t old_parentvp = NULLVP;
330
331
332 if (flags & VNODE_UPDATE_PARENT) {
333 if (dvp && vnode_ref(dvp) != 0)
334 dvp = NULLVP;
335 } else
336 dvp = NULLVP;
337 NAME_CACHE_LOCK();
338
339 if ( (flags & VNODE_UPDATE_NAME) && (name != vp->v_name) ) {
340 if (vp->v_name != NULL) {
341 remove_name_locked(vp->v_name);
342 vp->v_name = NULL;
343 }
344 if (name && *name) {
345 if (name_len == 0)
346 name_len = strlen(name);
347 vp->v_name = add_name_locked(name, name_len, name_hashval, 0);
348 }
349 }
350 if (flags & VNODE_UPDATE_PARENT) {
351 if (dvp != vp && dvp != vp->v_parent) {
352 old_parentvp = vp->v_parent;
353 vp->v_parent = dvp;
354 dvp = NULLVP;
355
356 if (old_parentvp)
357 flags |= VNODE_UPDATE_CACHE;
358 }
359 }
360 if (flags & VNODE_UPDATE_CACHE) {
361 while ( (ncp = LIST_FIRST(&vp->v_nclinks)) )
362 cache_delete(ncp, 1);
363 }
364 NAME_CACHE_UNLOCK();
365
366 if (dvp != NULLVP)
367 vnode_rele(dvp);
368
369 if (old_parentvp) {
370 struct uthread *ut;
371
372 ut = get_bsdthread_info(current_thread());
373
374 /*
375 * indicated to vnode_rele that it shouldn't do a
376 * vnode_reclaim at this time... instead it will
377 * chain the vnode to the uu_vreclaims list...
378 * we'll be responsible for calling vnode_reclaim
379 * on each of the vnodes in this list...
380 */
381 ut->uu_defer_reclaims = 1;
382 ut->uu_vreclaims = NULLVP;
383
384 while ( (vp = old_parentvp) != NULLVP ) {
385
386 vnode_lock(vp);
387
388 vnode_rele_internal(vp, 0, 0, 1);
389
390 /*
391 * check to see if the vnode is now in the state
392 * that would have triggered a vnode_reclaim in vnode_rele
393 * if it is, we save it's parent pointer and then NULL
394 * out the v_parent field... we'll drop the reference
395 * that was held on the next iteration of this loop...
396 * this short circuits a potential deep recursion if we
397 * have a long chain of parents in this state...
398 * we'll sit in this loop until we run into
399 * a parent in this chain that is not in this state
400 *
401 * make our check and the node_rele atomic
402 * with respect to the current vnode we're working on
403 * by holding the vnode lock
404 * if vnode_rele deferred the vnode_reclaim and has put
405 * this vnode on the list to be reaped by us, than
406 * it has left this vnode with an iocount == 1
407 */
408 if ( (vp->v_iocount == 1) && (vp->v_usecount == 0) &&
409 ((vp->v_lflag & (VL_MARKTERM | VL_TERMINATE | VL_DEAD)) == VL_MARKTERM)) {
410 /*
411 * vnode_rele wanted to do a vnode_reclaim on this vnode
412 * it should be sitting on the head of the uu_vreclaims chain
413 * pull the parent pointer now so that when we do the
414 * vnode_reclaim for each of the vnodes in the uu_vreclaims
415 * list, we won't recurse back through here
416 */
417 NAME_CACHE_LOCK();
418 old_parentvp = vp->v_parent;
419 vp->v_parent = NULLVP;
420 NAME_CACHE_UNLOCK();
421 } else {
422 /*
423 * we're done... we ran into a vnode that isn't
424 * being terminated
425 */
426 old_parentvp = NULLVP;
427 }
428 vnode_unlock(vp);
429 }
430 ut->uu_defer_reclaims = 0;
431
432 while ( (vp = ut->uu_vreclaims) != NULLVP) {
433 ut->uu_vreclaims = vp->v_defer_reclaimlist;
434
435 /*
436 * vnode_put will drive the vnode_reclaim if
437 * we are still the only reference on this vnode
438 */
439 vnode_put(vp);
440 }
441 }
442 }
443
444
445 /*
446 * Mark a vnode as having multiple hard links. HFS makes use of this
447 * because it keeps track of each link separately, and wants to know
448 * which link was actually used.
449 *
450 * This will cause the name cache to force a VNOP_LOOKUP on the vnode
451 * so that HFS can post-process the lookup. Also, volfs will call
452 * VNOP_GETATTR2 to determine the parent, instead of using v_parent.
453 */
454 void vnode_set_hard_link(vnode_t vp)
455 {
456 vnode_lock(vp);
457
458 /*
459 * In theory, we're changing the vnode's identity as far as the
460 * name cache is concerned, so we ought to grab the name cache lock
461 * here. However, there is already a race, and grabbing the name
462 * cache lock only makes the race window slightly smaller.
463 *
464 * The race happens because the vnode already exists in the name
465 * cache, and could be found by one thread before another thread
466 * can set the hard link flag.
467 */
468
469 vp->v_flag |= VISHARDLINK;
470
471 vnode_unlock(vp);
472 }
473
474
475 void vnode_uncache_credentials(vnode_t vp)
476 {
477 kauth_cred_t ucred = NULL;
478
479 if (vp->v_cred) {
480 vnode_lock(vp);
481
482 ucred = vp->v_cred;
483 vp->v_cred = NULL;
484
485 vnode_unlock(vp);
486
487 if (ucred)
488 kauth_cred_rele(ucred);
489 }
490 }
491
492
493 void vnode_cache_credentials(vnode_t vp, vfs_context_t context)
494 {
495 kauth_cred_t ucred;
496 kauth_cred_t tcred = NOCRED;
497 struct timeval tv;
498
499 ucred = vfs_context_ucred(context);
500
501 if (vp->v_cred != ucred || (vp->v_mount->mnt_kern_flag & MNTK_AUTH_OPAQUE)) {
502 vnode_lock(vp);
503
504 microuptime(&tv);
505 vp->v_cred_timestamp = tv.tv_sec;
506
507 if (vp->v_cred != ucred) {
508 kauth_cred_ref(ucred);
509
510 tcred = vp->v_cred;
511 vp->v_cred = ucred;
512 }
513 vnode_unlock(vp);
514
515 if (tcred)
516 kauth_cred_rele(tcred);
517 }
518 }
519
520 /* reverse_lookup - lookup by walking back up the parent chain while leveraging
521 * use of the name cache lock in order to protect our starting vnode.
522 * NOTE - assumes you already have search access to starting point.
523 * returns 0 when we have reached the root, current working dir, or chroot root
524 *
525 */
526 int
527 reverse_lookup(vnode_t start_vp, vnode_t *lookup_vpp, struct filedesc *fdp, vfs_context_t context, int *dp_authorized)
528 {
529 int vid, done = 0;
530 int auth_opaque = 0;
531 vnode_t dp = start_vp;
532 vnode_t vp = NULLVP;
533 kauth_cred_t ucred;
534 struct timeval tv;
535
536 ucred = vfs_context_ucred(context);
537 *lookup_vpp = start_vp;
538
539 NAME_CACHE_LOCK_SHARED();
540
541 if ( dp->v_mount && (dp->v_mount->mnt_kern_flag & MNTK_AUTH_OPAQUE) ) {
542 auth_opaque = 1;
543 microuptime(&tv);
544 }
545 for (;;) {
546 *dp_authorized = 0;
547
548 if (auth_opaque && ((tv.tv_sec - dp->v_cred_timestamp) > VCRED_EXPIRED))
549 break;
550 if (dp->v_cred != ucred)
551 break;
552 /*
553 * indicate that we're allowed to traverse this directory...
554 * even if we bail for some reason, this information is valid and is used
555 * to avoid doing a vnode_authorize
556 */
557 *dp_authorized = 1;
558
559 if ((dp->v_flag & VROOT) != 0 || /* Hit "/" */
560 (dp == fdp->fd_cdir) || /* Hit process's working directory */
561 (dp == fdp->fd_rdir)) { /* Hit process chroot()-ed root */
562 done = 1;
563 break;
564 }
565
566 if ( (vp = dp->v_parent) == NULLVP)
567 break;
568
569 dp = vp;
570 *lookup_vpp = dp;
571 } /* for (;;) */
572
573 vid = dp->v_id;
574
575 NAME_CACHE_UNLOCK();
576
577 if (done == 0 && dp != start_vp) {
578 if (vnode_getwithvid(dp, vid) != 0) {
579 *lookup_vpp = start_vp;
580 }
581 }
582
583 return((done == 1) ? 0 : -1);
584 }
585
586 int
587 cache_lookup_path(struct nameidata *ndp, struct componentname *cnp, vnode_t dp, vfs_context_t context, int *trailing_slash, int *dp_authorized)
588 {
589 char *cp; /* pointer into pathname argument */
590 int vid, vvid;
591 int auth_opaque = 0;
592 vnode_t vp = NULLVP;
593 vnode_t tdp = NULLVP;
594 kauth_cred_t ucred;
595 struct timeval tv;
596 unsigned int hash;
597
598 ucred = vfs_context_ucred(context);
599 *trailing_slash = 0;
600
601 NAME_CACHE_LOCK_SHARED();
602
603 if ( dp->v_mount && (dp->v_mount->mnt_kern_flag & MNTK_AUTH_OPAQUE) ) {
604 auth_opaque = 1;
605 microuptime(&tv);
606 }
607 for (;;) {
608 /*
609 * Search a directory.
610 *
611 * The cn_hash value is for use by cache_lookup
612 * The last component of the filename is left accessible via
613 * cnp->cn_nameptr for callers that need the name.
614 */
615 hash = 0;
616 cp = cnp->cn_nameptr;
617
618 while (*cp && (*cp != '/')) {
619 hash ^= crc32tab[((hash >> 24) ^ (unsigned char)*cp++)];
620 }
621 /*
622 * the crc generator can legitimately generate
623 * a 0... however, 0 for us means that we
624 * haven't computed a hash, so use 1 instead
625 */
626 if (hash == 0)
627 hash = 1;
628 cnp->cn_hash = hash;
629 cnp->cn_namelen = cp - cnp->cn_nameptr;
630
631 ndp->ni_pathlen -= cnp->cn_namelen;
632 ndp->ni_next = cp;
633
634 /*
635 * Replace multiple slashes by a single slash and trailing slashes
636 * by a null. This must be done before VNOP_LOOKUP() because some
637 * fs's don't know about trailing slashes. Remember if there were
638 * trailing slashes to handle symlinks, existing non-directories
639 * and non-existing files that won't be directories specially later.
640 */
641 while (*cp == '/' && (cp[1] == '/' || cp[1] == '\0')) {
642 cp++;
643 ndp->ni_pathlen--;
644
645 if (*cp == '\0') {
646 *trailing_slash = 1;
647 *ndp->ni_next = '\0';
648 }
649 }
650 ndp->ni_next = cp;
651
652 cnp->cn_flags &= ~(MAKEENTRY | ISLASTCN | ISDOTDOT);
653
654 if (*cp == '\0')
655 cnp->cn_flags |= ISLASTCN;
656
657 if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.')
658 cnp->cn_flags |= ISDOTDOT;
659
660 *dp_authorized = 0;
661
662 if (auth_opaque && ((tv.tv_sec - dp->v_cred_timestamp) > VCRED_EXPIRED))
663 break;
664
665 if (dp->v_cred != ucred)
666 break;
667 /*
668 * indicate that we're allowed to traverse this directory...
669 * even if we fail the cache lookup or decide to bail for
670 * some other reason, this information is valid and is used
671 * to avoid doing a vnode_authorize before the call to VNOP_LOOKUP
672 */
673 *dp_authorized = 1;
674
675 if ( (cnp->cn_flags & (ISLASTCN | ISDOTDOT)) ) {
676 if (cnp->cn_nameiop != LOOKUP)
677 break;
678 if (cnp->cn_flags & (LOCKPARENT | NOCACHE))
679 break;
680 if (cnp->cn_flags & ISDOTDOT) {
681 /*
682 * Quit here only if we can't use
683 * the parent directory pointer or
684 * don't have one. Otherwise, we'll
685 * use it below.
686 */
687 if ((dp->v_flag & VROOT) ||
688 dp->v_parent == NULLVP)
689 break;
690 }
691 }
692
693 /*
694 * "." and ".." aren't supposed to be cached, so check
695 * for them before checking the cache.
696 */
697 if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.')
698 vp = dp;
699 else if (cnp->cn_flags & ISDOTDOT)
700 vp = dp->v_parent;
701 else {
702 if ( (vp = cache_lookup_locked(dp, cnp)) == NULLVP)
703 break;
704 }
705
706 if ( (cnp->cn_flags & ISLASTCN) )
707 break;
708
709 if (vp->v_type != VDIR) {
710 if (vp->v_type != VLNK)
711 vp = NULL;
712 break;
713 }
714 if (vp->v_mountedhere && ((cnp->cn_flags & NOCROSSMOUNT) == 0))
715 break;
716
717 dp = vp;
718 vp = NULLVP;
719
720 cnp->cn_nameptr = ndp->ni_next + 1;
721 ndp->ni_pathlen--;
722 while (*cnp->cn_nameptr == '/') {
723 cnp->cn_nameptr++;
724 ndp->ni_pathlen--;
725 }
726 }
727 if (vp != NULLVP)
728 vvid = vp->v_id;
729 vid = dp->v_id;
730
731 NAME_CACHE_UNLOCK();
732
733
734 if ((vp != NULLVP) && (vp->v_type != VLNK) &&
735 ((cnp->cn_flags & (ISLASTCN | LOCKPARENT | WANTPARENT | SAVESTART)) == ISLASTCN)) {
736 /*
737 * if we've got a child and it's the last component, and
738 * the lookup doesn't need to return the parent then we
739 * can skip grabbing an iocount on the parent, since all
740 * we're going to do with it is a vnode_put just before
741 * we return from 'lookup'. If it's a symbolic link,
742 * we need the parent in case the link happens to be
743 * a relative pathname.
744 */
745 tdp = dp;
746 dp = NULLVP;
747 } else {
748 need_dp:
749 /*
750 * return the last directory we looked at
751 * with an io reference held
752 */
753 if (dp == ndp->ni_usedvp) {
754 /*
755 * if this vnode matches the one passed in via USEDVP
756 * than this context already holds an io_count... just
757 * use vnode_get to get an extra ref for lookup to play
758 * with... can't use the getwithvid variant here because
759 * it will block behind a vnode_drain which would result
760 * in a deadlock (since we already own an io_count that the
761 * vnode_drain is waiting on)... vnode_get grabs the io_count
762 * immediately w/o waiting... it always succeeds
763 */
764 vnode_get(dp);
765 } else if ( (vnode_getwithvid(dp, vid)) ) {
766 /*
767 * failure indicates the vnode
768 * changed identity or is being
769 * TERMINATED... in either case
770 * punt this lookup
771 */
772 return (ENOENT);
773 }
774 }
775 if (vp != NULLVP) {
776 if ( (vnode_getwithvid(vp, vvid)) ) {
777 vp = NULLVP;
778
779 /*
780 * can't get reference on the vp we'd like
781 * to return... if we didn't grab a reference
782 * on the directory (due to fast path bypass),
783 * then we need to do it now... we can't return
784 * with both ni_dvp and ni_vp NULL, and no
785 * error condition
786 */
787 if (dp == NULLVP) {
788 dp = tdp;
789 goto need_dp;
790 }
791 }
792 }
793 ndp->ni_dvp = dp;
794 ndp->ni_vp = vp;
795
796 return (0);
797 }
798
799
800 static vnode_t
801 cache_lookup_locked(vnode_t dvp, struct componentname *cnp)
802 {
803 register struct namecache *ncp;
804 register struct nchashhead *ncpp;
805 register long namelen = cnp->cn_namelen;
806 char *nameptr = cnp->cn_nameptr;
807 unsigned int hashval = (cnp->cn_hash & NCHASHMASK);
808 vnode_t vp;
809
810 ncpp = NCHHASH(dvp, cnp->cn_hash);
811 LIST_FOREACH(ncp, ncpp, nc_hash) {
812 if ((ncp->nc_dvp == dvp) && (ncp->nc_hashval == hashval)) {
813 if (memcmp(ncp->nc_name, nameptr, namelen) == 0 && ncp->nc_name[namelen] == 0)
814 break;
815 }
816 }
817 if (ncp == 0) {
818 /*
819 * We failed to find an entry
820 */
821 NCHSTAT(ncs_miss);
822 return (NULL);
823 }
824 NCHSTAT(ncs_goodhits);
825
826 vp = ncp->nc_vp;
827 if (vp && (vp->v_flag & VISHARDLINK)) {
828 /*
829 * The file system wants a VNOP_LOOKUP on this vnode
830 */
831 vp = NULL;
832 }
833
834 return (vp);
835 }
836
837
838 //
839 // Have to take a len argument because we may only need to
840 // hash part of a componentname.
841 //
842 static unsigned int
843 hash_string(const char *cp, int len)
844 {
845 unsigned hash = 0;
846
847 if (len) {
848 while (len--) {
849 hash ^= crc32tab[((hash >> 24) ^ (unsigned char)*cp++)];
850 }
851 } else {
852 while (*cp != '\0') {
853 hash ^= crc32tab[((hash >> 24) ^ (unsigned char)*cp++)];
854 }
855 }
856 /*
857 * the crc generator can legitimately generate
858 * a 0... however, 0 for us means that we
859 * haven't computed a hash, so use 1 instead
860 */
861 if (hash == 0)
862 hash = 1;
863 return hash;
864 }
865
866
867 /*
868 * Lookup an entry in the cache
869 *
870 * We don't do this if the segment name is long, simply so the cache
871 * can avoid holding long names (which would either waste space, or
872 * add greatly to the complexity).
873 *
874 * Lookup is called with dvp pointing to the directory to search,
875 * cnp pointing to the name of the entry being sought. If the lookup
876 * succeeds, the vnode is returned in *vpp, and a status of -1 is
877 * returned. If the lookup determines that the name does not exist
878 * (negative cacheing), a status of ENOENT is returned. If the lookup
879 * fails, a status of zero is returned.
880 */
881
882 int
883 cache_lookup(dvp, vpp, cnp)
884 struct vnode *dvp;
885 struct vnode **vpp;
886 struct componentname *cnp;
887 {
888 register struct namecache *ncp;
889 register struct nchashhead *ncpp;
890 register long namelen = cnp->cn_namelen;
891 char *nameptr = cnp->cn_nameptr;
892 unsigned int hashval = (cnp->cn_hash & NCHASHMASK);
893 boolean_t have_exclusive = FALSE;
894 uint32_t vid;
895 vnode_t vp;
896
897 NAME_CACHE_LOCK_SHARED();
898
899 ncpp = NCHHASH(dvp, cnp->cn_hash);
900 relook:
901 LIST_FOREACH(ncp, ncpp, nc_hash) {
902 if ((ncp->nc_dvp == dvp) && (ncp->nc_hashval == hashval)) {
903 if (memcmp(ncp->nc_name, nameptr, namelen) == 0 && ncp->nc_name[namelen] == 0)
904 break;
905 }
906 }
907 /* We failed to find an entry */
908 if (ncp == 0) {
909 NCHSTAT(ncs_miss);
910 NAME_CACHE_UNLOCK();
911 return (0);
912 }
913
914 /* We don't want to have an entry, so dump it */
915 if ((cnp->cn_flags & MAKEENTRY) == 0) {
916 if (have_exclusive == TRUE) {
917 NCHSTAT(ncs_badhits);
918 cache_delete(ncp, 1);
919 NAME_CACHE_UNLOCK();
920 return (0);
921 }
922 NAME_CACHE_UNLOCK();
923 NAME_CACHE_LOCK();
924 have_exclusive = TRUE;
925 goto relook;
926 }
927 vp = ncp->nc_vp;
928
929 /* We found a "positive" match, return the vnode */
930 if (vp) {
931 NCHSTAT(ncs_goodhits);
932
933 vid = vp->v_id;
934 NAME_CACHE_UNLOCK();
935
936 if (vnode_getwithvid(vp, vid)) {
937 #if COLLECT_STATS
938 NAME_CACHE_LOCK();
939 NCHSTAT(ncs_badvid);
940 NAME_CACHE_UNLOCK();
941 #endif
942 return (0);
943 }
944 *vpp = vp;
945 return (-1);
946 }
947
948 /* We found a negative match, and want to create it, so purge */
949 if (cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) {
950 if (have_exclusive == TRUE) {
951 NCHSTAT(ncs_badhits);
952 cache_delete(ncp, 1);
953 NAME_CACHE_UNLOCK();
954 return (0);
955 }
956 NAME_CACHE_UNLOCK();
957 NAME_CACHE_LOCK();
958 have_exclusive = TRUE;
959 goto relook;
960 }
961
962 /*
963 * We found a "negative" match, ENOENT notifies client of this match.
964 * The nc_whiteout field records whether this is a whiteout.
965 */
966 NCHSTAT(ncs_neghits);
967
968 if (ncp->nc_whiteout)
969 cnp->cn_flags |= ISWHITEOUT;
970 NAME_CACHE_UNLOCK();
971 return (ENOENT);
972 }
973
974 /*
975 * Add an entry to the cache.
976 */
977 void
978 cache_enter(dvp, vp, cnp)
979 struct vnode *dvp;
980 struct vnode *vp;
981 struct componentname *cnp;
982 {
983 register struct namecache *ncp, *negp;
984 register struct nchashhead *ncpp;
985
986 if (cnp->cn_hash == 0)
987 cnp->cn_hash = hash_string(cnp->cn_nameptr, cnp->cn_namelen);
988
989 NAME_CACHE_LOCK();
990
991 /* if the entry is for -ve caching vp is null */
992 if ((vp != NULLVP) && (LIST_FIRST(&vp->v_nclinks))) {
993 /*
994 * someone beat us to the punch..
995 * this vnode is already in the cache
996 */
997 NAME_CACHE_UNLOCK();
998 return;
999 }
1000 /*
1001 * We allocate a new entry if we are less than the maximum
1002 * allowed and the one at the front of the list is in use.
1003 * Otherwise we use the one at the front of the list.
1004 */
1005 if (numcache < desiredNodes &&
1006 ((ncp = nchead.tqh_first) == NULL ||
1007 ncp->nc_hash.le_prev != 0)) {
1008 /*
1009 * Allocate one more entry
1010 */
1011 ncp = (struct namecache *)_MALLOC_ZONE((u_long)sizeof *ncp, M_CACHE, M_WAITOK);
1012 numcache++;
1013 } else {
1014 /*
1015 * reuse an old entry
1016 */
1017 ncp = TAILQ_FIRST(&nchead);
1018 TAILQ_REMOVE(&nchead, ncp, nc_entry);
1019
1020 if (ncp->nc_hash.le_prev != 0) {
1021 /*
1022 * still in use... we need to
1023 * delete it before re-using it
1024 */
1025 NCHSTAT(ncs_stolen);
1026 cache_delete(ncp, 0);
1027 }
1028 }
1029 NCHSTAT(ncs_enters);
1030
1031 /*
1032 * Fill in cache info, if vp is NULL this is a "negative" cache entry.
1033 */
1034 ncp->nc_vp = vp;
1035 ncp->nc_dvp = dvp;
1036 ncp->nc_hashval = cnp->cn_hash;
1037 ncp->nc_whiteout = FALSE;
1038 ncp->nc_name = add_name_locked(cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_hash, 0);
1039
1040 /*
1041 * make us the newest entry in the cache
1042 * i.e. we'll be the last to be stolen
1043 */
1044 TAILQ_INSERT_TAIL(&nchead, ncp, nc_entry);
1045
1046 ncpp = NCHHASH(dvp, cnp->cn_hash);
1047 #if DIAGNOSTIC
1048 {
1049 register struct namecache *p;
1050
1051 for (p = ncpp->lh_first; p != 0; p = p->nc_hash.le_next)
1052 if (p == ncp)
1053 panic("cache_enter: duplicate");
1054 }
1055 #endif
1056 /*
1057 * make us available to be found via lookup
1058 */
1059 LIST_INSERT_HEAD(ncpp, ncp, nc_hash);
1060
1061 if (vp) {
1062 /*
1063 * add to the list of name cache entries
1064 * that point at vp
1065 */
1066 LIST_INSERT_HEAD(&vp->v_nclinks, ncp, nc_un.nc_link);
1067 } else {
1068 /*
1069 * this is a negative cache entry (vp == NULL)
1070 * stick it on the negative cache list
1071 * and record the whiteout state
1072 */
1073 TAILQ_INSERT_TAIL(&neghead, ncp, nc_un.nc_negentry);
1074
1075 if (cnp->cn_flags & ISWHITEOUT)
1076 ncp->nc_whiteout = TRUE;
1077 ncs_negtotal++;
1078
1079 if (ncs_negtotal > desiredNegNodes) {
1080 /*
1081 * if we've reached our desired limit
1082 * of negative cache entries, delete
1083 * the oldest
1084 */
1085 negp = TAILQ_FIRST(&neghead);
1086 TAILQ_REMOVE(&neghead, negp, nc_un.nc_negentry);
1087
1088 cache_delete(negp, 1);
1089 }
1090 }
1091 /*
1092 * add us to the list of name cache entries that
1093 * are children of dvp
1094 */
1095 LIST_INSERT_HEAD(&dvp->v_ncchildren, ncp, nc_child);
1096
1097 NAME_CACHE_UNLOCK();
1098 }
1099
1100
1101 /*
1102 * Initialize CRC-32 remainder table.
1103 */
1104 static void init_crc32(void)
1105 {
1106 /*
1107 * the CRC-32 generator polynomial is:
1108 * x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^10
1109 * + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
1110 */
1111 unsigned int crc32_polynomial = 0x04c11db7;
1112 unsigned int i,j;
1113
1114 /*
1115 * pre-calculate the CRC-32 remainder for each possible octet encoding
1116 */
1117 for (i = 0; i < 256; i++) {
1118 unsigned int crc_rem = i << 24;
1119
1120 for (j = 0; j < 8; j++) {
1121 if (crc_rem & 0x80000000)
1122 crc_rem = (crc_rem << 1) ^ crc32_polynomial;
1123 else
1124 crc_rem = (crc_rem << 1);
1125 }
1126 crc32tab[i] = crc_rem;
1127 }
1128 }
1129
1130
1131 /*
1132 * Name cache initialization, from vfs_init() when we are booting
1133 */
1134 void
1135 nchinit(void)
1136 {
1137 desiredNegNodes = (desiredvnodes / 10);
1138 desiredNodes = desiredvnodes + desiredNegNodes;
1139
1140 TAILQ_INIT(&nchead);
1141 TAILQ_INIT(&neghead);
1142
1143 init_crc32();
1144
1145 nchashtbl = hashinit(MAX(4096, (2 *desiredNodes)), M_CACHE, &nchash);
1146 nchashmask = nchash;
1147 nchash++;
1148
1149 init_string_table();
1150
1151 /* Allocate mount list lock group attribute and group */
1152 namecache_lck_grp_attr= lck_grp_attr_alloc_init();
1153
1154 namecache_lck_grp = lck_grp_alloc_init("Name Cache", namecache_lck_grp_attr);
1155
1156 /* Allocate mount list lock attribute */
1157 namecache_lck_attr = lck_attr_alloc_init();
1158
1159 /* Allocate mount list lock */
1160 namecache_rw_lock = lck_rw_alloc_init(namecache_lck_grp, namecache_lck_attr);
1161
1162
1163 }
1164
1165 void
1166 name_cache_lock_shared(void)
1167 {
1168 lck_rw_lock_shared(namecache_rw_lock);
1169 }
1170
1171 void
1172 name_cache_lock(void)
1173 {
1174 lck_rw_lock_exclusive(namecache_rw_lock);
1175 }
1176
1177 void
1178 name_cache_unlock(void)
1179 {
1180 lck_rw_done(namecache_rw_lock);
1181 }
1182
1183
1184 int
1185 resize_namecache(u_int newsize)
1186 {
1187 struct nchashhead *new_table;
1188 struct nchashhead *old_table;
1189 struct nchashhead *old_head, *head;
1190 struct namecache *entry, *next;
1191 uint32_t i, hashval;
1192 int dNodes, dNegNodes;
1193 u_long new_size, old_size;
1194
1195 dNegNodes = (newsize / 10);
1196 dNodes = newsize + dNegNodes;
1197
1198 // we don't support shrinking yet
1199 if (dNodes < desiredNodes) {
1200 return 0;
1201 }
1202 new_table = hashinit(2 * dNodes, M_CACHE, &nchashmask);
1203 new_size = nchashmask + 1;
1204
1205 if (new_table == NULL) {
1206 return ENOMEM;
1207 }
1208
1209 NAME_CACHE_LOCK();
1210 // do the switch!
1211 old_table = nchashtbl;
1212 nchashtbl = new_table;
1213 old_size = nchash;
1214 nchash = new_size;
1215
1216 // walk the old table and insert all the entries into
1217 // the new table
1218 //
1219 for(i=0; i < old_size; i++) {
1220 old_head = &old_table[i];
1221 for (entry=old_head->lh_first; entry != NULL; entry=next) {
1222 //
1223 // XXXdbg - Beware: this assumes that hash_string() does
1224 // the same thing as what happens in
1225 // lookup() over in vfs_lookup.c
1226 hashval = hash_string(entry->nc_name, 0);
1227 entry->nc_hashval = hashval;
1228 head = NCHHASH(entry->nc_dvp, hashval);
1229
1230 next = entry->nc_hash.le_next;
1231 LIST_INSERT_HEAD(head, entry, nc_hash);
1232 }
1233 }
1234 desiredNodes = dNodes;
1235 desiredNegNodes = dNegNodes;
1236
1237 NAME_CACHE_UNLOCK();
1238 FREE(old_table, M_CACHE);
1239
1240 return 0;
1241 }
1242
1243 static void
1244 cache_delete(struct namecache *ncp, int age_entry)
1245 {
1246 NCHSTAT(ncs_deletes);
1247
1248 if (ncp->nc_vp) {
1249 LIST_REMOVE(ncp, nc_un.nc_link);
1250 } else {
1251 TAILQ_REMOVE(&neghead, ncp, nc_un.nc_negentry);
1252 ncs_negtotal--;
1253 }
1254 LIST_REMOVE(ncp, nc_child);
1255
1256 LIST_REMOVE(ncp, nc_hash);
1257 /*
1258 * this field is used to indicate
1259 * that the entry is in use and
1260 * must be deleted before it can
1261 * be reused...
1262 */
1263 ncp->nc_hash.le_prev = NULL;
1264
1265 if (age_entry) {
1266 /*
1267 * make it the next one available
1268 * for cache_enter's use
1269 */
1270 TAILQ_REMOVE(&nchead, ncp, nc_entry);
1271 TAILQ_INSERT_HEAD(&nchead, ncp, nc_entry);
1272 }
1273 remove_name_locked(ncp->nc_name);
1274 ncp->nc_name = NULL;
1275 }
1276
1277
1278 /*
1279 * purge the entry associated with the
1280 * specified vnode from the name cache
1281 */
1282 void
1283 cache_purge(vnode_t vp)
1284 {
1285 struct namecache *ncp;
1286
1287 if ((LIST_FIRST(&vp->v_nclinks) == NULL) && (LIST_FIRST(&vp->v_ncchildren) == NULL))
1288 return;
1289
1290 NAME_CACHE_LOCK();
1291
1292 while ( (ncp = LIST_FIRST(&vp->v_nclinks)) )
1293 cache_delete(ncp, 1);
1294
1295 while ( (ncp = LIST_FIRST(&vp->v_ncchildren)) )
1296 cache_delete(ncp, 1);
1297
1298 NAME_CACHE_UNLOCK();
1299 }
1300
1301 /*
1302 * Purge all negative cache entries that are children of the
1303 * given vnode. A case-insensitive file system (or any file
1304 * system that has multiple equivalent names for the same
1305 * directory entry) can use this when creating or renaming
1306 * to remove negative entries that may no longer apply.
1307 */
1308 void
1309 cache_purge_negatives(vnode_t vp)
1310 {
1311 struct namecache *ncp;
1312
1313 NAME_CACHE_LOCK();
1314
1315 LIST_FOREACH(ncp, &vp->v_ncchildren, nc_child)
1316 if (ncp->nc_vp == NULL)
1317 cache_delete(ncp , 1);
1318
1319 NAME_CACHE_UNLOCK();
1320 }
1321
1322 /*
1323 * Flush all entries referencing a particular filesystem.
1324 *
1325 * Since we need to check it anyway, we will flush all the invalid
1326 * entries at the same time.
1327 */
1328 void
1329 cache_purgevfs(mp)
1330 struct mount *mp;
1331 {
1332 struct nchashhead *ncpp;
1333 struct namecache *ncp;
1334
1335 NAME_CACHE_LOCK();
1336 /* Scan hash tables for applicable entries */
1337 for (ncpp = &nchashtbl[nchash - 1]; ncpp >= nchashtbl; ncpp--) {
1338 restart:
1339 for (ncp = ncpp->lh_first; ncp != 0; ncp = ncp->nc_hash.le_next) {
1340 if (ncp->nc_dvp->v_mount == mp) {
1341 cache_delete(ncp, 0);
1342 goto restart;
1343 }
1344 }
1345 }
1346 NAME_CACHE_UNLOCK();
1347 }
1348
1349
1350
1351 //
1352 // String ref routines
1353 //
1354 static LIST_HEAD(stringhead, string_t) *string_ref_table;
1355 static u_long string_table_mask;
1356 static uint32_t max_chain_len=0;
1357 static struct stringhead *long_chain_head=NULL;
1358 static uint32_t filled_buckets=0;
1359 static uint32_t num_dups=0;
1360 static uint32_t nstrings=0;
1361
1362 typedef struct string_t {
1363 LIST_ENTRY(string_t) hash_chain;
1364 unsigned char *str;
1365 uint32_t refcount;
1366 } string_t;
1367
1368
1369
1370 static int
1371 resize_string_ref_table(void)
1372 {
1373 struct stringhead *new_table;
1374 struct stringhead *old_table;
1375 struct stringhead *old_head, *head;
1376 string_t *entry, *next;
1377 uint32_t i, hashval;
1378 u_long new_mask, old_mask;
1379
1380 new_table = hashinit((string_table_mask + 1) * 2, M_CACHE, &new_mask);
1381 if (new_table == NULL) {
1382 return ENOMEM;
1383 }
1384
1385 // do the switch!
1386 old_table = string_ref_table;
1387 string_ref_table = new_table;
1388 old_mask = string_table_mask;
1389 string_table_mask = new_mask;
1390
1391 printf("resize: max chain len %d, new table size %d\n",
1392 max_chain_len, new_mask + 1);
1393 max_chain_len = 0;
1394 long_chain_head = NULL;
1395 filled_buckets = 0;
1396
1397 // walk the old table and insert all the entries into
1398 // the new table
1399 //
1400 for(i=0; i <= old_mask; i++) {
1401 old_head = &old_table[i];
1402 for (entry=old_head->lh_first; entry != NULL; entry=next) {
1403 hashval = hash_string(entry->str, 0);
1404 head = &string_ref_table[hashval & string_table_mask];
1405 if (head->lh_first == NULL) {
1406 filled_buckets++;
1407 }
1408
1409 next = entry->hash_chain.le_next;
1410 LIST_INSERT_HEAD(head, entry, hash_chain);
1411 }
1412 }
1413
1414 FREE(old_table, M_CACHE);
1415
1416 return 0;
1417 }
1418
1419
1420 static void
1421 init_string_table(void)
1422 {
1423 string_ref_table = hashinit(4096, M_CACHE, &string_table_mask);
1424 }
1425
1426
1427 char *
1428 vfs_addname(const char *name, size_t len, u_int hashval, u_int flags)
1429 {
1430 char * ptr;
1431
1432 NAME_CACHE_LOCK();
1433 ptr = add_name_locked(name, len, hashval, flags);
1434 NAME_CACHE_UNLOCK();
1435
1436 return(ptr);
1437 }
1438
1439 static char *
1440 add_name_locked(const char *name, size_t len, u_int hashval, __unused u_int flags)
1441 {
1442 struct stringhead *head;
1443 string_t *entry;
1444 uint32_t chain_len = 0;
1445
1446 //
1447 // If the table gets more than 3/4 full, resize it
1448 //
1449 if (4*filled_buckets >= ((string_table_mask + 1) * 3)) {
1450 if (resize_string_ref_table() != 0) {
1451 printf("failed to resize the hash table.\n");
1452 }
1453 }
1454 if (hashval == 0) {
1455 hashval = hash_string(name, 0);
1456 }
1457
1458 head = &string_ref_table[hashval & string_table_mask];
1459 for (entry=head->lh_first; entry != NULL; chain_len++, entry=entry->hash_chain.le_next) {
1460 if (memcmp(entry->str, name, len) == 0 && entry->str[len] == '\0') {
1461 entry->refcount++;
1462 num_dups++;
1463 break;
1464 }
1465 }
1466
1467 if (entry == NULL) {
1468 // it wasn't already there so add it.
1469 MALLOC(entry, string_t *, sizeof(string_t) + len + 1, M_TEMP, M_WAITOK);
1470
1471 // have to get "head" again because we could have blocked
1472 // in malloc and thus head could have changed.
1473 //
1474 head = &string_ref_table[hashval & string_table_mask];
1475 if (head->lh_first == NULL) {
1476 filled_buckets++;
1477 }
1478
1479 entry->str = (char *)((char *)entry + sizeof(string_t));
1480 strncpy(entry->str, name, len);
1481 entry->str[len] = '\0';
1482 entry->refcount = 1;
1483 LIST_INSERT_HEAD(head, entry, hash_chain);
1484
1485 if (chain_len > max_chain_len) {
1486 max_chain_len = chain_len;
1487 long_chain_head = head;
1488 }
1489
1490 nstrings++;
1491 }
1492
1493 return entry->str;
1494 }
1495
1496 int
1497 vfs_removename(const char *nameref)
1498 {
1499 int i;
1500
1501 NAME_CACHE_LOCK();
1502 i = remove_name_locked(nameref);
1503 NAME_CACHE_UNLOCK();
1504
1505 return(i);
1506
1507 }
1508
1509
1510 static int
1511 remove_name_locked(const char *nameref)
1512 {
1513 struct stringhead *head;
1514 string_t *entry;
1515 uint32_t hashval;
1516 char * ptr;
1517
1518 hashval = hash_string(nameref, 0);
1519 head = &string_ref_table[hashval & string_table_mask];
1520 for (entry=head->lh_first; entry != NULL; entry=entry->hash_chain.le_next) {
1521 if (entry->str == (unsigned char *)nameref) {
1522 entry->refcount--;
1523 if (entry->refcount == 0) {
1524 LIST_REMOVE(entry, hash_chain);
1525 if (head->lh_first == NULL) {
1526 filled_buckets--;
1527 }
1528 ptr = entry->str;
1529 entry->str = NULL;
1530 nstrings--;
1531
1532 FREE(entry, M_TEMP);
1533 } else {
1534 num_dups--;
1535 }
1536
1537 return 0;
1538 }
1539 }
1540
1541 return ENOENT;
1542 }
1543
1544
1545 void
1546 dump_string_table(void)
1547 {
1548 struct stringhead *head;
1549 string_t *entry;
1550 u_long i;
1551
1552 NAME_CACHE_LOCK_SHARED();
1553
1554 for (i = 0; i <= string_table_mask; i++) {
1555 head = &string_ref_table[i];
1556 for (entry=head->lh_first; entry != NULL; entry=entry->hash_chain.le_next) {
1557 printf("%6d - %s\n", entry->refcount, entry->str);
1558 }
1559 }
1560 NAME_CACHE_UNLOCK();
1561 }