| 3027 | } |
| 3028 | |
| 3029 | int |
| 3030 | vn_vptocnp(struct vnode **vp, char *buf, size_t *buflen) |
| 3031 | { |
| 3032 | struct vnode *dvp; |
| 3033 | struct namecache *ncp; |
| 3034 | struct mtx *vlp; |
| 3035 | int error; |
| 3036 | |
| 3037 | vlp = VP2VNODELOCK(*vp); |
| 3038 | mtx_lock(vlp); |
| 3039 | ncp = (*vp)->v_cache_dd; |
| 3040 | if (ncp != NULL && (ncp->nc_flag & NCF_ISDOTDOT) == 0) { |
| 3041 | KASSERT(ncp == vn_dd_from_dst(*vp), |
| 3042 | ("%s: mismatch for dd entry (%p != %p)", __func__, |
| 3043 | ncp, vn_dd_from_dst(*vp))); |
| 3044 | } else { |
| 3045 | ncp = vn_dd_from_dst(*vp); |
| 3046 | } |
| 3047 | if (ncp != NULL) { |
| 3048 | if (*buflen < ncp->nc_nlen) { |
| 3049 | mtx_unlock(vlp); |
| 3050 | vrele(*vp); |
| 3051 | counter_u64_add(numfullpathfail4, 1); |
| 3052 | error = ENOMEM; |
| 3053 | SDT_PROBE3(vfs, namecache, fullpath, return, error, |
| 3054 | vp, NULL); |
| 3055 | return (error); |
| 3056 | } |
| 3057 | *buflen -= ncp->nc_nlen; |
| 3058 | memcpy(buf + *buflen, ncp->nc_name, ncp->nc_nlen); |
| 3059 | SDT_PROBE3(vfs, namecache, fullpath, hit, ncp->nc_dvp, |
| 3060 | ncp->nc_name, vp); |
| 3061 | dvp = *vp; |
| 3062 | *vp = ncp->nc_dvp; |
| 3063 | vref(*vp); |
| 3064 | mtx_unlock(vlp); |
| 3065 | vrele(dvp); |
| 3066 | return (0); |
| 3067 | } |
| 3068 | SDT_PROBE1(vfs, namecache, fullpath, miss, vp); |
| 3069 | |
| 3070 | mtx_unlock(vlp); |
| 3071 | vn_lock(*vp, LK_SHARED | LK_RETRY); |
| 3072 | error = VOP_VPTOCNP(*vp, &dvp, buf, buflen); |
| 3073 | vput(*vp); |
| 3074 | if (error) { |
| 3075 | counter_u64_add(numfullpathfail2, 1); |
| 3076 | SDT_PROBE3(vfs, namecache, fullpath, return, error, vp, NULL); |
| 3077 | return (error); |
| 3078 | } |
| 3079 | |
| 3080 | *vp = dvp; |
| 3081 | if (VN_IS_DOOMED(dvp)) { |
| 3082 | /* forced unmount */ |
| 3083 | vrele(dvp); |
| 3084 | error = ENOENT; |
| 3085 | SDT_PROBE3(vfs, namecache, fullpath, return, error, vp, NULL); |
| 3086 | return (error); |
no test coverage detected