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.14 2004/04/02 05:46:02 hmp 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>
55 #include <sys/globaldata.h>
58 * Random lookups in the cache are accomplished with a hash table using
59 * a hash key of (nc_src_vp, name).
61 * Negative entries may exist and correspond to structures where nc_vp
62 * is NULL. In a negative entry, NCF_WHITEOUT will be set if the entry
63 * corresponds to a whited-out directory entry (verses simply not finding the
66 * Upon reaching the last segment of a path, if the reference is for DELETE,
67 * or NOCACHE is set (rewrite), and the name is located in the cache, it
72 * Structures associated with name cacheing.
74 #define NCHHASH(hash) (&nchashtbl[(hash) & nchash])
77 MALLOC_DEFINE(M_VFSCACHE, "vfscache", "VFS name cache entries");
79 static LIST_HEAD(nchashhead, namecache) *nchashtbl; /* Hash Table */
80 static struct namecache_list ncneglist; /* instead of vnode */
81 static struct namecache rootnamecache; /* Dummy node */
83 static int nczapcheck; /* panic on bad release */
84 SYSCTL_INT(_debug, OID_AUTO, nczapcheck, CTLFLAG_RW, &nczapcheck, 0, "");
86 static u_long nchash; /* size of hash table */
87 SYSCTL_ULONG(_debug, OID_AUTO, nchash, CTLFLAG_RD, &nchash, 0, "");
89 static u_long ncnegfactor = 16; /* ratio of negative entries */
90 SYSCTL_ULONG(_debug, OID_AUTO, ncnegfactor, CTLFLAG_RW, &ncnegfactor, 0, "");
92 static u_long numneg; /* number of cache entries allocated */
93 SYSCTL_ULONG(_debug, OID_AUTO, numneg, CTLFLAG_RD, &numneg, 0, "");
95 static u_long numcache; /* number of cache entries allocated */
96 SYSCTL_ULONG(_debug, OID_AUTO, numcache, CTLFLAG_RD, &numcache, 0, "");
98 static u_long numunres; /* number of unresolved entries */
99 SYSCTL_ULONG(_debug, OID_AUTO, numunres, CTLFLAG_RD, &numunres, 0, "");
101 SYSCTL_INT(_debug, OID_AUTO, vnsize, CTLFLAG_RD, 0, sizeof(struct vnode), "");
102 SYSCTL_INT(_debug, OID_AUTO, ncsize, CTLFLAG_RD, 0, sizeof(struct namecache), "");
105 * The new name cache statistics
107 SYSCTL_NODE(_vfs, OID_AUTO, cache, CTLFLAG_RW, 0, "Name cache statistics");
108 #define STATNODE(mode, name, var) \
109 SYSCTL_ULONG(_vfs_cache, OID_AUTO, name, mode, var, 0, "");
110 STATNODE(CTLFLAG_RD, numneg, &numneg);
111 STATNODE(CTLFLAG_RD, numcache, &numcache);
112 static u_long numcalls; STATNODE(CTLFLAG_RD, numcalls, &numcalls);
113 static u_long dothits; STATNODE(CTLFLAG_RD, dothits, &dothits);
114 static u_long dotdothits; STATNODE(CTLFLAG_RD, dotdothits, &dotdothits);
115 static u_long numchecks; STATNODE(CTLFLAG_RD, numchecks, &numchecks);
116 static u_long nummiss; STATNODE(CTLFLAG_RD, nummiss, &nummiss);
117 static u_long nummisszap; STATNODE(CTLFLAG_RD, nummisszap, &nummisszap);
118 static u_long numposzaps; STATNODE(CTLFLAG_RD, numposzaps, &numposzaps);
119 static u_long numposhits; STATNODE(CTLFLAG_RD, numposhits, &numposhits);
120 static u_long numnegzaps; STATNODE(CTLFLAG_RD, numnegzaps, &numnegzaps);
121 static u_long numneghits; STATNODE(CTLFLAG_RD, numneghits, &numneghits);
123 struct nchstats nchstats[SMP_MAXCPU];
125 * Export VFS cache effectiveness statistics to user-land.
127 * The statistics are left for aggregation to user-land so
128 * neat things can be achieved, like observing per-CPU cache
132 nchstats_agg(SYSCTL_HANDLER_ARGS)
134 struct globaldata *gd;
138 for (i = 0; i < ncpus; ++i) {
139 gd = globaldata_find(i);
140 if ((error = SYSCTL_OUT(req, (void *)&(*gd->gd_nchstats),
141 sizeof(struct nchstats))))
147 SYSCTL_PROC(_vfs_cache, OID_AUTO, nchstats, CTLTYPE_OPAQUE|CTLFLAG_RD,
148 0, 0, nchstats_agg, "S,nchstats", "VFS cache effectiveness statistics");
150 static void cache_zap(struct namecache *ncp);
153 * cache_hold() and cache_drop() prevent the premature deletion of a
154 * namecache entry but do not prevent operations (such as zapping) on
155 * that namecache entry.
159 _cache_hold(struct namecache *ncp)
167 _cache_drop(struct namecache *ncp)
169 KKASSERT(ncp->nc_refs > 0);
170 if (ncp->nc_refs == 1 &&
171 (ncp->nc_flag & NCF_UNRESOLVED) &&
172 TAILQ_EMPTY(&ncp->nc_list)
181 cache_hold(struct namecache *ncp)
183 return(_cache_hold(ncp));
187 cache_drop(struct namecache *ncp)
193 * Try to destroy a namecache entry. The entry is disassociated from its
194 * vnode or ncneglist and reverted to an UNRESOLVED state.
196 * Then, if there are no additional references to the ncp and we can
197 * successfully delete the children, the entry is also removed from the
198 * namecache hashlist / topology.
200 * References or undeletable children will prevent the entry from being
201 * removed from the topology. The entry may be revalidated (typically
202 * by cache_enter()) at a later time. Children remain because:
204 * + we have tried to delete a node rather then a leaf in the topology.
205 * + the presence of negative entries (we try to scrap these).
206 * + an entry or child has a non-zero ref count and cannot be scrapped.
208 * This function must be called with the ncp held and will drop the ref
209 * count during zapping.
212 cache_zap(struct namecache *ncp)
214 struct namecache *par;
218 * Disassociate the vnode or negative cache ref and set NCF_UNRESOLVED.
220 if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
221 ncp->nc_flag |= NCF_UNRESOLVED;
223 if ((vp = ncp->nc_vp) != NULL) {
225 ncp->nc_vp = NULL; /* safety */
226 TAILQ_REMOVE(&vp->v_namecache, ncp, nc_vnode);
227 if (!TAILQ_EMPTY(&ncp->nc_list))
230 TAILQ_REMOVE(&ncneglist, ncp, nc_vnode);
236 * Try to scrap the entry and possibly tail-recurse on its parent.
237 * We only scrap unref'd (other then our ref) unresolved entries,
238 * we do not scrap 'live' entries.
240 while (ncp->nc_flag & NCF_UNRESOLVED) {
242 * Someone other then us has a ref, stop.
244 if (ncp->nc_refs > 1)
248 * We have children, stop.
250 if (!TAILQ_EMPTY(&ncp->nc_list))
254 * Ok, we can completely destroy and free this entry. Sanity
255 * check it against our static rootnamecache structure,
256 * then remove it from the hash.
258 KKASSERT(ncp != &rootnamecache);
260 if (ncp->nc_flag & NCF_HASHED) {
261 ncp->nc_flag &= ~NCF_HASHED;
262 LIST_REMOVE(ncp, nc_hash);
266 * Unlink from its parent and free, then loop on the
267 * parent. XXX temp hack, in stage-3 parent is never NULL
269 if ((par = ncp->nc_parent) != NULL) {
270 par = cache_hold(par);
271 TAILQ_REMOVE(&par->nc_list, ncp, nc_entry);
272 if (par->nc_vp && TAILQ_EMPTY(&par->nc_list))
276 ncp->nc_refs = -1; /* safety */
277 ncp->nc_parent = NULL; /* safety */
279 free(ncp->nc_name, M_VFSCACHE);
280 free(ncp, M_VFSCACHE);
282 if (par == NULL) /* temp hack */
283 return; /* temp hack */
290 * Lookup an entry in the cache
292 * Lookup is called with dvp pointing to the directory to search,
293 * cnp pointing to the name of the entry being sought.
295 * If the lookup succeeds, the vnode is returned in *vpp, and a
296 * status of -1 is returned.
298 * If the lookup determines that the name does not exist (negative cacheing),
299 * a status of ENOENT is returned.
301 * If the lookup fails, a status of zero is returned.
303 * Note that UNRESOLVED entries are ignored. They are not negative cache
307 cache_lookup(struct vnode *dvp, struct namecache *par, struct vnode **vpp,
308 struct namecache **ncpp, struct componentname *cnp)
310 struct namecache *ncp;
312 globaldata_t gd = mycpu;
316 if (cnp->cn_nameptr[0] == '.') {
317 if (cnp->cn_namelen == 1) {
320 numposhits++; /* include in total statistics */
323 if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.') {
325 numposhits++; /* include in total statistics */
326 if (dvp->v_dd->v_id != dvp->v_ddid ||
327 (cnp->cn_flags & CNP_MAKEENTRY) == 0) {
336 hash = fnv_32_buf(cnp->cn_nameptr, cnp->cn_namelen, FNV1_32_INIT);
337 hash = fnv_32_buf(&dvp->v_id, sizeof(dvp->v_id), hash);
338 LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) {
340 if ((ncp->nc_flag & NCF_UNRESOLVED) == 0 &&
341 /* ncp->nc_parent == par instead of dvp STAGE-3 */
342 ncp->nc_dvp_data == (uintptr_t)dvp && /* STAGE-2 only */
343 ncp->nc_dvp_id == dvp->v_id && /* STAGE-2 only */
344 ncp->nc_nlen == cnp->cn_namelen &&
345 bcmp(ncp->nc_name, cnp->cn_nameptr, ncp->nc_nlen) == 0
352 /* We failed to find an entry */
354 if ((cnp->cn_flags & CNP_MAKEENTRY) == 0) {
359 gd->gd_nchstats->ncs_miss++;
363 /* We don't want to have an entry, so dump it */
364 if ((cnp->cn_flags & CNP_MAKEENTRY) == 0) {
366 gd->gd_nchstats->ncs_badhits++;
371 /* We found a "positive" match, return the vnode */
374 gd->gd_nchstats->ncs_goodhits++;
380 /* We found a negative match, and want to create it, so purge */
381 if (cnp->cn_nameiop == NAMEI_CREATE) {
383 gd->gd_nchstats->ncs_badhits++;
391 * We found a "negative" match, ENOENT notifies client of this match.
392 * The nc_flag field records whether this is a whiteout. Since there
393 * is no vnode we can use the vnode tailq link field with ncneglist.
395 TAILQ_REMOVE(&ncneglist, ncp, nc_vnode);
396 TAILQ_INSERT_TAIL(&ncneglist, ncp, nc_vnode);
397 gd->gd_nchstats->ncs_neghits++;
398 if (ncp->nc_flag & NCF_WHITEOUT)
399 cnp->cn_flags |= CNP_ISWHITEOUT;
405 * Generate a special linkage between the mount point and the root of the
406 * mounted filesystem in order to maintain the namecache topology across
407 * a mount point. The special linkage has a 0-length name component
408 * and sets NCF_MOUNTPT.
411 cache_mount(struct vnode *dvp, struct vnode *tvp)
413 struct namecache *ncp;
414 struct namecache *par;
415 struct nchashhead *nchpp;
419 * If a linkage already exists we do not have to do anything.
421 hash = fnv_32_buf("", 0, FNV1_32_INIT);
422 hash = fnv_32_buf(&dvp->v_id, sizeof(dvp->v_id), hash);
423 LIST_FOREACH(ncp, (NCHHASH(hash)), nc_hash) {
425 if (ncp->nc_vp == tvp &&
427 /* ncp->nc_parent == par STAGE-3 par instad of dvp */
428 ncp->nc_dvp_data == (uintptr_t)dvp && /* STAGE-2 only */
429 ncp->nc_dvp_id == dvp->v_id /* STAGE-2 only */
436 * STAGE-2 par can be NULL
437 * STAGE-3 par is passed as argument and cannot be NULL
439 par = TAILQ_FIRST(&dvp->v_namecache);
442 * Otherwise create a new linkage.
444 ncp = malloc(sizeof(*ncp), M_VFSCACHE, M_WAITOK | M_ZERO);
446 TAILQ_INIT(&ncp->nc_list);
447 ncp->nc_flag = NCF_MOUNTPT;
449 /* STAGE-3 par never NULL */
450 ncp->nc_parent = par;
451 if (TAILQ_EMPTY(&par->nc_list)) {
455 TAILQ_INSERT_HEAD(&par->nc_list, ncp, nc_entry);
457 ncp->nc_dvp_data = (uintptr_t)dvp; /* STAGE-2 ONLY */
458 ncp->nc_dvp_id = dvp->v_id; /* STAGE-2 ONLY */
461 * Linkup the target vnode. The target vnode is NULL if this is
462 * to be a negative cache entry.
466 TAILQ_INSERT_HEAD(&tvp->v_namecache, ncp, nc_vnode);
468 if (tvp->v_type == VDIR) {
470 vp->v_ddid = dvp->v_id;
477 hash = fnv_32_buf("", 0, FNV1_32_INIT);
478 hash = fnv_32_buf(&ncp->nc_dvp_id, sizeof(ncp->nc_dvp_id), hash);
479 nchpp = NCHHASH(hash);
480 LIST_INSERT_HEAD(nchpp, ncp, nc_hash);
482 ncp->nc_flag |= NCF_HASHED;
486 * Add an entry to the cache.
489 cache_enter(struct vnode *dvp, struct namecache *par, struct vnode *vp, struct componentname *cnp)
491 struct namecache *ncp;
492 struct nchashhead *nchpp;
498 * "." and ".." are degenerate cases, they are not added to the
501 if (cnp->cn_nameptr[0] == '.') {
502 if (cnp->cn_namelen == 1) {
505 if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.') {
508 dvp->v_ddid = vp->v_id;
518 printf("ENTER '%*.*s' %p ", (int)cnp->cn_namelen, (int)cnp->cn_namelen, cnp->cn_nameptr, vp);
521 * Locate other entries associated with this vnode and zap them,
522 * because the purge code may not be able to find them due to
523 * the topology not yet being consistent. This is a temporary
528 TAILQ_FOREACH(ncp, &vp->v_namecache, nc_vnode) {
529 if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) {
530 cache_zap(cache_hold(ncp));
536 hash = fnv_32_buf(cnp->cn_nameptr, cnp->cn_namelen, FNV1_32_INIT);
537 hash = fnv_32_buf(&dvp->v_id, sizeof(dvp->v_id), hash);
539 ncp = malloc(sizeof(*ncp), M_VFSCACHE, M_WAITOK | M_ZERO);
540 ncp->nc_name = malloc(cnp->cn_namelen, M_VFSCACHE, M_WAITOK);
541 TAILQ_INIT(&ncp->nc_list);
546 * Linkup the parent pointer, bump the parent vnode's hold
547 * count when we go from 0->1 children.
549 * STAGE-2 par may be NULL
550 * STAGE-3 par may not be NULL, nc_dvp_* removed
552 par = TAILQ_FIRST(&dvp->v_namecache);
554 ncp->nc_parent = par;
555 if (TAILQ_EMPTY(&par->nc_list)) {
559 TAILQ_INSERT_HEAD(&par->nc_list, ncp, nc_entry);
561 ncp->nc_dvp_data = (uintptr_t)dvp;
562 ncp->nc_dvp_id = dvp->v_id;
565 * Add to the hash table
567 ncp->nc_nlen = cnp->cn_namelen;
568 bcopy(cnp->cn_nameptr, ncp->nc_name, cnp->cn_namelen);
569 nchpp = NCHHASH(hash);
570 LIST_INSERT_HEAD(nchpp, ncp, nc_hash);
572 ncp->nc_flag |= NCF_HASHED;
575 * Linkup the target vnode. The target vnode is NULL if this is
576 * to be a negative cache entry.
581 TAILQ_INSERT_HEAD(&ncneglist, ncp, nc_vnode);
582 ncp->nc_flag &= ~NCF_WHITEOUT;
583 if (cnp->cn_flags & CNP_ISWHITEOUT)
584 ncp->nc_flag |= NCF_WHITEOUT;
587 if (!TAILQ_EMPTY(&ncp->nc_list))
589 TAILQ_INSERT_HEAD(&vp->v_namecache, ncp, nc_vnode);
590 if (vp->v_type == VDIR) {
592 vp->v_ddid = dvp->v_id;
597 * Don't cache too many negative hits
599 if (numneg > MINNEG && numneg * ncnegfactor > numcache) {
600 ncp = TAILQ_FIRST(&ncneglist);
601 KKASSERT(ncp != NULL);
602 cache_zap(cache_hold(ncp));
607 * Name cache initialization, from vfsinit() when we are booting
609 * rootnamecache is initialized such that it cannot be recursively deleted.
617 /* initialise per-cpu namecache effectiveness statistics. */
618 for (i = 0; i < ncpus; ++i) {
619 gd = globaldata_find(i);
620 gd->gd_nchstats = &nchstats[i];
623 TAILQ_INIT(&ncneglist);
624 nchashtbl = hashinit(desiredvnodes*2, M_VFSCACHE, &nchash);
625 TAILQ_INIT(&rootnamecache.nc_list);
626 rootnamecache.nc_flag |= NCF_HASHED | NCF_ROOT | NCF_UNRESOLVED;
627 rootnamecache.nc_refs = 1;
631 * vfs_cache_setroot()
633 * Create an association between the root of our namecache and
634 * the root vnode. This routine may be called several times during
638 vfs_cache_setroot(struct vnode *nvp)
640 KKASSERT(rootnamecache.nc_refs > 0); /* don't accidently free */
641 cache_zap(cache_hold(&rootnamecache));
643 rootnamecache.nc_vp = nvp;
644 rootnamecache.nc_flag &= ~NCF_UNRESOLVED;
647 if (!TAILQ_EMPTY(&rootnamecache.nc_list))
649 TAILQ_INSERT_HEAD(&nvp->v_namecache, &rootnamecache, nc_vnode);
652 TAILQ_INSERT_HEAD(&ncneglist, &rootnamecache, nc_vnode);
653 rootnamecache.nc_flag &= ~NCF_WHITEOUT;
658 * Invalidate all namecache entries to a particular vnode as well as
659 * any direct children of that vnode in the namecache. This is a
660 * 'catch all' purge used by filesystems that do not know any better.
662 * A new vnode v_id is generated. Note that no vnode will ever have a
665 * Note that the linkage between the vnode and its namecache entries will
666 * be removed, but the namecache entries themselves might stay put due to
667 * active references from elsewhere in the system or due to the existance of
668 * the children. The namecache topology is left intact even if we do not
669 * know what the vnode association is. Such entries will be marked
672 * XXX: Only time and the size of v_id prevents this from failing:
673 * XXX: In theory we should hunt down all (struct vnode*, v_id)
674 * XXX: soft references and nuke them, at least on the global
675 * XXX: v_id wraparound. The period of resistance can be extended
676 * XXX: by incrementing each vnodes v_id individually instead of
677 * XXX: using the global v_id.
680 cache_purge(struct vnode *vp)
682 static u_long nextid;
683 struct namecache *ncp;
684 struct namecache *scan;
687 * Disassociate the vnode from its namecache entries along with
688 * (for historical reasons) any direct children.
690 while ((ncp = TAILQ_FIRST(&vp->v_namecache)) != NULL) {
693 restart: /* YYY hack, fix me */
694 TAILQ_FOREACH(scan, &ncp->nc_list, nc_entry) {
695 if ((scan->nc_flag & NCF_UNRESOLVED) == 0) {
696 cache_zap(cache_hold(scan));
704 * Calculate a new unique id for ".." handling
708 } while (nextid == vp->v_id || nextid == 0);
715 * Flush all entries referencing a particular filesystem.
717 * Since we need to check it anyway, we will flush all the invalid
718 * entries at the same time.
721 cache_purgevfs(struct mount *mp)
723 struct nchashhead *nchpp;
724 struct namecache *ncp, *nnp;
727 * Scan hash tables for applicable entries.
729 for (nchpp = &nchashtbl[nchash]; nchpp >= nchashtbl; nchpp--) {
730 ncp = LIST_FIRST(nchpp);
734 nnp = LIST_NEXT(ncp, nc_hash);
737 if (ncp->nc_vp && ncp->nc_vp->v_mount == mp)
749 * Test whether the vnode is at a leaf in the nameicache tree.
751 * Returns 0 if it is a leaf, -1 if it isn't.
754 cache_leaf_test(struct vnode *vp)
756 struct namecache *scan;
757 struct namecache *ncp;
759 TAILQ_FOREACH(scan, &vp->v_namecache, nc_vnode) {
760 TAILQ_FOREACH(ncp, &scan->nc_list, nc_entry) {
761 /* YYY && ncp->nc_vp->v_type == VDIR ? */
762 if (ncp->nc_vp != NULL)
770 * Perform canonical checks and cache lookup and pass on to filesystem
771 * through the vop_cachedlookup only if needed.
774 * struct vnode a_dvp;
775 * struct namecache *a_ncp;
776 * struct vnode **a_vpp;
777 * struct namecache **a_ncpp;
778 * struct componentname *a_cnp;
782 vfs_cache_lookup(struct vop_lookup_args *ap)
784 struct vnode *dvp, *vp;
787 struct namecache *par = ap->a_par;
788 struct vnode **vpp = ap->a_vpp;
789 struct namecache **ncpp = ap->a_ncpp;
790 struct componentname *cnp = ap->a_cnp;
791 struct ucred *cred = cnp->cn_cred;
792 int flags = cnp->cn_flags;
793 struct thread *td = cnp->cn_td;
794 u_long vpid; /* capability number of vnode */
800 lockparent = flags & CNP_LOCKPARENT;
802 if (dvp->v_type != VDIR)
805 if ((flags & CNP_ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
806 (cnp->cn_nameiop == NAMEI_DELETE || cnp->cn_nameiop == NAMEI_RENAME)) {
810 error = VOP_ACCESS(dvp, VEXEC, cred, td);
815 error = cache_lookup(dvp, par, vpp, ncpp, cnp);
818 return (VOP_CACHEDLOOKUP(dvp, par, vpp, ncpp, cnp));
825 cnp->cn_flags &= ~CNP_PDIRUNLOCK;
826 if (dvp == vp) { /* lookup on "." */
829 } else if (flags & CNP_ISDOTDOT) {
830 VOP_UNLOCK(dvp, NULL, 0, td);
831 cnp->cn_flags |= CNP_PDIRUNLOCK;
832 error = vget(vp, NULL, LK_EXCLUSIVE, td);
833 if (!error && lockparent && (flags & CNP_ISLASTCN)) {
834 if ((error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td)) == 0)
835 cnp->cn_flags &= ~CNP_PDIRUNLOCK;
838 error = vget(vp, NULL, LK_EXCLUSIVE, td);
839 if (!lockparent || error || !(flags & CNP_ISLASTCN)) {
840 VOP_UNLOCK(dvp, NULL, 0, td);
841 cnp->cn_flags |= CNP_PDIRUNLOCK;
845 * Check that the capability number did not change
846 * while we were waiting for the lock.
849 if (vpid == vp->v_id)
852 if (lockparent && dvp != vp && (flags & CNP_ISLASTCN)) {
853 VOP_UNLOCK(dvp, NULL, 0, td);
854 cnp->cn_flags |= CNP_PDIRUNLOCK;
857 if (cnp->cn_flags & CNP_PDIRUNLOCK) {
858 error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td);
861 cnp->cn_flags &= ~CNP_PDIRUNLOCK;
863 return (VOP_CACHEDLOOKUP(dvp, par, vpp, ncpp, cnp));
866 static int disablecwd;
867 SYSCTL_INT(_debug, OID_AUTO, disablecwd, CTLFLAG_RW, &disablecwd, 0, "");
869 static u_long numcwdcalls; STATNODE(CTLFLAG_RD, numcwdcalls, &numcwdcalls);
870 static u_long numcwdfail1; STATNODE(CTLFLAG_RD, numcwdfail1, &numcwdfail1);
871 static u_long numcwdfail2; STATNODE(CTLFLAG_RD, numcwdfail2, &numcwdfail2);
872 static u_long numcwdfail3; STATNODE(CTLFLAG_RD, numcwdfail3, &numcwdfail3);
873 static u_long numcwdfail4; STATNODE(CTLFLAG_RD, numcwdfail4, &numcwdfail4);
874 static u_long numcwdfound; STATNODE(CTLFLAG_RD, numcwdfound, &numcwdfound);
877 __getcwd(struct __getcwd_args *uap)
879 struct proc *p = curproc;
881 int error, i, slash_prefixed;
882 struct filedesc *fdp;
883 struct namecache *ncp;
891 if (uap->buflen > MAXPATHLEN)
892 uap->buflen = MAXPATHLEN;
893 buf = bp = malloc(uap->buflen, M_TEMP, M_WAITOK);
894 bp += uap->buflen - 1;
898 for (vp = fdp->fd_cdir; vp != fdp->fd_rdir && vp != rootvnode;) {
899 if (vp->v_flag & VROOT) {
900 if (vp->v_mount == NULL) { /* forced unmount */
904 vp = vp->v_mount->mnt_vnodecovered;
907 if (vp->v_dd->v_id != vp->v_ddid) {
912 TAILQ_FOREACH(ncp, &vp->v_namecache, nc_vnode) {
913 /* ncp->nc_parent == par STAGE-3 */
914 if (ncp->nc_dvp_data == (uintptr_t)vp->v_dd &&
915 ncp->nc_dvp_id == vp->v_ddid) {
924 for (i = ncp->nc_nlen - 1; i >= 0; i--) {
930 *--bp = ncp->nc_name[i];
941 if (!slash_prefixed) {
950 error = copyout(bp, uap->buf, strlen(bp) + 1);
956 * Thus begins the fullpath magic.
960 #define STATNODE(name) \
962 SYSCTL_UINT(_vfs_cache, OID_AUTO, name, CTLFLAG_RD, &name, 0, "")
964 static int disablefullpath;
965 SYSCTL_INT(_debug, OID_AUTO, disablefullpath, CTLFLAG_RW,
966 &disablefullpath, 0, "");
968 STATNODE(numfullpathcalls);
969 STATNODE(numfullpathfail1);
970 STATNODE(numfullpathfail2);
971 STATNODE(numfullpathfail3);
972 STATNODE(numfullpathfail4);
973 STATNODE(numfullpathfound);
976 textvp_fullpath(struct proc *p, char **retbuf, char **retfreebuf)
979 int i, slash_prefixed;
980 struct filedesc *fdp;
981 struct namecache *ncp;
982 struct vnode *vp, *textvp;
987 textvp = p->p_textvp;
990 buf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
991 bp = buf + MAXPATHLEN - 1;
995 for (vp = textvp; vp != fdp->fd_rdir && vp != rootvnode;) {
996 if (vp->v_flag & VROOT) {
997 if (vp->v_mount == NULL) { /* forced unmount */
1001 vp = vp->v_mount->mnt_vnodecovered;
1004 if (vp != textvp && vp->v_dd->v_id != vp->v_ddid) {
1009 TAILQ_FOREACH(ncp, &vp->v_namecache, nc_vnode) {
1012 /* ncp->nc_parent == par STAGE-3 */
1013 if (ncp->nc_dvp_data == (uintptr_t)vp->v_dd &&
1014 ncp->nc_dvp_id == vp->v_ddid) {
1023 for (i = ncp->nc_nlen - 1; i >= 0; i--) {
1029 *--bp = ncp->nc_name[i];
1040 if (!slash_prefixed) {