diff mbox series

[2/5] linux: Disable fstatat64 fallback if __ASSUME_STATX is defined

Message ID 20210319183121.2252064-3-adhemerval.zanella@linaro.org
State New
Headers show
Series More stat fixes | expand

Commit Message

Adhemerval Zanella March 19, 2021, 6:31 p.m. UTC
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.
---
 sysdeps/unix/sysv/linux/fstatat64.c | 57 +++++++++++++++++++++--------
 1 file changed, 41 insertions(+), 16 deletions(-)

Comments

Stefan Liebler March 26, 2021, 9:24 a.m. UTC | #1
On 19/03/2021 19:31, Adhemerval Zanella via Libc-alpha wrote:
> 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.
> ---
>  sysdeps/unix/sysv/linux/fstatat64.c | 57 +++++++++++++++++++++--------
>  1 file changed, 41 insertions(+), 16 deletions(-)
> 
> diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
> index 490226a8ec..c3a030af58 100644
> --- a/sysdeps/unix/sysv/linux/fstatat64.c
> +++ b/sysdeps/unix/sysv/linux/fstatat64.c
> @@ -31,6 +31,7 @@
>  #if __TIMESIZE == 64 \
>       && (__WORDSIZE == 32 \
>       && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
> +# define FSTATAT_USE_STATX 1
This will lead to a redefinition later in the file.


>  /* Sanity check to avoid newer 32-bit ABI to support non-LFS calls.  */
>  _Static_assert (sizeof (__off_t) == sizeof (__off64_t),
>                  "__blkcnt_t and __blkcnt64_t must match");
> @@ -40,27 +41,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 +113,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
FSTATAT_USE_STATX will be redefined as mentioned earlier
> +
> +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
> +
The former __fstatat64_time64 is splitted into fstatat64_time64_statx
and fstatat64_time64_stat. And if statx is always available, we can skip
the stat part.
OK
>    return INTERNAL_SYSCALL_ERROR_P (r)
>  	 ? INLINE_SYSCALL_ERROR_RETURN_VALUE (-r)
>  	 : 0;
>
Adhemerval Zanella March 26, 2021, 7:38 p.m. UTC | #2
On 26/03/2021 06:24, Stefan Liebler via Libc-alpha wrote:
> On 19/03/2021 19:31, Adhemerval Zanella via Libc-alpha wrote:
>> 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.
>> ---
>>  sysdeps/unix/sysv/linux/fstatat64.c | 57 +++++++++++++++++++++--------
>>  1 file changed, 41 insertions(+), 16 deletions(-)
>>
>> diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
>> index 490226a8ec..c3a030af58 100644
>> --- a/sysdeps/unix/sysv/linux/fstatat64.c
>> +++ b/sysdeps/unix/sysv/linux/fstatat64.c
>> @@ -31,6 +31,7 @@
>>  #if __TIMESIZE == 64 \
>>       && (__WORDSIZE == 32 \
>>       && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
>> +# define FSTATAT_USE_STATX 1
> This will lead to a redefinition later in the file.

This is incorrect and a left over from a rebase, I will remove it.
diff mbox series

Patch

diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
index 490226a8ec..c3a030af58 100644
--- a/sysdeps/unix/sysv/linux/fstatat64.c
+++ b/sysdeps/unix/sysv/linux/fstatat64.c
@@ -31,6 +31,7 @@ 
 #if __TIMESIZE == 64 \
      && (__WORDSIZE == 32 \
      && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
+# define FSTATAT_USE_STATX 1
 /* Sanity check to avoid newer 32-bit ABI to support non-LFS calls.  */
 _Static_assert (sizeof (__off_t) == sizeof (__off64_t),
                 "__blkcnt_t and __blkcnt64_t must match");
@@ -40,27 +41,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 +113,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;