2 * Copyright (c) 1989, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 2003 Matthew Dillon <dillon@backplane.com>,
7 * This code is derived from software contributed to Berkeley by
8 * Poul-Henning Kamp of the FreeBSD Project.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95
39 * $FreeBSD: src/sys/kern/vfs_cache.c,v 1.42.2.6 2001/10/05 20:07:03 dillon Exp $
40 * $DragonFly: src/sys/kern/vfs_cache.c,v 1.11 2003/10/09 22:27:19 dillon Exp $
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/sysctl.h>
47 #include <sys/mount.h>
48 #include <sys/vnode.h>
49 #include <sys/malloc.h>
50 #include <sys/sysproto.h>
52 #include <sys/namei.h>
53 #include <sys/filedesc.h>
54 #include <sys/fnv_hash.h>
57 * Random lookups in the cache are accomplished with a hash table using
58 * a hash key of (nc_src_vp, name).
60 * Negative entries may exist and correspond to structures where nc_vp
61 * is NULL. In a negative entry, NCF_WHITEOUT will be set if the entry
62 * corresponds to a whited-out directory entry (verses simply not finding the
65 * Upon reaching the last segment of a path, if the reference is for DELETE,
66 * or NOCACHE is set (rewrite), and the name is located in the cache, it
71 * Structures associated with name cacheing.
73 #define NCHHASH(hash) (&nchashtbl[(hash) & nchash])
75 static LIST_HEAD(nchashhead, namecache) *nchashtbl; /* Hash Table */
76 static struct namecache_list ncneglist; /* instead of vnode */
77 static struct namecache rootnamecache; /* Dummy node */
79 static int nczapcheck; /* panic on bad release */
80 SYSCTL_INT(_debug, OID_AUTO, nczapcheck, CTLFLAG_RW, &nczapcheck, 0, "");
82 static u_long nchash; /* size of hash table */
83 SYSCTL_ULONG(_debug, OID_AUTO, nchash, CTLFLAG_RD, &nchash, 0, "");
85 static u_long ncnegfactor = 16; /* ratio of negative entries */
86 SYSCTL_ULONG(_debug, OID_AUTO, ncnegfactor, CTLFLAG_RW, &ncnegfactor, 0, "");
88 static u_long numneg; /* number of cache entries allocated */
89 SYSCTL_ULONG(_debug, OID_AUTO, numneg, CTLFLAG_RD, &numneg, 0, "");
91 static u_long numcache; /* number of cache entries allocated */
92 SYSCTL_ULONG(_debug, OID_AUTO, numcache, CTLFLAG_RD, &numcache, 0, "");
94 struct nchstats nchstats; /* cache effectiveness statistics */
96 SYSCTL_INT(_debug, OID_AUTO, vnsize, CTLFLAG_RD, 0, sizeof(struct vnode), "");
97 SYSCTL_INT(_debug, OID_AUTO, ncsize, CTLFLAG_RD, 0, sizeof(struct namecache), "");
100 * The new name cache statistics
102 SYSCTL_NODE(_vfs, OID_AUTO, cache, CTLFLAG_RW, 0, "Name cache statistics");
103 #define STATNODE(mode, name, var) \
104 SYSCTL_ULONG(_vfs_cache, OID_AUTO, name, mode, var, 0, "");
105 STATNODE(CTLFLAG_RD, numneg, &numneg);
106 STATNODE(CTLFLAG_RD, numcache, &numcache);
107 static u_long numcalls; STATNODE(CTLFLAG_RD, numcalls, &numcalls);
108 static u_long dothits; STATNODE(CTLFLAG_RD, dothits, &dothits);
109 static u_long dotdothits; STATNODE(CTLFLAG_RD, dotdothits, &dotdothits);
110 static u_long numchecks; STATNODE(CTLFLAG_RD, numchecks, &numchecks);
111 static u_long nummiss; STATNODE(CTLFLAG_RD, nummiss, &nummiss);
112 static u_long nummisszap; STATNODE(CTLFLAG_RD, nummisszap, &nummisszap);
113 static u_long numposzaps; STATNODE(CTLFLAG_RD, numposzaps, &numposzaps);
114 static u_long numposhits; STATNODE(CTLFLAG_RD, numposhits, &numposhits);
115 static u_long numnegzaps; STATNODE(CTLFLAG_RD, numnegzaps, &numnegzaps);
116 static u_long numneghits; STATNODE(CTLFLAG_RD, numneghits, &numneghits);
119 static void cache_zap(struct namecache *ncp);
121 MALLOC_DEFINE(M_VFSCACHE, "vfscache", "VFS name cache entries");
124 * cache_hold() and cache_drop() prevent the premature deletion of a
125 * namecache entry but do not prevent operations (such as zapping) on
126 * that namecache entry.
130 _cache_hold(struct namecache *ncp)
138 _cache_drop(struct namecache *ncp)
140 KKASSERT(ncp->nc_refs > 0);
141 if (ncp->nc_refs == 1 && (ncp->nc_flag & NCF_HASHED) == 0)
148 cache_hold(struct namecache *ncp)
150 return(_cache_hold(ncp));
154 cache_drop(struct namecache *ncp)
160 * Try to destroy a namecache entry. The entry is disassociated from its
161 * vnode or ncneglist and reverted to an UNRESOLVED state.
163 * Then, if there are no additional references to the ncp and we can
164 * successfully delete the children, the entry is also removed from the
165 * namecache hashlist / topology.
167 * References or undeletable children will prevent the entry from being
168 * removed from the topology. The entry may be revalidated (typically
169 * by cache_enter()) at a later time. Children remain because:
171 * + we have tried to delete a node rather then a leaf in the topology.
172 * + the presence of negative entries (we try to scrap these).
173 * + an entry or child has a non-zero ref count and cannot be scrapped.
175 * This function must be called with the ncp held and will drop the ref
176 * count during zapping.
179 cache_zap(struct namecache *ncp)
181 struct namecache *par;
185 * Disassociate the vnode or negative cache ref and set NCF_UNRESOLVED.
187 if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
188 ncp->nc_flag |= NCF_UNRESOLVED;
190 if ((vp = ncp->nc_vp) != NULL) {
191 ncp->nc_vp = NULL; /* safety */
192 TAILQ_REMOVE(&vp->v_namecache, ncp, nc_vnode);
193 if (vp && !TAILQ_EMPTY(&ncp->nc_list))
196 TAILQ_REMOVE(&ncneglist, ncp, nc_vnode);
202 * Try to scrap the entry and possibly tail-recurse on its parent.
203 * We only scrap unref'd (other then our ref) unresolved entries,
204 * we do not scrap 'live' entries.
206 while (ncp->nc_flag & NCF_UNRESOLVED) {
208 * Someone other then us has a ref, stop.
210 if (ncp->nc_refs > 1)
214 * We have children, stop.
216 if (!TAILQ_EMPTY(&ncp->nc_list))
220 * Ok, we can completely destroy and free this entry. Sanity
221 * check it against our static rootnamecache structure,
222 * then remove it from the hash.
224 KKASSERT(ncp != &rootnamecache);
226 if (ncp->nc_flag & NCF_HASHED) {
227 ncp->nc_flag &= ~NCF_HASHED;
228 LIST_REMOVE(ncp, nc_hash);
232 * Unlink from its parent and free, then loop on the
233 * parent. XXX temp hack, in stage-3 parent is never NULL
235 if ((par = ncp->nc_parent) != NULL) {
236 par = cache_hold(par);
237 TAILQ_REMOVE(&par->nc_list, ncp, nc_entry);
238 if (par->nc_vp && TAILQ_EMPTY(&par->nc_list))
241 ncp->nc_refs = -1; /* safety */
242 ncp->nc_parent = NULL; /* safety */
244 free(ncp->nc_name, M_VFSCACHE);
245 free(ncp, M_VFSCACHE);
247 if (par == NULL) /* temp hack */
248 return; /* temp hack */
255 * Lookup an entry in the cache
257 * Lookup is called with dvp pointing to the directory to search,
258 * cnp pointing to the name of the entry being sought.
260 * If the lookup succeeds, the vnode is returned in *vpp, and a
261 * status of -1 is returned.
263 * If the lookup determines that the name does not exist (negative cacheing),
264 * a status of ENOENT is returned.
266 * If the lookup fails, a status of zero is returned.
268 * Note that UNRESOLVED entries are ignored. They are not negative cache
272 cache_lookup(struct vnode *dvp, struct namecache *par, struct vnode **vpp,
273 struct namecache **ncpp, struct componentname *cnp)
275 struct namecache *ncp;
280 if (cnp->cn_nameptr[0] == '.') {
281 if (cnp->cn_namelen == 1) {
284 numposhits++; /* include in total statistics */
287 if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.') {
289 numposhits++; /* include in total statistics */
290 if (dvp->v_dd->v_id != dvp->v_ddid ||
291 (cnp->cn_flags & CNP_MAKEENTRY) == 0) {
300 hash = fnv_32_buf(cnp->cn_nameptr, cnp->cn_namelen, FNV1_32_INIT);
301 hash = fnv_32_buf(&dvp->v_id, sizeof(dvp->v_id), hash);
302 LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) {
304 if ((ncp->nc_flag & NCF_UNRESOLVED) == 0 &&
305 /* ncp->nc_parent == par instead of dvp STAGE-3 */
306 ncp->nc_dvp_data == (uintptr_t)dvp && /* STAGE-2 only */
307 ncp->nc_dvp_id == dvp->v_id && /* STAGE-2 only */
308 ncp->nc_nlen == cnp->cn_namelen &&
309 bcmp(ncp->nc_name, cnp->cn_nameptr, ncp->nc_nlen) == 0
316 /* We failed to find an entry */
318 if ((cnp->cn_flags & CNP_MAKEENTRY) == 0) {
327 /* We don't want to have an entry, so dump it */
328 if ((cnp->cn_flags & CNP_MAKEENTRY) == 0) {
330 nchstats.ncs_badhits++;
335 /* We found a "positive" match, return the vnode */
338 nchstats.ncs_goodhits++;
344 /* We found a negative match, and want to create it, so purge */
345 if (cnp->cn_nameiop == NAMEI_CREATE) {
347 nchstats.ncs_badhits++;
355 * We found a "negative" match, ENOENT notifies client of this match.
356 * The nc_flag field records whether this is a whiteout. Since there
357 * is no vnode we can use the vnode tailq link field with ncneglist.
359 TAILQ_REMOVE(&ncneglist, ncp, nc_vnode);
360 TAILQ_INSERT_TAIL(&ncneglist, ncp, nc_vnode);
361 nchstats.ncs_neghits++;
362 if (ncp->nc_flag & NCF_WHITEOUT)
363 cnp->cn_flags |= CNP_ISWHITEOUT;
369 * Generate a special linkage between the mount point and the root of the
370 * mounted filesystem in order to maintain the namecache topology across
371 * a mount point. The special linkage has a 0-length name component
372 * and sets NCF_MOUNTPT.
375 cache_mount(struct vnode *dvp, struct vnode *tvp)
377 struct namecache *ncp;
378 struct namecache *par;
379 struct nchashhead *nchpp;
383 * If a linkage already exists we do not have to do anything.
385 hash = fnv_32_buf("", 0, FNV1_32_INIT);
386 hash = fnv_32_buf(&dvp->v_id, sizeof(dvp->v_id), hash);
387 LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) {
389 if (ncp->nc_vp == tvp &&
391 /* ncp->nc_parent == par STAGE-3 par instad of dvp */
392 ncp->nc_dvp_data == (uintptr_t)dvp && /* STAGE-2 only */
393 ncp->nc_dvp_id == dvp->v_id /* STAGE-2 only */
400 * STAGE-2 par can be NULL
401 * STAGE-3 par is passed as argument and cannot be NULL
403 par = TAILQ_FIRST(&dvp->v_namecache);
406 * Otherwise create a new linkage.
408 ncp = malloc(sizeof(*ncp), M_VFSCACHE, M_WAITOK|M_ZERO);
411 TAILQ_INIT(&ncp->nc_list);
412 ncp->nc_flag = NCF_MOUNTPT;
414 /* STAGE-3 par never NULL */
415 ncp->nc_parent = par;
416 if (TAILQ_EMPTY(&par->nc_list)) {
420 TAILQ_INSERT_HEAD(&par->nc_list, ncp, nc_entry);
422 ncp->nc_dvp_data = (uintptr_t)dvp; /* STAGE-2 ONLY */
423 ncp->nc_dvp_id = dvp->v_id; /* STAGE-2 ONLY */
426 * Linkup the target vnode. The target vnode is NULL if this is
427 * to be a negative cache entry.
430 TAILQ_INSERT_HEAD(&tvp->v_namecache, ncp, nc_vnode);
432 if (tvp->v_type == VDIR) {
434 vp->v_ddid = dvp->v_id;
441 hash = fnv_32_buf("", 0, FNV1_32_INIT);
442 hash = fnv_32_buf(&ncp->nc_dvp_id, sizeof(ncp->nc_dvp_id), hash);
443 nchpp = NCHHASH(hash);
444 LIST_INSERT_HEAD(nchpp, ncp, nc_hash);
446 ncp->nc_flag |= NCF_HASHED;
450 * Add an entry to the cache.
453 cache_enter(struct vnode *dvp, struct namecache *par, struct vnode *vp, struct componentname *cnp)
455 struct namecache *ncp;
456 struct nchashhead *nchpp;
462 * "." and ".." are degenerate cases, they are not added to the
465 if (cnp->cn_nameptr[0] == '.') {
466 if (cnp->cn_namelen == 1) {
469 if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.') {
472 dvp->v_ddid = vp->v_id;
482 printf("ENTER '%*.*s' %p ", (int)cnp->cn_namelen, (int)cnp->cn_namelen, cnp->cn_nameptr, vp);
485 * Attempt to locate an unresolved entry in the cache and
486 * reassociate it, otherwise allocate a new entry. Unresolved
487 * entries can exist due to normal vnode reuse and/or cache
488 * purges issued by filesystems for various reasons.
491 hash = fnv_32_buf(cnp->cn_nameptr, cnp->cn_namelen, FNV1_32_INIT);
492 hash = fnv_32_buf(&dvp->v_id, sizeof(dvp->v_id), hash);
493 LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) {
495 if ((ncp->nc_flag & NCF_UNRESOLVED) &&
496 /* ncp->nc_parent == par STAGE-3 */
497 ncp->nc_dvp_data == (uintptr_t)dvp && /* STAGE-2 ONLY */
498 ncp->nc_dvp_id == dvp->v_id && /* STAGE-2 ONLY */
499 ncp->nc_nlen == cnp->cn_namelen &&
500 bcmp(ncp->nc_name, cnp->cn_nameptr, ncp->nc_nlen) == 0
504 printf("Reresolve %*.*s\n", (int)cnp->cn_namelen, (int)cnp->cn_namelen, cnp->cn_nameptr);
511 ncp = malloc(sizeof(*ncp), M_VFSCACHE, M_WAITOK | M_ZERO);
512 ncp->nc_name = malloc(cnp->cn_namelen, M_VFSCACHE, M_WAITOK);
513 TAILQ_INIT(&ncp->nc_list);
518 * Linkup the parent pointer, bump the parent vnode's hold
519 * count when we go from 0->1 children.
521 * STAGE-2 par may be NULL
522 * STAGE-3 par may not be NULL, nc_dvp_* removed
524 par = TAILQ_FIRST(&dvp->v_namecache);
526 ncp->nc_parent = par;
527 if (TAILQ_EMPTY(&par->nc_list)) {
531 TAILQ_INSERT_HEAD(&par->nc_list, ncp, nc_entry);
533 ncp->nc_dvp_data = (uintptr_t)dvp;
534 ncp->nc_dvp_id = dvp->v_id;
537 * Add to the hash table
539 ncp->nc_nlen = cnp->cn_namelen;
540 bcopy(cnp->cn_nameptr, ncp->nc_name, cnp->cn_namelen);
541 nchpp = NCHHASH(hash);
542 LIST_INSERT_HEAD(nchpp, ncp, nc_hash);
544 ncp->nc_flag |= NCF_HASHED;
545 } else if (vp && !TAILQ_EMPTY(&vp->v_namecache)) {
547 * STAGE-2 ONLY, will be gone in stage-3. Since we cannot
548 * directly invalidate unattached children in a directory
549 * when the directory is purged. we have to * clean them up
550 * as we go along. This is a big but temporary hack. In
551 * STAGE-3 there will be no unattached children.
553 struct namecache *scan;
554 struct namecache *next = NULL;
556 scan = TAILQ_FIRST(&vp->v_namecache);
558 for (; scan; scan = next) {
559 next = TAILQ_NEXT(scan, nc_vnode);
562 if (scan->nc_refs || !TAILQ_EMPTY(&scan->nc_list)) {
566 if ((scan->nc_flag & NCF_UNRESOLVED) || scan == ncp) {
570 if (scan->nc_parent == NULL) {
574 if (scan->nc_parent->nc_vp == NULL) {
578 if ((uintptr_t)scan->nc_parent->nc_vp != scan->nc_dvp_data ||
579 scan->nc_parent->nc_vp->v_id != scan->nc_dvp_id) {
588 * Linkup the target vnode. The target vnode is NULL if this is
589 * to be a negative cache entry.
593 ncp->nc_flag &= ~NCF_UNRESOLVED;
596 TAILQ_INSERT_HEAD(&ncneglist, ncp, nc_vnode);
597 ncp->nc_flag &= ~NCF_WHITEOUT;
598 if (cnp->cn_flags & CNP_ISWHITEOUT)
599 ncp->nc_flag |= NCF_WHITEOUT;
601 if (!TAILQ_EMPTY(&ncp->nc_list))
603 TAILQ_INSERT_HEAD(&vp->v_namecache, ncp, nc_vnode);
604 if (vp->v_type == VDIR) {
606 vp->v_ddid = dvp->v_id;
611 * Don't cache too many negative hits
613 if (numneg * ncnegfactor > numcache) {
614 ncp = TAILQ_FIRST(&ncneglist);
615 KKASSERT(ncp != NULL);
616 cache_zap(cache_hold(ncp));
621 * Name cache initialization, from vfs_init() when we are booting
623 * rootnamecache is initialized such that it cannot be recursively deleted.
628 TAILQ_INIT(&ncneglist);
629 nchashtbl = hashinit(desiredvnodes*2, M_VFSCACHE, &nchash);
630 TAILQ_INIT(&rootnamecache.nc_list);
631 rootnamecache.nc_flag |= NCF_HASHED | NCF_ROOT | NCF_UNRESOLVED;
632 rootnamecache.nc_refs = 1;
636 * vfs_cache_setroot()
638 * Create an association between the root of our namecache and
639 * the root vnode. This routine may be called several times during
643 vfs_cache_setroot(struct vnode *nvp)
645 KKASSERT(rootnamecache.nc_refs > 0); /* don't accidently free */
646 cache_zap(cache_hold(&rootnamecache));
648 rootnamecache.nc_vp = nvp;
649 rootnamecache.nc_flag &= ~NCF_UNRESOLVED;
652 if (!TAILQ_EMPTY(&rootnamecache.nc_list))
654 TAILQ_INSERT_HEAD(&nvp->v_namecache, &rootnamecache, nc_vnode);
657 TAILQ_INSERT_HEAD(&ncneglist, &rootnamecache, nc_vnode);
658 rootnamecache.nc_flag &= ~NCF_WHITEOUT;
663 * Invalidate all namecache entries to a particular vnode as well as
664 * any direct children of that vnode in the namecache. This is a
665 * 'catch all' purge used by filesystems that do not know any better.
667 * A new vnode v_id is generated. Note that no vnode will ever have a
670 * Note that the linkage between the vnode and its namecache entries will
671 * be removed, but the namecache entries themselves might stay put due to
672 * active references from elsewhere in the system or due to the existance of
673 * the children. The namecache topology is left intact even if we do not
674 * know what the vnode association is. Such entries will be marked
677 * XXX: Only time and the size of v_id prevents this from failing:
678 * XXX: In theory we should hunt down all (struct vnode*, v_id)
679 * XXX: soft references and nuke them, at least on the global
680 * XXX: v_id wraparound. The period of resistance can be extended
681 * XXX: by incrementing each vnodes v_id individually instead of
682 * XXX: using the global v_id.
685 cache_purge(struct vnode *vp)
687 static u_long nextid;
688 struct namecache *ncp;
689 struct namecache *scan;
692 * Disassociate the vnode from its namecache entries along with
693 * (for historical reasons) any direct children.
695 while ((ncp = TAILQ_FIRST(&vp->v_namecache)) != NULL) {
698 restart: /* YYY hack, fix me */
699 TAILQ_FOREACH(scan, &ncp->nc_list, nc_entry) {
700 if ((scan->nc_flag & NCF_UNRESOLVED) == 0) {
701 cache_zap(cache_hold(scan));
709 * Calculate a new unique id for ".." handling
713 } while (nextid == vp->v_id || nextid == 0);
720 * Flush all entries referencing a particular filesystem.
722 * Since we need to check it anyway, we will flush all the invalid
723 * entries at the same time.
726 cache_purgevfs(struct mount *mp)
728 struct nchashhead *nchpp;
729 struct namecache *ncp, *nnp;
732 * Scan hash tables for applicable entries.
734 for (nchpp = &nchashtbl[nchash]; nchpp >= nchashtbl; nchpp--) {
735 ncp = LIST_FIRST(nchpp);
739 nnp = LIST_NEXT(ncp, nc_hash);
742 if (ncp->nc_vp && ncp->nc_vp->v_mount == mp)
754 * Test whether the vnode is at a leaf in the nameicache tree.
756 * Returns 0 if it is a leaf, -1 if it isn't.
759 cache_leaf_test(struct vnode *vp)
761 struct namecache *scan;
762 struct namecache *ncp;
764 TAILQ_FOREACH(scan, &vp->v_namecache, nc_vnode) {
765 TAILQ_FOREACH(ncp, &scan->nc_list, nc_entry) {
766 /* YYY && ncp->nc_vp->v_type == VDIR ? */
767 if (ncp->nc_vp != NULL)
775 * Perform canonical checks and cache lookup and pass on to filesystem
776 * through the vop_cachedlookup only if needed.
779 * struct vnode a_dvp;
780 * struct namecache *a_ncp;
781 * struct vnode **a_vpp;
782 * struct namecache **a_ncpp;
783 * struct componentname *a_cnp;
787 vfs_cache_lookup(struct vop_lookup_args *ap)
789 struct vnode *dvp, *vp;
792 struct namecache *par = ap->a_par;
793 struct vnode **vpp = ap->a_vpp;
794 struct namecache **ncpp = ap->a_ncpp;
795 struct componentname *cnp = ap->a_cnp;
796 struct ucred *cred = cnp->cn_cred;
797 int flags = cnp->cn_flags;
798 struct thread *td = cnp->cn_td;
799 u_long vpid; /* capability number of vnode */
805 lockparent = flags & CNP_LOCKPARENT;
807 if (dvp->v_type != VDIR)
810 if ((flags & CNP_ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
811 (cnp->cn_nameiop == NAMEI_DELETE || cnp->cn_nameiop == NAMEI_RENAME)) {
815 error = VOP_ACCESS(dvp, VEXEC, cred, td);
820 error = cache_lookup(dvp, par, vpp, ncpp, cnp);
823 return (VOP_CACHEDLOOKUP(dvp, par, vpp, ncpp, cnp));
830 cnp->cn_flags &= ~CNP_PDIRUNLOCK;
831 if (dvp == vp) { /* lookup on "." */
834 } else if (flags & CNP_ISDOTDOT) {
835 VOP_UNLOCK(dvp, 0, td);
836 cnp->cn_flags |= CNP_PDIRUNLOCK;
837 error = vget(vp, LK_EXCLUSIVE, td);
838 if (!error && lockparent && (flags & CNP_ISLASTCN)) {
839 if ((error = vn_lock(dvp, LK_EXCLUSIVE, td)) == 0)
840 cnp->cn_flags &= ~CNP_PDIRUNLOCK;
843 error = vget(vp, LK_EXCLUSIVE, td);
844 if (!lockparent || error || !(flags & CNP_ISLASTCN)) {
845 VOP_UNLOCK(dvp, 0, td);
846 cnp->cn_flags |= CNP_PDIRUNLOCK;
850 * Check that the capability number did not change
851 * while we were waiting for the lock.
854 if (vpid == vp->v_id)
857 if (lockparent && dvp != vp && (flags & CNP_ISLASTCN)) {
858 VOP_UNLOCK(dvp, 0, td);
859 cnp->cn_flags |= CNP_PDIRUNLOCK;
862 if (cnp->cn_flags & CNP_PDIRUNLOCK) {
863 error = vn_lock(dvp, LK_EXCLUSIVE, td);
866 cnp->cn_flags &= ~CNP_PDIRUNLOCK;
868 return (VOP_CACHEDLOOKUP(dvp, par, vpp, ncpp, cnp));
871 static int disablecwd;
872 SYSCTL_INT(_debug, OID_AUTO, disablecwd, CTLFLAG_RW, &disablecwd, 0, "");
874 static u_long numcwdcalls; STATNODE(CTLFLAG_RD, numcwdcalls, &numcwdcalls);
875 static u_long numcwdfail1; STATNODE(CTLFLAG_RD, numcwdfail1, &numcwdfail1);
876 static u_long numcwdfail2; STATNODE(CTLFLAG_RD, numcwdfail2, &numcwdfail2);
877 static u_long numcwdfail3; STATNODE(CTLFLAG_RD, numcwdfail3, &numcwdfail3);
878 static u_long numcwdfail4; STATNODE(CTLFLAG_RD, numcwdfail4, &numcwdfail4);
879 static u_long numcwdfound; STATNODE(CTLFLAG_RD, numcwdfound, &numcwdfound);
882 __getcwd(struct __getcwd_args *uap)
884 struct proc *p = curproc;
886 int error, i, slash_prefixed;
887 struct filedesc *fdp;
888 struct namecache *ncp;
896 if (uap->buflen > MAXPATHLEN)
897 uap->buflen = MAXPATHLEN;
898 buf = bp = malloc(uap->buflen, M_TEMP, M_WAITOK);
899 bp += uap->buflen - 1;
903 for (vp = fdp->fd_cdir; vp != fdp->fd_rdir && vp != rootvnode;) {
904 if (vp->v_flag & VROOT) {
905 if (vp->v_mount == NULL) { /* forced unmount */
909 vp = vp->v_mount->mnt_vnodecovered;
912 if (vp->v_dd->v_id != vp->v_ddid) {
917 TAILQ_FOREACH(ncp, &vp->v_namecache, nc_vnode) {
918 /* ncp->nc_parent == par STAGE-3 */
919 if (ncp->nc_dvp_data == (uintptr_t)vp->v_dd &&
920 ncp->nc_dvp_id == vp->v_ddid) {
929 for (i = ncp->nc_nlen - 1; i >= 0; i--) {
935 *--bp = ncp->nc_name[i];
946 if (!slash_prefixed) {
955 error = copyout(bp, uap->buf, strlen(bp) + 1);
961 * Thus begins the fullpath magic.
965 #define STATNODE(name) \
967 SYSCTL_UINT(_vfs_cache, OID_AUTO, name, CTLFLAG_RD, &name, 0, "")
969 static int disablefullpath;
970 SYSCTL_INT(_debug, OID_AUTO, disablefullpath, CTLFLAG_RW,
971 &disablefullpath, 0, "");
973 STATNODE(numfullpathcalls);
974 STATNODE(numfullpathfail1);
975 STATNODE(numfullpathfail2);
976 STATNODE(numfullpathfail3);
977 STATNODE(numfullpathfail4);
978 STATNODE(numfullpathfound);
981 textvp_fullpath(struct proc *p, char **retbuf, char **retfreebuf)
984 int i, slash_prefixed;
985 struct filedesc *fdp;
986 struct namecache *ncp;
987 struct vnode *vp, *textvp;
992 textvp = p->p_textvp;
995 buf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
996 bp = buf + MAXPATHLEN - 1;
1000 for (vp = textvp; vp != fdp->fd_rdir && vp != rootvnode;) {
1001 if (vp->v_flag & VROOT) {
1002 if (vp->v_mount == NULL) { /* forced unmount */
1006 vp = vp->v_mount->mnt_vnodecovered;
1009 if (vp != textvp && vp->v_dd->v_id != vp->v_ddid) {
1014 TAILQ_FOREACH(ncp, &vp->v_namecache, nc_vnode) {
1017 /* ncp->nc_parent == par STAGE-3 */
1018 if (ncp->nc_dvp_data == (uintptr_t)vp->v_dd &&
1019 ncp->nc_dvp_id == vp->v_ddid) {
1028 for (i = ncp->nc_nlen - 1; i >= 0; i--) {
1034 *--bp = ncp->nc_name[i];
1045 if (!slash_prefixed) {