diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -895,8 +895,7 @@ int sys_fchdir(struct thread *td, struct fchdir_args *uap) { - struct vnode *vp, *tdp; - struct mount *mp; + struct vnode *vp; struct file *fp; int error; @@ -908,23 +907,17 @@ vp = fp->f_vnode; vrefact(vp); fdrop(fp, td); + vn_lock(vp, LK_SHARED | LK_RETRY); AUDIT_ARG_VNODE1(vp); error = change_dir(vp, td); - while (!error && (mp = vp->v_mountedhere) != NULL) { - if (vfs_busy(mp, 0)) - continue; - error = VFS_ROOT(mp, LK_SHARED, &tdp); - vfs_unbusy(mp); - if (error != 0) - break; - vput(vp); - vp = tdp; - } - if (error != 0) { + if (__predict_false(error != 0)) { vput(vp); return (error); } + error = vn_cross_mounts(vp, LK_SHARED, &vp); + if (__predict_false(error != 0)) + return (error); VOP_UNLOCK(vp); pwd_chdir(td, vp); return (0);