Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/vfs_cache.c
| Show First 20 Lines • Show All 300 Lines • ▼ Show 20 Lines | |||||
| SYSCTL_OPAQUE(_vfs_cache, OID_AUTO, nchstats, CTLFLAG_RD | CTLFLAG_MPSAFE, | SYSCTL_OPAQUE(_vfs_cache, OID_AUTO, nchstats, CTLFLAG_RD | CTLFLAG_MPSAFE, | ||||
| &nchstats, sizeof(nchstats), "LU", | &nchstats, sizeof(nchstats), "LU", | ||||
| "VFS cache effectiveness statistics"); | "VFS cache effectiveness statistics"); | ||||
| static void cache_zap(struct namecache *ncp); | static void cache_zap(struct namecache *ncp); | ||||
| static int vn_vptocnp_locked(struct vnode **vp, struct ucred *cred, char *buf, | static int vn_vptocnp_locked(struct vnode **vp, struct ucred *cred, | ||||
| u_int *buflen); | int lkflags, char *buf, u_int *buflen); | ||||
| static int vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir, | static int vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir, | ||||
| char *buf, char **retbuf, u_int buflen); | int lkflags, char *buf, char **retbuf, u_int buflen); | ||||
| static MALLOC_DEFINE(M_VFSCACHE, "vfscache", "VFS name cache entries"); | static MALLOC_DEFINE(M_VFSCACHE, "vfscache", "VFS name cache entries"); | ||||
| #ifdef DIAGNOSTIC | #ifdef DIAGNOSTIC | ||||
| /* | /* | ||||
| * Grab an atomic snapshot of the name cache hash chain lengths | * Grab an atomic snapshot of the name cache hash chain lengths | ||||
| */ | */ | ||||
| static SYSCTL_NODE(_debug, OID_AUTO, hashstat, CTLFLAG_RW, NULL, | static SYSCTL_NODE(_debug, OID_AUTO, hashstat, CTLFLAG_RW, NULL, | ||||
| ▲ Show 20 Lines • Show All 755 Lines • ▼ Show 20 Lines | kern___getcwd(struct thread *td, char *buf, enum uio_seg bufseg, u_int buflen, | ||||
| tmpbuf = malloc(buflen, M_TEMP, M_WAITOK); | tmpbuf = malloc(buflen, M_TEMP, M_WAITOK); | ||||
| fdp = td->td_proc->p_fd; | fdp = td->td_proc->p_fd; | ||||
| FILEDESC_SLOCK(fdp); | FILEDESC_SLOCK(fdp); | ||||
| cdir = fdp->fd_cdir; | cdir = fdp->fd_cdir; | ||||
| VREF(cdir); | VREF(cdir); | ||||
| rdir = fdp->fd_rdir; | rdir = fdp->fd_rdir; | ||||
| VREF(rdir); | VREF(rdir); | ||||
| FILEDESC_SUNLOCK(fdp); | FILEDESC_SUNLOCK(fdp); | ||||
| error = vn_fullpath1(td, cdir, rdir, tmpbuf, &bp, buflen); | error = vn_fullpath1(td, cdir, rdir, 0, tmpbuf, &bp, buflen); | ||||
| vrele(rdir); | vrele(rdir); | ||||
| vrele(cdir); | vrele(cdir); | ||||
| if (!error) { | if (!error) { | ||||
| if (bufseg == UIO_SYSSPACE) | if (bufseg == UIO_SYSSPACE) | ||||
| bcopy(bp, buf, strlen(bp) + 1); | bcopy(bp, buf, strlen(bp) + 1); | ||||
| else | else | ||||
| error = copyout(bp, buf, strlen(bp) + 1); | error = copyout(bp, buf, strlen(bp) + 1); | ||||
| Show All 27 Lines | |||||
| STATNODE(numfullpathfail4, "Number of fullpath search errors (ENOMEM)"); | STATNODE(numfullpathfail4, "Number of fullpath search errors (ENOMEM)"); | ||||
| STATNODE(numfullpathfound, "Number of successful fullpath calls"); | STATNODE(numfullpathfound, "Number of successful fullpath calls"); | ||||
| /* | /* | ||||
| * Retrieve the full filesystem path that correspond to a vnode from the name | * Retrieve the full filesystem path that correspond to a vnode from the name | ||||
| * cache (if available) | * cache (if available) | ||||
| */ | */ | ||||
| int | int | ||||
| vn_fullpath(struct thread *td, struct vnode *vn, char **retbuf, char **freebuf) | vn_fullpath(struct thread *td, struct vnode *vn, int lkflags, char **retbuf, | ||||
| char **freebuf) | |||||
| { | { | ||||
| char *buf; | char *buf; | ||||
| struct filedesc *fdp; | struct filedesc *fdp; | ||||
| struct vnode *rdir; | struct vnode *rdir; | ||||
| int error; | int error; | ||||
| KASSERT((lkflags & ~LK_NOWAIT) == 0, | |||||
| ("invalid lkflags: %08x", lkflags)); | |||||
| if (disablefullpath) | if (disablefullpath) | ||||
| return (ENODEV); | return (ENODEV); | ||||
| if (vn == NULL) | if (vn == NULL) | ||||
| return (EINVAL); | return (EINVAL); | ||||
| buf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); | buf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); | ||||
| fdp = td->td_proc->p_fd; | fdp = td->td_proc->p_fd; | ||||
| FILEDESC_SLOCK(fdp); | FILEDESC_SLOCK(fdp); | ||||
| rdir = fdp->fd_rdir; | rdir = fdp->fd_rdir; | ||||
| VREF(rdir); | VREF(rdir); | ||||
| FILEDESC_SUNLOCK(fdp); | FILEDESC_SUNLOCK(fdp); | ||||
| error = vn_fullpath1(td, vn, rdir, buf, retbuf, MAXPATHLEN); | error = vn_fullpath1(td, vn, rdir, lkflags, buf, retbuf, MAXPATHLEN); | ||||
| vrele(rdir); | vrele(rdir); | ||||
| if (!error) | if (!error) | ||||
| *freebuf = buf; | *freebuf = buf; | ||||
| else | else | ||||
| free(buf, M_TEMP); | free(buf, M_TEMP); | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| Show All 11 Lines | vn_fullpath_global(struct thread *td, struct vnode *vn, | ||||
| char *buf; | char *buf; | ||||
| int error; | int error; | ||||
| if (disablefullpath) | if (disablefullpath) | ||||
| return (ENODEV); | return (ENODEV); | ||||
| if (vn == NULL) | if (vn == NULL) | ||||
| return (EINVAL); | return (EINVAL); | ||||
| buf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); | buf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); | ||||
| error = vn_fullpath1(td, vn, rootvnode, buf, retbuf, MAXPATHLEN); | error = vn_fullpath1(td, vn, rootvnode, 0, buf, retbuf, MAXPATHLEN); | ||||
| if (!error) | if (!error) | ||||
| *freebuf = buf; | *freebuf = buf; | ||||
| else | else | ||||
| free(buf, M_TEMP); | free(buf, M_TEMP); | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| int | int | ||||
| vn_vptocnp(struct vnode **vp, struct ucred *cred, char *buf, u_int *buflen) | vn_vptocnp(struct vnode **vp, struct ucred *cred, char *buf, u_int *buflen) | ||||
| { | { | ||||
| int error; | int error; | ||||
| CACHE_RLOCK(); | CACHE_RLOCK(); | ||||
| error = vn_vptocnp_locked(vp, cred, buf, buflen); | error = vn_vptocnp_locked(vp, cred, 0, buf, buflen); | ||||
| if (error == 0) | if (error == 0) | ||||
| CACHE_RUNLOCK(); | CACHE_RUNLOCK(); | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| static int | static int | ||||
| vn_vptocnp_locked(struct vnode **vp, struct ucred *cred, char *buf, | vn_vptocnp_locked(struct vnode **vp, struct ucred *cred, int lkflags, | ||||
| u_int *buflen) | char *buf, u_int *buflen) | ||||
| { | { | ||||
| struct vnode *dvp; | struct vnode *dvp; | ||||
| struct namecache *ncp; | struct namecache *ncp; | ||||
| int error; | int error; | ||||
| TAILQ_FOREACH(ncp, &((*vp)->v_cache_dst), nc_dst) { | TAILQ_FOREACH(ncp, &((*vp)->v_cache_dst), nc_dst) { | ||||
| if ((ncp->nc_flag & NCF_ISDOTDOT) == 0) | if ((ncp->nc_flag & NCF_ISDOTDOT) == 0) | ||||
| break; | break; | ||||
| Show All 18 Lines | if (ncp != NULL) { | ||||
| CACHE_RUNLOCK(); | CACHE_RUNLOCK(); | ||||
| vrele(dvp); | vrele(dvp); | ||||
| CACHE_RLOCK(); | CACHE_RLOCK(); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| SDT_PROBE(vfs, namecache, fullpath, miss, vp, 0, 0, 0, 0); | SDT_PROBE(vfs, namecache, fullpath, miss, vp, 0, 0, 0, 0); | ||||
| CACHE_RUNLOCK(); | CACHE_RUNLOCK(); | ||||
| vn_lock(*vp, LK_SHARED | LK_RETRY); | |||||
| lkflags |= LK_SHARED; | |||||
| if ((lkflags & LK_NOWAIT) == 0) | |||||
| lkflags |= LK_RETRY; | |||||
| error = vn_lock(*vp, lkflags); | |||||
| if (error) | |||||
| vrele(*vp); | |||||
| else { | |||||
| error = VOP_VPTOCNP(*vp, &dvp, cred, buf, buflen); | error = VOP_VPTOCNP(*vp, &dvp, cred, buf, buflen); | ||||
| vput(*vp); | vput(*vp); | ||||
| } | |||||
| if (error) { | if (error) { | ||||
| numfullpathfail2++; | numfullpathfail2++; | ||||
| SDT_PROBE(vfs, namecache, fullpath, return, error, vp, | SDT_PROBE(vfs, namecache, fullpath, return, error, vp, | ||||
| NULL, 0, 0); | NULL, 0, 0); | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| *vp = dvp; | *vp = dvp; | ||||
| Show All 14 Lines | vn_vptocnp_locked(struct vnode **vp, struct ucred *cred, int lkflags, | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| /* | /* | ||||
| * The magic behind kern___getcwd() and vn_fullpath(). | * The magic behind kern___getcwd() and vn_fullpath(). | ||||
| */ | */ | ||||
| static int | static int | ||||
| vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir, | vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir, | ||||
| char *buf, char **retbuf, u_int buflen) | int lkflags, char *buf, char **retbuf, u_int buflen) | ||||
| { | { | ||||
| int error, slash_prefixed; | int error, slash_prefixed; | ||||
| #ifdef KDTRACE_HOOKS | #ifdef KDTRACE_HOOKS | ||||
| struct vnode *startvp = vp; | struct vnode *startvp = vp; | ||||
| #endif | #endif | ||||
| struct vnode *vp1; | struct vnode *vp1; | ||||
| buflen--; | buflen--; | ||||
| buf[buflen] = '\0'; | buf[buflen] = '\0'; | ||||
| error = 0; | error = 0; | ||||
| slash_prefixed = 0; | slash_prefixed = 0; | ||||
| SDT_PROBE(vfs, namecache, fullpath, entry, vp, 0, 0, 0, 0); | SDT_PROBE(vfs, namecache, fullpath, entry, vp, 0, 0, 0, 0); | ||||
| numfullpathcalls++; | numfullpathcalls++; | ||||
| vref(vp); | vref(vp); | ||||
| CACHE_RLOCK(); | CACHE_RLOCK(); | ||||
| if (vp->v_type != VDIR) { | if (vp->v_type != VDIR) { | ||||
| error = vn_vptocnp_locked(&vp, td->td_ucred, buf, &buflen); | error = vn_vptocnp_locked(&vp, td->td_ucred, lkflags, buf, &buflen); | ||||
| if (error) | if (error) | ||||
| return (error); | return (error); | ||||
| if (buflen == 0) { | if (buflen == 0) { | ||||
| CACHE_RUNLOCK(); | CACHE_RUNLOCK(); | ||||
| vrele(vp); | vrele(vp); | ||||
| return (ENOMEM); | return (ENOMEM); | ||||
| } | } | ||||
| buf[--buflen] = '/'; | buf[--buflen] = '/'; | ||||
| Show All 21 Lines | if (vp->v_type != VDIR) { | ||||
| CACHE_RUNLOCK(); | CACHE_RUNLOCK(); | ||||
| vrele(vp); | vrele(vp); | ||||
| numfullpathfail1++; | numfullpathfail1++; | ||||
| error = ENOTDIR; | error = ENOTDIR; | ||||
| SDT_PROBE(vfs, namecache, fullpath, return, | SDT_PROBE(vfs, namecache, fullpath, return, | ||||
| error, vp, NULL, 0, 0); | error, vp, NULL, 0, 0); | ||||
| break; | break; | ||||
| } | } | ||||
| error = vn_vptocnp_locked(&vp, td->td_ucred, buf, &buflen); | error = vn_vptocnp_locked(&vp, td->td_ucred, lkflags, buf, &buflen); | ||||
| if (error) | if (error) | ||||
| break; | break; | ||||
| if (buflen == 0) { | if (buflen == 0) { | ||||
| CACHE_RUNLOCK(); | CACHE_RUNLOCK(); | ||||
| vrele(vp); | vrele(vp); | ||||
| error = ENOMEM; | error = ENOMEM; | ||||
| SDT_PROBE(vfs, namecache, fullpath, return, error, | SDT_PROBE(vfs, namecache, fullpath, return, error, | ||||
| startvp, NULL, 0, 0); | startvp, NULL, 0, 0); | ||||
| ▲ Show 20 Lines • Show All 153 Lines • Show Last 20 Lines | |||||