We normally expect the exported system to be stable, so don't revalidate attributes. Signed-off-by: Trond Myklebust <trond.myklebust@xxxxxxxxxxxxxxx> --- configure.ac | 2 +- support/misc/xstat.c | 72 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index e870862a8abb..50002b4a5677 100644 --- a/configure.ac +++ b/configure.ac @@ -321,7 +321,7 @@ AC_CHECK_FUNC([getservbyname], , AC_CHECK_LIB([crypt], [crypt], [LIBCRYPT="-lcrypt"]) AC_CHECK_HEADERS([sched.h], [], []) -AC_CHECK_FUNCS([unshare fstatat], [] , []) +AC_CHECK_FUNCS([unshare fstatat statx], [] , []) AC_LIBPTHREAD([]) if test "$enable_nfsv4" = yes; then diff --git a/support/misc/xstat.c b/support/misc/xstat.c index d092f73dfd65..fa047880cfd0 100644 --- a/support/misc/xstat.c +++ b/support/misc/xstat.c @@ -1,21 +1,93 @@ +#include <errno.h> #include <sys/types.h> #include <fcntl.h> #include <sys/stat.h> +#include <sys/sysmacros.h> #include <unistd.h> #include "config.h" #include "xstat.h" #ifdef HAVE_FSTATAT +#ifdef HAVE_STATX + +static void +statx_copy(struct stat *stbuf, const struct statx *stxbuf) +{ + stbuf->st_dev = makedev(stxbuf->stx_dev_major, stxbuf->stx_dev_minor); + stbuf->st_ino = stxbuf->stx_ino; + stbuf->st_mode = stxbuf->stx_mode; + stbuf->st_nlink = stxbuf->stx_nlink; + stbuf->st_uid = stxbuf->stx_uid; + stbuf->st_gid = stxbuf->stx_gid; + stbuf->st_rdev = makedev(stxbuf->stx_rdev_major, stxbuf->stx_rdev_minor); + stbuf->st_size = stxbuf->stx_size; + stbuf->st_blksize = stxbuf->stx_blksize; + stbuf->st_blocks = stxbuf->stx_blocks; + stbuf->st_atim.tv_sec = stxbuf->stx_atime.tv_sec; + stbuf->st_atim.tv_nsec = stxbuf->stx_atime.tv_nsec; + stbuf->st_mtim.tv_sec = stxbuf->stx_mtime.tv_sec; + stbuf->st_mtim.tv_nsec = stxbuf->stx_mtime.tv_nsec; + stbuf->st_ctim.tv_sec = stxbuf->stx_ctime.tv_sec; + stbuf->st_ctim.tv_nsec = stxbuf->stx_ctime.tv_nsec; +} + +static int +statx_do_stat(int fd, const char *pathname, struct stat *statbuf, int flags) +{ + static int statx_supported = 1; + struct statx stxbuf; + int ret; + + if (statx_supported) { + ret = statx(fd, pathname, flags, + STATX_BASIC_STATS, + &stxbuf); + if (ret == 0) { + statx_copy(statbuf, &stxbuf); + return 0; + } + if (errno == ENOSYS) + statx_supported = 0; + } else + errno = ENOSYS; + return -1; +} + +static int +statx_stat_nosync(int fd, const char *pathname, struct stat *statbuf, int flags) +{ + return statx_do_stat(fd, pathname, statbuf, flags | AT_STATX_DONT_SYNC); +} + +#else + +static int +statx_stat_nosync(int fd, const char *pathname, struct stat *statbuf, int flags) +{ + errno = ENOSYS; + return -1; +} + +#endif /* HAVE_STATX */ int xlstat(const char *pathname, struct stat *statbuf) { + if (statx_stat_nosync(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT| + AT_SYMLINK_NOFOLLOW) == 0) + return 0; + else if (errno != ENOSYS) + return -1; return fstatat(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW); } int xstat(const char *pathname, struct stat *statbuf) { + if (statx_stat_nosync(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT) == 0) + return 0; + else if (errno != ENOSYS) + return -1; return fstatat(AT_FDCWD, pathname, statbuf, AT_NO_AUTOMOUNT); } -- 2.21.0