[v3,05/11] Use xstat() with no synchronisation if available
diff mbox series

Message ID 20190528203122.11401-6-trond.myklebust@hammerspace.com
State New
Headers show
Series
  • Add the "[exports] rootdir" option to nfs.conf
Related show

Commit Message

Trond Myklebust May 28, 2019, 8:31 p.m. UTC
We normally expect the exported system to be stable, so don't
revalidate attributes.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
---
 configure.ac         |  2 +-
 support/misc/xstat.c | 72 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 73 insertions(+), 1 deletion(-)

Patch
diff mbox series

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);
 }