diff --git a/lib/libsys/stat.2 b/lib/libsys/stat.2 --- a/lib/libsys/stat.2 +++ b/lib/libsys/stat.2 @@ -119,6 +119,8 @@ is equal to .Dv AT_FDCWD , operate on the current working directory. +.It Dv AT_NO_AUTOMOUNT +Do not auto-mount the last component name of the path. .El .Pp If diff --git a/sys/fs/autofs/autofs_vnops.c b/sys/fs/autofs/autofs_vnops.c --- a/sys/fs/autofs/autofs_vnops.c +++ b/sys/fs/autofs/autofs_vnops.c @@ -89,7 +89,8 @@ * otherwise. */ if (autofs_mount_on_stat && autofs_cached(anp, NULL, 0) == false && - autofs_ignore_thread(curthread) == false) { + autofs_ignore_thread(curthread) == false && + (ap->a_flags & VN_GETATTR_NOAUTOMOUNT) == 0) { error = autofs_trigger_vn(vp, "", 0, &newvp); if (error != 0) return (error); @@ -247,7 +248,9 @@ } if (autofs_cached(anp, cnp->cn_nameptr, cnp->cn_namelen) == false && - autofs_ignore_thread(curthread) == false) { + autofs_ignore_thread(curthread) == false && + ((cnp->cn_flags & ISLASTCN) == 0 || + (cnp->cn_flags & NOAUTOMOUNT) != 0)) { error = autofs_trigger_vn(dvp, cnp->cn_nameptr, cnp->cn_namelen, &newvp); if (error != 0) 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 @@ -113,7 +113,7 @@ uint64_t res; MPASS((at_flags & (AT_SYMLINK_FOLLOW | AT_SYMLINK_NOFOLLOW)) != - (AT_SYMLINK_FOLLOW | AT_SYMLINK_NOFOLLOW)); + (AT_SYMLINK_FOLLOW | AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)); res = 0; at_flags &= mask; @@ -128,6 +128,8 @@ } if ((mask & AT_EMPTY_PATH) != 0 && (at_flags & AT_EMPTY_PATH) != 0) res |= EMPTYPATH; + if ((mask & AT_NO_AUTOMOUNT) != 0 && (at_flags & AT_NO_AUTOMOUNT) != 0) + res |= NOAUTOMOUNT; return (res); } @@ -2459,15 +2461,16 @@ enum uio_seg pathseg, struct stat *sbp) { struct nameidata nd; - int error; + int error, statflag; if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_RESOLVE_BENEATH | - AT_EMPTY_PATH)) != 0) + AT_EMPTY_PATH | AT_NO_AUTOMOUNT)) != 0) return (EINVAL); NDINIT_ATRIGHTS(&nd, LOOKUP, at2cnpflags(flag, AT_RESOLVE_BENEATH | - AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH) | LOCKSHARED | LOCKLEAF | - AUDITVNODE1, pathseg, path, fd, &cap_fstat_rights); + AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH | AT_NO_AUTOMOUNT) | + LOCKSHARED | LOCKLEAF | AUDITVNODE1, pathseg, path, fd, + &cap_fstat_rights); if ((error = namei(&nd)) != 0) { if (error == ENOTDIR && @@ -2475,7 +2478,11 @@ error = kern_fstat(td, fd, sbp); return (error); } - error = VOP_STAT(nd.ni_vp, sbp, 0, td->td_ucred, NOCRED); + + statflag = 0; + if ((flag & AT_NO_AUTOMOUNT) != 0) + statflag = VN_GETATTR_NOAUTOMOUNT; + error = VOP_STAT(nd.ni_vp, sbp, statflag, td->td_ucred, NOCRED); NDFREE_PNBUF(&nd); vput(nd.ni_vp); #ifdef __STAT_TIME_T_EXT diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h --- a/sys/sys/fcntl.h +++ b/sys/sys/fcntl.h @@ -229,6 +229,8 @@ #define AT_RESOLVE_BENEATH 0x2000 /* Do not allow name resolution to walk out of dirfd */ #define AT_EMPTY_PATH 0x4000 /* Operate on dirfd if path is empty */ +#define AT_NO_AUTOMOUNT 0x8000 /* No automount of last cn of + fstatat() */ #endif /* __BSD_VISIBLE */ /* diff --git a/sys/sys/namei.h b/sys/sys/namei.h --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -152,6 +152,7 @@ #define LOCKSHARED 0x0100 /* Shared lock leaf */ #define NOFOLLOW 0x0000 /* do not follow symbolic links (pseudo) */ #define RBENEATH 0x100000000ULL /* No escape, even tmp, from start dir */ +#define NOAUTOMOUNT 0x200000000ULL /* No automount on last cn */ #define MODMASK 0xf000001ffULL /* mask of operational modifiers */ /* diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -618,6 +618,7 @@ #define COPY_FILE_RANGE_TIMEO1SEC 0x01000000 /* Return after 1sec. */ /* VOP_STAT()/VOP_GETATTR() flags */ +#define VN_GETATTR_NOAUTOMOUNT 0x00000001 /* * Public vnode manipulation functions.