about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2021-03-18 22:30:23 +0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2021-03-29 10:22:13 -0300
commit1fbffbda365ae8582981dfb284c83903931dd312 (patch)
tree400a63c17afac185870fcd2ba216f2b61f66bad2
parent4c4e90ccf8e44db24d288305aef2162c8e97fb51 (diff)
downloadglibc-1fbffbda365ae8582981dfb284c83903931dd312.tar.gz
glibc-1fbffbda365ae8582981dfb284c83903931dd312.tar.xz
glibc-1fbffbda365ae8582981dfb284c83903931dd312.zip
linux: Disable fstatat64 fallback if __ASSUME_STATX is defined
If the minimum kernel supports statx there is no need to call the
fallback stat legacy syscalls.

The statx is also called on compat xstat syscall, but different
than the fstatat it calls no fallback and it is assumed to be
always present.

Checked on powerpc-linux-gnu (with and without --enable-kernel=4.11)
and on powerpc64-linux-gnu.
-rw-r--r--sysdeps/unix/sysv/linux/fstatat64.c56
1 files changed, 40 insertions, 16 deletions
diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
index 490226a8ec..4d936ee0bb 100644
--- a/sysdeps/unix/sysv/linux/fstatat64.c
+++ b/sysdeps/unix/sysv/linux/fstatat64.c
@@ -40,27 +40,25 @@ _Static_assert (sizeof (__blkcnt_t) == sizeof (__blkcnt64_t),
                 "__blkcnt_t and __blkcnt64_t must match");
 #endif
 
-int
-__fstatat64_time64 (int fd, const char *file, struct __stat64_t64 *buf,
-		    int flag)
+static inline int
+fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
+			int flag)
 {
-  int r;
-
-#if (__WORDSIZE == 32 \
-     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
   /* 32-bit kABI with default 64-bit time_t, e.g. arc, riscv32.   Also
      64-bit time_t support is done through statx syscall.  */
   struct statx tmp;
-  r = INTERNAL_SYSCALL_CALL (statx, fd, file, AT_NO_AUTOMOUNT | flag,
-			     STATX_BASIC_STATS, &tmp);
+  int r = INTERNAL_SYSCALL_CALL (statx, fd, file, AT_NO_AUTOMOUNT | flag,
+				 STATX_BASIC_STATS, &tmp);
   if (r == 0)
-    {
-      __cp_stat64_t64_statx (buf, &tmp);
-      return 0;
-    }
-  if (-r != ENOSYS)
-    return INLINE_SYSCALL_ERROR_RETURN_VALUE (-r);
-#endif
+    __cp_stat64_t64_statx (buf, &tmp);
+  return r;
+}
+
+static inline int
+fstatat64_time64_stat (int fd, const char *file, struct __stat64_t64 *buf,
+		       int flag)
+{
+  int r;
 
 #if XSTAT_IS_XSTAT64
 # ifdef __NR_newfstatat
@@ -114,6 +112,32 @@ __fstatat64_time64 (int fd, const char *file, struct __stat64_t64 *buf,
 # endif
 #endif
 
+  return r;
+}
+
+#if (__WORDSIZE == 32 \
+     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
+# define FSTATAT_USE_STATX 1
+#else
+# define FSTATAT_USE_STATX 0
+#endif
+
+int
+__fstatat64_time64 (int fd, const char *file, struct __stat64_t64 *buf,
+		    int flag)
+{
+  int r;
+
+#if FSTATAT_USE_STATX
+  r = fstatat64_time64_statx (fd, file, buf, flag);
+# ifndef __ASSUME_STATX
+  if (r == -ENOSYS)
+    r = fstatat64_time64_stat (fd, file, buf, flag);
+# endif
+#else
+  r = fstatat64_time64_stat (fd, file, buf, flag);
+#endif
+
   return INTERNAL_SYSCALL_ERROR_P (r)
 	 ? INLINE_SYSCALL_ERROR_RETURN_VALUE (-r)
 	 : 0;