]>
Commit | Line | Data |
---|---|---|
067c64fe AM |
1 | From: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
2 | Subject: [PATCH v2] io: Do not implement fstat with fstatat | |
3 | Date: Mon, 11 Sep 2023 10:25:48 -0300 | |
4 | ||
5 | AT_EMPTY_PATH is a requirement to implement fstat over fstatat, | |
6 | however it does not prevent the kernel to read the path argument. | |
7 | It is not an issue, but on x86-64 with SMAP-capable CPUs the kernel is | |
8 | forced to perform expensive user memory access. After that regular | |
9 | lookup is performed which adds even more overhead. | |
10 | ||
11 | Instead, issue the fstat syscall directly on LFS fstat implementation | |
12 | (32 bit architectures will still continue to use statx, which is | |
13 | required to have 64 bit time_t support). it should be even a | |
14 | small performance gain on non x86_64, since there is no need | |
15 | to handle the path argument. | |
16 | ||
17 | Checked on x86_64-linux-gnu. | |
18 | --- | |
19 | sysdeps/unix/sysv/linux/fstat64.c | 37 +++++++++++++++++++++++-- | |
20 | sysdeps/unix/sysv/linux/fstatat64.c | 12 ++------ | |
21 | sysdeps/unix/sysv/linux/internal-stat.h | 31 +++++++++++++++++++++ | |
22 | 3 files changed, 68 insertions(+), 12 deletions(-) | |
23 | create mode 100644 sysdeps/unix/sysv/linux/internal-stat.h | |
24 | ||
25 | diff --git a/sysdeps/unix/sysv/linux/fstat64.c b/sysdeps/unix/sysv/linux/fstat64.c | |
26 | index 124384e57f..a291f0825b 100644 | |
27 | --- a/sysdeps/unix/sysv/linux/fstat64.c | |
28 | +++ b/sysdeps/unix/sysv/linux/fstat64.c | |
29 | @@ -19,20 +19,53 @@ | |
30 | #define __fstat __redirect___fstat | |
31 | #define fstat __redirect_fstat | |
32 | #include <sys/stat.h> | |
33 | +#undef __fstat | |
34 | +#undef fstat | |
35 | #include <fcntl.h> | |
36 | -#include <kernel_stat.h> | |
37 | -#include <stat_t64_cp.h> | |
38 | +#include <internal-stat.h> | |
39 | #include <errno.h> | |
40 | ||
41 | int | |
42 | __fstat64_time64 (int fd, struct __stat64_t64 *buf) | |
43 | { | |
44 | +#if !FSTATAT_USE_STATX | |
45 | +# if XSTAT_IS_XSTAT64 | |
46 | +# ifdef __NR_fstat | |
47 | + /* 64-bit kABI, e.g. aarch64, ia64, powerpc64*, s390x, riscv64, and | |
48 | + x86_64. */ | |
49 | + return INLINE_SYSCALL_CALL (fstat, fd, buf); | |
50 | +# elif defined __NR_fstat64 | |
51 | +# if STAT64_IS_KERNEL_STAT64 | |
52 | + /* 64-bit kABI outlier, e.g. alpha */ | |
53 | + return INLINE_SYSCALL_CALL (fstat64, fd, buf); | |
54 | +# else | |
55 | + /* 64-bit kABI outlier, e.g. sparc64. */ | |
56 | + struct kernel_stat64 kst64; | |
57 | + int r = INLINE_SYSCALL_CALL (fstat64, fd, &kst64); | |
58 | + if (r == 0) | |
59 | + __cp_stat64_kstat64 (buf, &kst64); | |
60 | + return r; | |
61 | +# endif /* STAT64_IS_KERNEL_STAT64 */ | |
62 | +# endif | |
63 | +# else /* XSTAT_IS_XSTAT64 */ | |
64 | + /* 64-bit kabi outlier, e.g. mips64 and mips64-n32. */ | |
65 | + struct kernel_stat kst; | |
66 | + int r = INLINE_SYSCALL_CALL (fstat, fd, &kst); | |
67 | + if (r == 0) | |
68 | + __cp_kstat_stat64_t64 (&kst, buf); | |
69 | + return r; | |
70 | +# endif | |
71 | +#else /* !FSTATAT_USE_STATX */ | |
72 | + /* All kABIs with non-LFS support and with old 32-bit time_t support | |
73 | + e.g. arm, csky, i386, hppa, m68k, microblaze, nios2, sh, powerpc32, | |
74 | + and sparc32. */ | |
75 | if (fd < 0) | |
76 | { | |
77 | __set_errno (EBADF); | |
78 | return -1; | |
79 | } | |
80 | return __fstatat64_time64 (fd, "", buf, AT_EMPTY_PATH); | |
81 | +#endif | |
82 | } | |
83 | #if __TIMESIZE != 64 | |
84 | hidden_def (__fstat64_time64) | |
85 | diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c | |
86 | index 3509d3ca6d..127c6ff601 100644 | |
87 | --- a/sysdeps/unix/sysv/linux/fstatat64.c | |
88 | +++ b/sysdeps/unix/sysv/linux/fstatat64.c | |
89 | @@ -21,12 +21,10 @@ | |
90 | #include <sys/stat.h> | |
91 | #include <fcntl.h> | |
92 | #include <string.h> | |
93 | -#include <kernel_stat.h> | |
94 | #include <sysdep.h> | |
95 | #include <time.h> | |
96 | -#include <kstat_cp.h> | |
97 | -#include <stat_t64_cp.h> | |
98 | #include <sys/sysmacros.h> | |
99 | +#include <internal-stat.h> | |
100 | ||
101 | #if __TIMESIZE == 64 \ | |
102 | && (__WORDSIZE == 32 \ | |
103 | @@ -40,11 +38,7 @@ _Static_assert (sizeof (__blkcnt_t) == sizeof (__blkcnt64_t), | |
104 | "__blkcnt_t and __blkcnt64_t must match"); | |
105 | #endif | |
106 | ||
107 | -#if (__WORDSIZE == 32 \ | |
108 | - && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \ | |
109 | - || defined STAT_HAS_TIME32 \ | |
110 | - || (!defined __NR_newfstatat && !defined __NR_fstatat64) | |
111 | -# define FSTATAT_USE_STATX 1 | |
112 | +#if FSTATAT_USE_STATX | |
113 | ||
114 | static inline int | |
115 | fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf, | |
116 | @@ -79,8 +73,6 @@ fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf, | |
117 | ||
118 | return r; | |
119 | } | |
120 | -#else | |
121 | -# define FSTATAT_USE_STATX 0 | |
122 | #endif | |
123 | ||
124 | /* Only statx supports 64-bit timestamps for 32-bit architectures with | |
125 | diff --git a/sysdeps/unix/sysv/linux/internal-stat.h b/sysdeps/unix/sysv/linux/internal-stat.h | |
126 | new file mode 100644 | |
127 | index 0000000000..e3b0569853 | |
128 | --- /dev/null | |
129 | +++ b/sysdeps/unix/sysv/linux/internal-stat.h | |
130 | @@ -0,0 +1,31 @@ | |
131 | +/* Internal stat definitions. | |
132 | + Copyright (C) 2023 Free Software Foundation, Inc. | |
133 | + This file is part of the GNU C Library. | |
134 | + | |
135 | + The GNU C Library is free software; you can redistribute it and/or | |
136 | + modify it under the terms of the GNU Lesser General Public | |
137 | + License as published by the Free Software Foundation; either | |
138 | + version 2.1 of the License, or (at your option) any later version. | |
139 | + | |
140 | + The GNU C Library is distributed in the hope that it will be useful, | |
141 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
142 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
143 | + Lesser General Public License for more details. | |
144 | + | |
145 | + You should have received a copy of the GNU Lesser General Public | |
146 | + License along with the GNU C Library; if not, see | |
147 | + <https://www.gnu.org/licenses/>. */ | |
148 | + | |
149 | +#include <sysdep.h> | |
150 | +#include <stat_t64_cp.h> | |
151 | +#include <kernel_stat.h> | |
152 | +#include <kstat_cp.h> | |
153 | + | |
154 | +#if (__WORDSIZE == 32 \ | |
155 | + && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \ | |
156 | + || defined STAT_HAS_TIME32 \ | |
157 | + || (!defined __NR_newfstatat && !defined __NR_fstatat64) | |
158 | +# define FSTATAT_USE_STATX 1 | |
159 | +#else | |
160 | +# define FSTATAT_USE_STATX 0 | |
161 | +#endif |