fstat performance enhancement (RHEL-2338)

Resolves: RHEL-2338
This commit is contained in:
Florian Weimer 2023-11-24 13:29:19 +01:00
parent 26fb3f4504
commit bca78af34a
5 changed files with 278 additions and 1 deletions

47
glibc-RHEL-2338-1.patch Normal file
View File

@ -0,0 +1,47 @@
commit c3b023a7822185c9176cfb96eeca4ada3d662c4b
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Wed Nov 24 12:57:57 2021 -0300
linux: Only build fstatat fallback if required
For 32-bit architecture with __ASSUME_STATX there is no need to
build fstatat64_time64_stat.
Checked on i686-linux-gnu.
diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
index f968e4ef0594852e..50ae5ad74832efe1 100644
--- a/sysdeps/unix/sysv/linux/fstatat64.c
+++ b/sysdeps/unix/sysv/linux/fstatat64.c
@@ -74,6 +74,17 @@ fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
return r;
}
+#if (__WORDSIZE == 32 \
+ && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
+ || defined STAT_HAS_TIME32
+# define FSTATAT_USE_STATX 1
+#else
+# define FSTATAT_USE_STATX 0
+#endif
+
+/* Only statx supports 64-bit timestamps for 32-bit architectures with
+ __ASSUME_STATX, so there is no point in building the fallback. */
+#if !FSTATAT_USE_STATX || (FSTATAT_USE_STATX && !defined __ASSUME_STATX)
static inline int
fstatat64_time64_stat (int fd, const char *file, struct __stat64_t64 *buf,
int flag)
@@ -134,13 +145,6 @@ fstatat64_time64_stat (int fd, const char *file, struct __stat64_t64 *buf,
return r;
}
-
-#if (__WORDSIZE == 32 \
- && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
- || defined STAT_HAS_TIME32
-# define FSTATAT_USE_STATX 1
-#else
-# define FSTATAT_USE_STATX 0
#endif
int

36
glibc-RHEL-2338-2.patch Normal file
View File

@ -0,0 +1,36 @@
commit c7f05bd5342517f3f751e6ea8dec1916b80bee8a
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Wed Mar 9 18:35:39 2022 -0300
Fix ununsed fstatat64_time64_statx
It is only called for legacy ABIs.
diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
index 50ae5ad74832efe1..45221bbdf901fa47 100644
--- a/sysdeps/unix/sysv/linux/fstatat64.c
+++ b/sysdeps/unix/sysv/linux/fstatat64.c
@@ -40,6 +40,11 @@ _Static_assert (sizeof (__blkcnt_t) == sizeof (__blkcnt64_t),
"__blkcnt_t and __blkcnt64_t must match");
#endif
+#if (__WORDSIZE == 32 \
+ && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
+ || defined STAT_HAS_TIME32
+# define FSTATAT_USE_STATX 1
+
static inline int
fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
int flag)
@@ -73,11 +78,6 @@ fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
return r;
}
-
-#if (__WORDSIZE == 32 \
- && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
- || defined STAT_HAS_TIME32
-# define FSTATAT_USE_STATX 1
#else
# define FSTATAT_USE_STATX 0
#endif

30
glibc-RHEL-2338-3.patch Normal file
View File

@ -0,0 +1,30 @@
commit e6547d635b991651600fab31f788ed5facd77610
Author: WANG Xuerui <git@xen0n.name>
Date: Wed Jun 1 10:12:28 2022 +0800
linux: use statx for fstat if neither newfstatat nor fstatat64 is present
LoongArch is going to be the first architecture supported by Linux that
has neither fstat* nor newfstatat [1], instead exclusively relying on
statx. So in fstatat64's implementation, we need to also enable statx
usage if neither fstatat64 nor newfstatat is present, to prepare for
this new case of kernel ABI.
[1]: https://lore.kernel.org/all/20220518092619.1269111-1-chenhuacai@loongson.cn/
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
index 45221bbdf901fa47..ded431257bf3450f 100644
--- a/sysdeps/unix/sysv/linux/fstatat64.c
+++ b/sysdeps/unix/sysv/linux/fstatat64.c
@@ -42,7 +42,8 @@ _Static_assert (sizeof (__blkcnt_t) == sizeof (__blkcnt64_t),
#if (__WORDSIZE == 32 \
&& (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
- || defined STAT_HAS_TIME32
+ || defined STAT_HAS_TIME32 \
+ || (!defined __NR_newfstatat && !defined __NR_fstatat64)
# define FSTATAT_USE_STATX 1
static inline int

157
glibc-RHEL-2338-4.patch Normal file
View File

@ -0,0 +1,157 @@
commit 551101e8240b7514fc646d1722f8b79c90362b8f
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Mon Sep 11 10:25:48 2023 -0300
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.
diff --git a/sysdeps/unix/sysv/linux/fstat64.c b/sysdeps/unix/sysv/linux/fstat64.c
index 46de80b663b9c1c4..fe4f57065f8713d2 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)
diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
index ded431257bf3450f..8e9db7b11f0e1cf3 100644
--- a/sysdeps/unix/sysv/linux/fstatat64.c
+++ b/sysdeps/unix/sysv/linux/fstatat64.c
@@ -21,12 +21,10 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
-#include <kernel_stat.h>
#include <sysdep.h>
#include <time.h>
-#include <kstat_cp.h>
-#include <stat_t64_cp.h>
#include <sys/sysmacros.h>
+#include <internal-stat.h>
#if __TIMESIZE == 64 \
&& (__WORDSIZE == 32 \
@@ -40,11 +38,7 @@ _Static_assert (sizeof (__blkcnt_t) == sizeof (__blkcnt64_t),
"__blkcnt_t and __blkcnt64_t must match");
#endif
-#if (__WORDSIZE == 32 \
- && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
- || defined STAT_HAS_TIME32 \
- || (!defined __NR_newfstatat && !defined __NR_fstatat64)
-# define FSTATAT_USE_STATX 1
+#if FSTATAT_USE_STATX
static inline int
fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
@@ -79,8 +73,6 @@ fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
return r;
}
-#else
-# define FSTATAT_USE_STATX 0
#endif
/* Only statx supports 64-bit timestamps for 32-bit architectures with
diff --git a/sysdeps/unix/sysv/linux/internal-stat.h b/sysdeps/unix/sysv/linux/internal-stat.h
new file mode 100644
index 0000000000000000..e3b05698532fb185
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/internal-stat.h
@@ -0,0 +1,31 @@
+/* Internal stat definitions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <stat_t64_cp.h>
+#include <kernel_stat.h>
+#include <kstat_cp.h>
+
+#if (__WORDSIZE == 32 \
+ && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
+ || defined STAT_HAS_TIME32 \
+ || (!defined __NR_newfstatat && !defined __NR_fstatat64)
+# define FSTATAT_USE_STATX 1
+#else
+# define FSTATAT_USE_STATX 0
+#endif

View File

@ -155,7 +155,7 @@ end \
Summary: The GNU libc libraries
Name: glibc
Version: %{glibcversion}
Release: 90%{?dist}
Release: 91%{?dist}
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
# libraries.
@ -777,6 +777,10 @@ Patch540: glibc-RHEL-16275.patch
Patch541: glibc-RHEL-2491.patch
Patch542: glibc-RHEL-14383-1.patch
Patch543: glibc-RHEL-14383-2.patch
Patch544: glibc-RHEL-2338-1.patch
Patch545: glibc-RHEL-2338-2.patch
Patch546: glibc-RHEL-2338-3.patch
Patch547: glibc-RHEL-2338-4.patch
##############################################################################
# Continued list of core "glibc" package information:
@ -2935,6 +2939,9 @@ update_gconv_modules_cache ()
%endif
%changelog
* Fri Nov 24 2023 Florian Weimer <fweimer@redhat.com> - 2.34-91
- fstat performance enhancement (RHEL-2338)
* Tue Nov 21 2023 Florian Weimer <fweimer@redhat.com> - 2.34-90
- ldconfig should skip temporary files created by RPM (RHEL-14383)