diff options
author | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2023-09-11 10:25:48 -0300 |
---|---|---|
committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2023-09-27 09:30:24 -0300 |
commit | 551101e8240b7514fc646d1722f8b79c90362b8f (patch) | |
tree | 350c748f6d9bf80e3cacf581fe3a7fed7d94fd9f /sysdeps/unix/sysv/linux/fstat64.c | |
parent | 64b1a44183a3094672ed304532bedb9acc707554 (diff) | |
download | glibc-551101e8240b7514fc646d1722f8b79c90362b8f.tar.gz glibc-551101e8240b7514fc646d1722f8b79c90362b8f.tar.xz glibc-551101e8240b7514fc646d1722f8b79c90362b8f.zip |
io: Do not implement fstat with fstatat
AT_EMPTY_PATH is a requirement to implement fstat over fstatat, however it does not prevent the kernel to read the path argument. It is not an issue, but on x86-64 with SMAP-capable CPUs the kernel is forced to perform expensive user memory access. After that regular lookup is performed which adds even more overhead. Instead, issue the fstat syscall directly on LFS fstat implementation (32 bit architectures will still continue to use statx, which is required to have 64 bit time_t support). it should be even a small performance gain on non x86_64, since there is no need to handle the path argument. Checked on x86_64-linux-gnu.
Diffstat (limited to 'sysdeps/unix/sysv/linux/fstat64.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/fstat64.c | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/sysdeps/unix/sysv/linux/fstat64.c b/sysdeps/unix/sysv/linux/fstat64.c index 124384e57f..a291f0825b 100644 --- a/sysdeps/unix/sysv/linux/fstat64.c +++ b/sysdeps/unix/sysv/linux/fstat64.c @@ -19,20 +19,53 @@ #define __fstat __redirect___fstat #define fstat __redirect_fstat #include <sys/stat.h> +#undef __fstat +#undef fstat #include <fcntl.h> -#include <kernel_stat.h> -#include <stat_t64_cp.h> +#include <internal-stat.h> #include <errno.h> int __fstat64_time64 (int fd, struct __stat64_t64 *buf) { +#if !FSTATAT_USE_STATX +# if XSTAT_IS_XSTAT64 +# ifdef __NR_fstat + /* 64-bit kABI, e.g. aarch64, ia64, powerpc64*, s390x, riscv64, and + x86_64. */ + return INLINE_SYSCALL_CALL (fstat, fd, buf); +# elif defined __NR_fstat64 +# if STAT64_IS_KERNEL_STAT64 + /* 64-bit kABI outlier, e.g. alpha */ + return INLINE_SYSCALL_CALL (fstat64, fd, buf); +# else + /* 64-bit kABI outlier, e.g. sparc64. */ + struct kernel_stat64 kst64; + int r = INLINE_SYSCALL_CALL (fstat64, fd, &kst64); + if (r == 0) + __cp_stat64_kstat64 (buf, &kst64); + return r; +# endif /* STAT64_IS_KERNEL_STAT64 */ +# endif +# else /* XSTAT_IS_XSTAT64 */ + /* 64-bit kabi outlier, e.g. mips64 and mips64-n32. */ + struct kernel_stat kst; + int r = INLINE_SYSCALL_CALL (fstat, fd, &kst); + if (r == 0) + __cp_kstat_stat64_t64 (&kst, buf); + return r; +# endif +#else /* !FSTATAT_USE_STATX */ + /* All kABIs with non-LFS support and with old 32-bit time_t support + e.g. arm, csky, i386, hppa, m68k, microblaze, nios2, sh, powerpc32, + and sparc32. */ if (fd < 0) { __set_errno (EBADF); return -1; } return __fstatat64_time64 (fd, "", buf, AT_EMPTY_PATH); +#endif } #if __TIMESIZE != 64 hidden_def (__fstat64_time64) |