* Resolve a directory to a pathname. * * The name of the directory can always be found in the namecache or fetched * from the filesystem. There is also guaranteed to be only one parent, meaning * we can just follow vnodes up until we find the root. * * The vnode must be referenced. */
| 3102 | * The vnode must be referenced. |
| 3103 | */ |
| 3104 | static int |
| 3105 | vn_fullpath_dir(struct vnode *vp, struct vnode *rdir, char *buf, char **retbuf, |
| 3106 | size_t *len, size_t addend) |
| 3107 | { |
| 3108 | #ifdef KDTRACE_HOOKS |
| 3109 | struct vnode *startvp = vp; |
| 3110 | #endif |
| 3111 | struct vnode *vp1; |
| 3112 | size_t buflen; |
| 3113 | int error; |
| 3114 | bool slash_prefixed; |
| 3115 | |
| 3116 | VNPASS(vp->v_type == VDIR || VN_IS_DOOMED(vp), vp); |
| 3117 | VNPASS(vp->v_usecount > 0, vp); |
| 3118 | |
| 3119 | buflen = *len; |
| 3120 | |
| 3121 | slash_prefixed = true; |
| 3122 | if (addend == 0) { |
| 3123 | MPASS(*len >= 2); |
| 3124 | buflen--; |
| 3125 | buf[buflen] = '\0'; |
| 3126 | slash_prefixed = false; |
| 3127 | } |
| 3128 | |
| 3129 | error = 0; |
| 3130 | |
| 3131 | SDT_PROBE1(vfs, namecache, fullpath, entry, vp); |
| 3132 | counter_u64_add(numfullpathcalls, 1); |
| 3133 | while (vp != rdir && vp != rootvnode) { |
| 3134 | /* |
| 3135 | * The vp vnode must be already fully constructed, |
| 3136 | * since it is either found in namecache or obtained |
| 3137 | * from VOP_VPTOCNP(). We may test for VV_ROOT safely |
| 3138 | * without obtaining the vnode lock. |
| 3139 | */ |
| 3140 | if ((vp->v_vflag & VV_ROOT) != 0) { |
| 3141 | vn_lock(vp, LK_RETRY | LK_SHARED); |
| 3142 | |
| 3143 | /* |
| 3144 | * With the vnode locked, check for races with |
| 3145 | * unmount, forced or not. Note that we |
| 3146 | * already verified that vp is not equal to |
| 3147 | * the root vnode, which means that |
| 3148 | * mnt_vnodecovered can be NULL only for the |
| 3149 | * case of unmount. |
| 3150 | */ |
| 3151 | if (VN_IS_DOOMED(vp) || |
| 3152 | (vp1 = vp->v_mount->mnt_vnodecovered) == NULL || |
| 3153 | vp1->v_mountedhere != vp->v_mount) { |
| 3154 | vput(vp); |
| 3155 | error = ENOENT; |
| 3156 | SDT_PROBE3(vfs, namecache, fullpath, return, |
| 3157 | error, vp, NULL); |
| 3158 | break; |
| 3159 | } |
| 3160 | |
| 3161 | vref(vp1); |
no test coverage detected