[15/16] linux: Add {f}stat{at} y2038 support

Message ID 20200723194641.1949404-16-adhemerval.zanella@linaro.org
State Committed
Headers
Series Add y2038 support for stat functions |

Commit Message

Adhemerval Zanella July 23, 2020, 7:46 p.m. UTC
  A new struct __stat{64}_t64 type is added with the required
__timespec64 time definition.  Both non-LFS and LFS support were
done with an extra __NR_statx call plus a conversion to the new
__stat{64}_t64 type.  The statx call is done only for architectures
with support for 32-bit time_t ABI.

Internally some extra routines to copy from/to struct stat{64}
to struct __stat{64} used on multiple implementations (stat, fstat,
lstat, and fstatat) are added on a extra file (stat_t64_cp.c).  Aslo
some extra routines to copy from statx to __stat{64} is added on
statx_cp.c.

Checked with a build for all affected ABIs. I also checked on x86_64,
i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and s390x.
---
 include/sys/stat.h                            |  32 +++++
 sysdeps/generic/struct_stat_time64.h          |   7 +
 sysdeps/unix/sysv/linux/Makefile              |   2 +-
 sysdeps/unix/sysv/linux/fstat.c               |  13 +-
 sysdeps/unix/sysv/linux/fstat64.c             |  20 ++-
 sysdeps/unix/sysv/linux/fstatat.c             |  64 +++++----
 sysdeps/unix/sysv/linux/fstatat64.c           |  88 ++++++++++---
 sysdeps/unix/sysv/linux/lstat.c               |  13 +-
 sysdeps/unix/sysv/linux/lstat64.c             |  19 ++-
 .../unix/sysv/linux/mips/mips64/kstat_cp.h    |  23 +---
 .../unix/sysv/linux/mips/mips64/statx_cp.c    |   3 -
 sysdeps/unix/sysv/linux/stat.c                |  13 +-
 sysdeps/unix/sysv/linux/stat64.c              |  20 ++-
 sysdeps/unix/sysv/linux/stat_t64_cp.c         |  92 +++++++++++++
 sysdeps/unix/sysv/linux/stat_t64_cp.h         |  28 ++++
 sysdeps/unix/sysv/linux/statx_cp.c            |  54 ++++++++
 sysdeps/unix/sysv/linux/statx_cp.h            |   6 +
 sysdeps/unix/sysv/linux/struct_stat_time64.h  | 122 ++++++++++++++++++
 18 files changed, 539 insertions(+), 80 deletions(-)
 create mode 100644 sysdeps/generic/struct_stat_time64.h
 delete mode 100644 sysdeps/unix/sysv/linux/mips/mips64/statx_cp.c
 create mode 100644 sysdeps/unix/sysv/linux/stat_t64_cp.c
 create mode 100644 sysdeps/unix/sysv/linux/stat_t64_cp.h
 create mode 100644 sysdeps/unix/sysv/linux/struct_stat_time64.h
  

Comments

Joseph Myers July 23, 2020, 8:55 p.m. UTC | #1
On Thu, 23 Jul 2020, Adhemerval Zanella via Libc-alpha wrote:

> A new struct __stat{64}_t64 type is added with the required
> __timespec64 time definition.  Both non-LFS and LFS support were
> done with an extra __NR_statx call plus a conversion to the new
> __stat{64}_t64 type.  The statx call is done only for architectures
> with support for 32-bit time_t ABI.

The combination of 64-bit times with 32-bit offsets is not supposed to be 
supported (no existing glibc configuration supports such a combination); 
_TIME_BITS=64 without _FILE_OFFSET_BITS=64 should be an error.  Thus, the 
__stat_t64 type and functions shouldn't be present.
  
Adhemerval Zanella July 23, 2020, 9 p.m. UTC | #2
On 23/07/2020 17:55, Joseph Myers wrote:
> On Thu, 23 Jul 2020, Adhemerval Zanella via Libc-alpha wrote:
> 
>> A new struct __stat{64}_t64 type is added with the required
>> __timespec64 time definition.  Both non-LFS and LFS support were
>> done with an extra __NR_statx call plus a conversion to the new
>> __stat{64}_t64 type.  The statx call is done only for architectures
>> with support for 32-bit time_t ABI.
> 
> The combination of 64-bit times with 32-bit offsets is not supposed to be 
> supported (no existing glibc configuration supports such a combination); 
> _TIME_BITS=64 without _FILE_OFFSET_BITS=64 should be an error.  Thus, the 
> __stat_t64 type and functions shouldn't be present.
> 

Ok, I was not sure if the plan was to enforce it, but I agree that it
does make sense.  And this simplifies the require work as well.
  
Lukasz Majewski July 24, 2020, 10:53 a.m. UTC | #3
Hi Adhemerval,

> A new struct __stat{64}_t64 type is added with the required
> __timespec64 time definition.  Both non-LFS and LFS support were
> done with an extra __NR_statx call plus a conversion to the new
> __stat{64}_t64 type.  The statx call is done only for architectures
> with support for 32-bit time_t ABI.
> 
> Internally some extra routines to copy from/to struct stat{64}
> to struct __stat{64} used on multiple implementations (stat, fstat,
> lstat, and fstatat) are added on a extra file (stat_t64_cp.c).  Aslo
> some extra routines to copy from statx to __stat{64} is added on
> statx_cp.c.
> 
> Checked with a build for all affected ABIs. I also checked on x86_64,
> i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and s390x.

This patch set is a huge step forward for the *stat* conversion to
support 64 bit time.

In fact we will only need redirections when -D__USE_TIME_BITS64 support
is added.

> ---
>  include/sys/stat.h                            |  32 +++++
>  sysdeps/generic/struct_stat_time64.h          |   7 +
>  sysdeps/unix/sysv/linux/Makefile              |   2 +-
>  sysdeps/unix/sysv/linux/fstat.c               |  13 +-
>  sysdeps/unix/sysv/linux/fstat64.c             |  20 ++-
>  sysdeps/unix/sysv/linux/fstatat.c             |  64 +++++----
>  sysdeps/unix/sysv/linux/fstatat64.c           |  88 ++++++++++---
>  sysdeps/unix/sysv/linux/lstat.c               |  13 +-
>  sysdeps/unix/sysv/linux/lstat64.c             |  19 ++-
>  .../unix/sysv/linux/mips/mips64/kstat_cp.h    |  23 +---
>  .../unix/sysv/linux/mips/mips64/statx_cp.c    |   3 -
>  sysdeps/unix/sysv/linux/stat.c                |  13 +-
>  sysdeps/unix/sysv/linux/stat64.c              |  20 ++-
>  sysdeps/unix/sysv/linux/stat_t64_cp.c         |  92 +++++++++++++
>  sysdeps/unix/sysv/linux/stat_t64_cp.h         |  28 ++++
>  sysdeps/unix/sysv/linux/statx_cp.c            |  54 ++++++++
>  sysdeps/unix/sysv/linux/statx_cp.h            |   6 +
>  sysdeps/unix/sysv/linux/struct_stat_time64.h  | 122
> ++++++++++++++++++ 18 files changed, 539 insertions(+), 80
> deletions(-) create mode 100644 sysdeps/generic/struct_stat_time64.h
>  delete mode 100644 sysdeps/unix/sysv/linux/mips/mips64/statx_cp.c
>  create mode 100644 sysdeps/unix/sysv/linux/stat_t64_cp.c
>  create mode 100644 sysdeps/unix/sysv/linux/stat_t64_cp.h
>  create mode 100644 sysdeps/unix/sysv/linux/struct_stat_time64.h
> 
> diff --git a/include/sys/stat.h b/include/sys/stat.h
> index 199173b007..87d4a5ec4f 100644
> --- a/include/sys/stat.h
> +++ b/include/sys/stat.h
> @@ -3,6 +3,8 @@
>  
>  #ifndef _ISOMAC
>  # include <xstatver.h>
> +# include <struct___timespec64.h>
> +# include <struct_stat_time64.h>
>  # include <stdbool.h>
>  
>  static inline bool
> @@ -44,6 +46,36 @@ hidden_proto (__lstat64)
>  hidden_proto (__fstatat64)
>  # endif
>  
> +# if __TIMESIZE == 64
> +#  define __stat_time64  __stat
> +#  define __stat64_time64  __stat64
> +#  define __fstat_time64  __fstat
> +#  define __fstat64_time64  __fstat64
> +#  define __lstat_time64  __lstat
> +#  define __lstat64_time64  __lstat64
> +#  define __fstatat_time64  __fstatat
> +#  define __fstatat64_time64 __fstatat64
> +# else
> +extern int __stat_time64 (const char *file, struct __stat_t64 *buf);
> +libc_hidden_proto (__stat_time64);
> +extern int __stat64_time64 (const char *file, struct __stat64_t64
> *buf); +hidden_proto (__stat64_time64);
> +extern int __lstat_time64 (const char *file, struct __stat_t64 *buf);
> +libc_hidden_proto (__lstat_time64);
> +extern int __lstat64_time64 (const char *file, struct __stat64_t64
> *buf); +hidden_proto (__lstat64_time64);
> +extern int __fstat_time64 (int fd, struct __stat_t64 *buf);
> +libc_hidden_proto (__fstat_time64);
> +extern int __fstat64_time64 (int fd, struct __stat64_t64 *buf);
> +hidden_proto (__fstat64_time64);
> +extern int __fstatat_time64 (int dirfd, const char *pathname,
> +			     struct __stat_t64 *buf, int flags);
> +libc_hidden_proto (__fstatat_time64);
> +extern int __fstatat64_time64 (int dirfd, const char *pathname,
> +			       struct __stat64_t64 *buf, int flags);
> +hidden_proto (__fstatat64_time64);
> +# endif
> +
>  extern int __chmod (const char *__file, __mode_t __mode);
>  libc_hidden_proto (__chmod)
>  extern int __fchmod (int __fd, __mode_t __mode);
> diff --git a/sysdeps/generic/struct_stat_time64.h
> b/sysdeps/generic/struct_stat_time64.h new file mode 100644
> index 0000000000..24bb9f75cb
> --- /dev/null
> +++ b/sysdeps/generic/struct_stat_time64.h
> @@ -0,0 +1,7 @@
> +#ifndef _BITS_STRUCT_STAT_TIME64_H
> +#define _BITS_STRUCT_STAT_TIME64_H 1
> +
> +#define __stat_t64   stat
> +#define __stat64_t64 stat64
> +
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/Makefile
> b/sysdeps/unix/sysv/linux/Makefile index f189f65daf..95a51ee4f2 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -273,7 +273,7 @@ sysdep_routines += xstatconv internal_statvfs
> internal_statvfs64 \ open_nocancel open64_nocancel \
>  		   openat_nocancel openat64_nocancel \
>  		   read_nocancel pread64_nocancel \
> -		   write_nocancel statx_cp
> +		   write_nocancel statx_cp stat_t64_cp
>  
>  sysdep_headers += bits/fcntl-linux.h
>  
> diff --git a/sysdeps/unix/sysv/linux/fstat.c
> b/sysdeps/unix/sysv/linux/fstat.c index bdbeded956..0981dbaa95 100644
> --- a/sysdeps/unix/sysv/linux/fstat.c
> +++ b/sysdeps/unix/sysv/linux/fstat.c
> @@ -19,13 +19,24 @@
>  #include <sys/stat.h>
>  #include <kernel_stat.h>
>  #include <fcntl.h>
> +#include <stat_t64_cp.h>
>  
>  #if !XSTAT_IS_XSTAT64
> +int
> +__fstat_time64 (int fd, struct __stat_t64 *buf)
> +{
> +  return __fstatat_time64 (fd, "", buf, AT_EMPTY_PATH);
> +}
> +# if __TIMESIZE != 64
> +libc_hidden_def (__fstat_time64)
> +
>  int
>  __fstat (int fd, struct stat *buf)
>  {
> -  return __fstatat (fd, "", buf, AT_EMPTY_PATH);
> +  struct __stat_t64 st_t64;
> +  return __fstat_time64 (fd, &st_t64) ?: __cp_stat_t64_stat
> (&st_t64, buf); }
> +# endif
>  
>  weak_alias (__fstat, fstat)
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/fstat64.c
> b/sysdeps/unix/sysv/linux/fstat64.c index c2ff1ff577..67667e79d8
> 100644 --- a/sysdeps/unix/sysv/linux/fstat64.c
> +++ b/sysdeps/unix/sysv/linux/fstat64.c
> @@ -19,16 +19,30 @@
>  #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>
> +
> +int
> +__fstat64_time64 (int fd, struct __stat64_t64 *buf)
> +{
> +  return __fstatat64_time64 (fd, "", buf, AT_EMPTY_PATH);
> +}
> +#if __TIMESIZE != 64
> +hidden_def (__fstat64_time64)
>  
>  int
>  __fstat64 (int fd, struct stat64 *buf)
>  {
> -  return __fstatat64 (fd, "", buf, AT_EMPTY_PATH);
> +  struct __stat64_t64 st_t64;
> +  return __fstat64_time64 (fd, &st_t64)
> +	 ?: __cp_stat64_t64_stat64 (&st_t64, buf);
>  }
> +#endif
> +
> +#undef __fstat
> +#undef fstat
> +
>  hidden_def (__fstat64)
>  weak_alias (__fstat64, fstat64)
>  
> diff --git a/sysdeps/unix/sysv/linux/fstatat.c
> b/sysdeps/unix/sysv/linux/fstatat.c index 03ddb3f493..f65d3b74a6
> 100644 --- a/sysdeps/unix/sysv/linux/fstatat.c
> +++ b/sysdeps/unix/sysv/linux/fstatat.c
> @@ -22,25 +22,28 @@
>  
>  #if !XSTAT_IS_XSTAT64
>  # include <kstat_cp.h>
> +# include <statx_cp.h>
> +# include <stat_t64_cp.h>
>  
>  int
> -__fstatat (int fd, const char *file, struct stat *st, int flag)
> +__fstatat_time64 (int fd, const char *file, struct __stat_t64 *st,
> int flag) {
> -# if STAT_IS_KERNEL_STAT
> -  /* New kABIs which uses generic pre 64-bit time Linux ABI, e.g.
> -     csky, nios2  */
> -  int r = INLINE_SYSCALL_CALL (fstatat64, fd, file, st, flag);
> -  if (r == 0 && (st->__st_ino_pad != 0
> -		 || st->__st_size_pad != 0
> -		 || st->__st_blocks_pad != 0))
> -    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
> -  return r;
> -# else
> -#  ifdef __NR_fstatat64
> -  /* Old KABIs with old non-LFS support, e.g. arm, i386, hppa, m68k,
> mips32,
> -     microblaze, s390, sh, powerpc, and sparc.  */
> +  struct statx stx;
> +  int r = INLINE_SYSCALL_CALL (statx, fd, file, flag,
> STATX_BASIC_STATS,
> +			       &stx);

I'm wondering about the indentation here - I do see 3*TAB and some
spaces. Shouldn't we only use spaces?

And one more question what is the correct alignment:
		(statx, fd, file, flag
		 &stx);

or
		(statx, fd, file, flag
		&stx);

> +  if (r == 0 || errno != ENOSYS)
> +    {
> +      if (r == 0)
> +	__cp_stat_t64_statx (st, &stx);
> +      return r;
> +    }

Great that the statx is used here.

> +
> +# ifdef __NR_fstatat64
> +  /* Both new kABI which uses generic pre 64-bit time Linux ABI
> (e.g. csky
> +     and nios) and old kABI with non-LFS support (e.g. arm, i386,
> hppa, m68k,
> +     mips32, microblaze, s390, sh, powerpc, and sparc32).  */
>    struct stat64 st64;
> -  int r = INLINE_SYSCALL_CALL (fstatat64, fd, file, &st64, flag);
> +  r = INLINE_SYSCALL_CALL (fstatat64, fd, file, &st64, flag);
>    if (r == 0)
>      {
>        if (! in_ino_t_range (st64.st_ino)
> @@ -48,7 +51,7 @@ __fstatat (int fd, const char *file, struct stat
> *st, int flag) || ! in_blkcnt_t_range (st64.st_blocks))
>  	return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
>  
> -      /* Clear internal pad and reserved fields.  */
> +      /* Clear both pad and reserved fields.  */
>        memset (st, 0, sizeof (*st));
>  
>        st->st_dev = st64.st_dev,
> @@ -61,22 +64,29 @@ __fstatat (int fd, const char *file, struct stat
> *st, int flag) st->st_size = st64.st_size;
>        st->st_blksize = st64.st_blksize;
>        st->st_blocks  = st64.st_blocks;
> -      st->st_atim.tv_sec = st64.st_atim.tv_sec;
> -      st->st_atim.tv_nsec = st64.st_atim.tv_nsec;
> -      st->st_mtim.tv_sec = st64.st_mtim.tv_sec;
> -      st->st_mtim.tv_nsec = st64.st_mtim.tv_nsec;
> -      st->st_ctim.tv_sec = st64.st_ctim.tv_sec;
> -      st->st_ctim.tv_nsec = st64.st_ctim.tv_nsec;
> +      st->st_atim = valid_timespec_to_timespec64 (st64.st_atim);
> +      st->st_mtim = valid_timespec_to_timespec64 (st64.st_mtim);
> +      st->st_ctim = valid_timespec_to_timespec64 (st64.st_ctim);
>      }
>    return r;
> -#  else
> +# else
>    /* 64-bit kabi outlier, e.g. mips64 and mips64-n32.  */
>    struct kernel_stat kst;
> -  int r = INTERNAL_SYSCALL_CALL (newfstatat, fd, file, &kst, flag);
> -  return r ?: __cp_kstat_stat (&kst, st);
> -#  endif /* __nr_fstatat64  */
> -# endif /* STAT_IS_KERNEL_STAT  */
> +  r = INTERNAL_SYSCALL_CALL (newfstatat, fd, file, &kst, flag);
> +  return r ?: __cp_kstat_stat_t64 (&kst, st);
> +# endif /* __NR_fstatat64  */
> +}
> +# if __TIMESIZE != 64
> +libc_hidden_def (__fstatat_time64)
> +
> +int
> +__fstatat (int fd, const char *file, struct stat *buf, int flags)
> +{
> +  struct __stat_t64 st_t64;
> +  return __fstatat_time64 (fd, file, &st_t64, flags)
> +	 ?: __cp_stat_t64_stat (&st_t64, buf);
>  }
> +# endif
>  
>  weak_alias (__fstatat, fstatat)
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/fstatat64.c
> b/sysdeps/unix/sysv/linux/fstatat64.c index 82fab107a5..b3940f0d20
> 100644 --- a/sysdeps/unix/sysv/linux/fstatat64.c
> +++ b/sysdeps/unix/sysv/linux/fstatat64.c
> @@ -19,56 +19,102 @@
>  #define __fstatat __redirect___fstatat
>  #define fstatat   __redirect_fstatat
>  #include <sys/stat.h>
> -#undef __fstatat
> -#undef fstatat
>  #include <fcntl.h>
> -
> +#include <string.h>
>  #include <kernel_stat.h>
>  #include <sysdep.h>
> -
> +#include <time.h>
>  #include <statx_cp.h>
>  #include <kstat_cp.h>
> +#include <stat_t64_cp.h>
>  
>  int
> -__fstatat64 (int fd, const char *file, struct stat64 *st, int flag)
> +__fstatat64_time64 (int fd, const char *file, struct __stat64_t64
> *st,
> +		    int flag)
>  {
> +  int r;
> +
> +#if (__WORDSIZE == 32 \
> +     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))

I do guess that the above condition is to ensure that 32 bit archs
(excluding x86_64-x32 - e.g. arm, riscv, etc) use statx?

> +  struct statx tmp;
> +  r = INLINE_SYSCALL_CALL (statx, fd, file, AT_NO_AUTOMOUNT | flag,
> +			   STATX_BASIC_STATS, &tmp);
> +  if (r == 0 || errno != ENOSYS)
> +    {
> +      if (r == 0)
> +	__cp_stat64_t64_statx (st, &tmp);
> +      return r;
> +    }
> +#endif
> +
>  #if XSTAT_IS_XSTAT64
>  # ifdef __NR_newfstatat
>    /* 64-bit kABI, e.g. aarch64, ia64, powerpc64*, s390x, riscv64, and
>       x86_64.  */
> -  return INLINE_SYSCALL_CALL (newfstatat, fd, file, st, flag);
> +  r = INLINE_SYSCALL_CALL (newfstatat, fd, file, st, flag);
>  # elif defined __NR_fstatat64
>  #  if STAT64_IS_KERNEL_STAT64
> -  /* 64-bit kABI outlier, e.g. alpha.  */
> -  return INLINE_SYSCALL_CALL (fstatat64, fd, file, st, flag);
> +  /* 64-bit kABI outlier, e.g. alpha  */
> +  r = INLINE_SYSCALL_CALL (fstatat64, fd, file, st, flag);
>  #  else
>    /* 64-bit kABI outlier, e.g. sparc64.  */
>    struct kernel_stat64 kst64;
> -  int r = INLINE_SYSCALL_CALL (fstatat64, fd, file, &kst64, flag);
> -  return r ?: __cp_stat64_kstat64 (st, &kst64);
> -#  endif
> -# else
> -  /* 32-bit kABI with default 64-bit time_t, e.g. arc, riscv32.  */
> -  struct statx tmp;
> -  int r = INLINE_SYSCALL_CALL (statx, fd, file, AT_NO_AUTOMOUNT |
> flag,
> -			       STATX_BASIC_STATS, &tmp);
> +  r = INLINE_SYSCALL_CALL (fstatat64, fd, file, &kst64, flag);
>    if (r == 0)
> -    __cp_stat64_statx (st, &tmp);
> -  return r;
> +    r = __cp_stat64_kstat64 (st, &kst64);
> +#  endif
>  # endif
>  #else
>  # ifdef __NR_fstatat64
>    /* All kABIs with non-LFS support, e.g. arm, csky, i386, hppa,
> m68k, microblaze, nios2, sh, powerpc32, and sparc32.  */
> -  return INLINE_SYSCALL_CALL (fstatat64, fd, file, st, flag);
> +  struct stat64 st64;
> +  r = INLINE_SYSCALL_CALL (fstatat64, fd, file, &st64, flag);
> +  if (r == 0)
> +    {
> +      /* Clear both pad and reserved fields.  */
> +      memset (st, 0, sizeof (*st));
> +
> +      st->st_dev = st64.st_dev,
> +      st->st_ino = st64.st_ino;
> +      st->st_mode = st64.st_mode;
> +      st->st_nlink = st64.st_nlink;
> +      st->st_uid = st64.st_uid;
> +      st->st_gid = st64.st_gid;
> +      st->st_rdev = st64.st_rdev;
> +      st->st_size = st64.st_size;
> +      st->st_blksize = st64.st_blksize;
> +      st->st_blocks  = st64.st_blocks;
> +      st->st_atim = valid_timespec_to_timespec64 (st64.st_atim);
> +      st->st_mtim = valid_timespec_to_timespec64 (st64.st_mtim);
> +      st->st_ctim = valid_timespec_to_timespec64 (st64.st_ctim);
> +    }
>  # else
>    /* 64-bit kabi outlier, e.g. mips64 and mips64-n32.  */
>    struct kernel_stat kst;
> -  int r = INTERNAL_SYSCALL_CALL (newfstatat, fd, file, &kst, flag);
> -  return r ?: __cp_kstat_stat64 (&kst, st);
> +  r = INTERNAL_SYSCALL_CALL (newfstatat, fd, file, &kst, flag);
> +  if (r == 0)
> +    r =  __cp_kstat_stat64_t64 (&kst, st);
>  # endif
>  #endif
> +
> +  return r;
>  }
> +#if __TIMESIZE != 64
> +hidden_def (__fstatat64_time64)
> +
> +int
> +__fstatat64 (int fd, const char *file, struct stat64 *st, int flags)
> +{
> +  struct __stat64_t64 st_t64;
> +  return __fstatat64_time64 (fd, file, &st_t64, flags)
> +	 ?: __cp_stat64_t64_stat64 (&st_t64, st);
> +}
> +#endif
> +
> +#undef __fstatat
> +#undef fstatat
> +
>  hidden_def (__fstatat64)
>  weak_alias (__fstatat64, fstatat64)
>  
> diff --git a/sysdeps/unix/sysv/linux/lstat.c
> b/sysdeps/unix/sysv/linux/lstat.c index b0bdeee9e9..803ad78171 100644
> --- a/sysdeps/unix/sysv/linux/lstat.c
> +++ b/sysdeps/unix/sysv/linux/lstat.c
> @@ -19,13 +19,24 @@
>  #include <sys/stat.h>
>  #include <fcntl.h>
>  #include <kernel_stat.h>
> +#include <stat_t64_cp.h>
>  
>  #if !XSTAT_IS_XSTAT64
> +int
> +__lstat_time64 (const char *file, struct __stat_t64 *buf)
> +{
> +  return __fstatat_time64 (AT_FDCWD, file, buf, AT_SYMLINK_NOFOLLOW);
> +}
> +# if __TIMESIZE != 64
> +libc_hidden_def (__lstat_time64)
> +
>  int
>  __lstat (const char *file, struct stat *buf)
>  {
> -  return __fstatat (AT_FDCWD, file, buf, AT_SYMLINK_NOFOLLOW);
> +  struct __stat_t64 st_t64;
> +  return __lstat_time64 (file, &st_t64) ?: __cp_stat_t64_stat
> (&st_t64, buf); }
> +# endif
>  
>  weak_alias (__lstat, lstat)
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/lstat64.c
> b/sysdeps/unix/sysv/linux/lstat64.c index e5f02e9822..971ab8469d
> 100644 --- a/sysdeps/unix/sysv/linux/lstat64.c
> +++ b/sysdeps/unix/sysv/linux/lstat64.c
> @@ -19,19 +19,32 @@
>  #define __lstat __redirect___lstat
>  #define lstat   __redirect_lstat
>  #include <sys/stat.h>
> -#undef __lstat
> -#undef lstat
>  #include <fcntl.h>
>  #include <kernel_stat.h>
> +#include <stat_t64_cp.h>
> +
> +int
> +__lstat64_time64 (const char *file, struct __stat64_t64 *buf)
> +{
> +  return __fstatat64_time64 (AT_FDCWD, file, buf,
> AT_SYMLINK_NOFOLLOW); +}
> +#if __TIMESIZE != 64
> +hidden_def (__lstat64_time64)
>  
>  int
>  __lstat64 (const char *file, struct stat64 *buf)
>  {
> -  return __fstatat64 (AT_FDCWD, file, buf, AT_SYMLINK_NOFOLLOW);
> +  struct __stat64_t64 st_t64;
> +  return __lstat64_time64 (file, &st_t64)
> +	 ?: __cp_stat64_t64_stat64 (&st_t64, buf);
>  }
> +#endif
>  hidden_def (__lstat64)
>  weak_alias (__lstat64, lstat64)
>  
> +#undef __lstat
> +#undef lstat
> +
>  #if XSTAT_IS_XSTAT64
>  strong_alias (__lstat64, __lstat)
>  weak_alias (__lstat64, lstat)
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/kstat_cp.h
> b/sysdeps/unix/sysv/linux/mips/mips64/kstat_cp.h index
> 7f226416f9..553f4226bc 100644 ---
> a/sysdeps/unix/sysv/linux/mips/mips64/kstat_cp.h +++
> b/sysdeps/unix/sysv/linux/mips/mips64/kstat_cp.h @@ -20,23 +20,21 @@
>  #include <kernel_stat.h>
>  
>  static inline int
> -__cp_kstat_stat (const struct kernel_stat *kst, struct stat *st)
> +__cp_kstat_stat_t64 (const struct kernel_stat *kst, struct
> __stat_t64 *st) {
> +  if (! in_ino_t_range (kst->st_ino)
> +      || ! in_off_t_range (kst->st_size)
> +      || ! in_blkcnt_t_range (kst->st_blocks))
> +    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
> +
>    st->st_dev = kst->st_dev;
> -  memset (&st->st_pad1, 0, sizeof (st->st_pad1));
>    st->st_ino = kst->st_ino;
> -  if (st->st_ino != kst->st_ino)
> -    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
>    st->st_mode = kst->st_mode;
>    st->st_nlink = kst->st_nlink;
>    st->st_uid = kst->st_uid;
>    st->st_gid = kst->st_gid;
>    st->st_rdev = kst->st_rdev;
> -  memset (&st->st_pad2, 0, sizeof (st->st_pad2));
>    st->st_size = kst->st_size;
> -  if (st->st_size != kst->st_size)
> -    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
> -  st->st_pad3 = 0;
>    st->st_atim.tv_sec = kst->st_atime_sec;
>    st->st_atim.tv_nsec = kst->st_atime_nsec;
>    st->st_mtim.tv_sec = kst->st_mtime_sec;
> @@ -45,26 +43,20 @@ __cp_kstat_stat (const struct kernel_stat *kst,
> struct stat *st) st->st_ctim.tv_nsec = kst->st_ctime_nsec;
>    st->st_blksize = kst->st_blksize;
>    st->st_blocks = kst->st_blocks;
> -  if (st->st_blocks != kst->st_blocks)
> -    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
> -  memset (&st->st_pad5, 0, sizeof (st->st_pad5));
>  
>    return 0;
>  }
>  
>  static inline int
> -__cp_kstat_stat64 (const struct kernel_stat *kst, struct stat64 *st)
> +__cp_kstat_stat64_t64 (const struct kernel_stat *kst, struct
> __stat64_t64 *st) {
>    st->st_dev = kst->st_dev;
> -  memset (&st->st_pad1, 0, sizeof (st->st_pad1));
>    st->st_ino = kst->st_ino;
>    st->st_mode = kst->st_mode;
>    st->st_nlink = kst->st_nlink;
>    st->st_uid = kst->st_uid;
>    st->st_gid = kst->st_gid;
>    st->st_rdev = kst->st_rdev;
> -  memset (&st->st_pad2, 0, sizeof (st->st_pad2));
> -  st->st_pad3 = 0;
>    st->st_size = kst->st_size;
>    st->st_blksize = kst->st_blksize;
>    st->st_blocks = kst->st_blocks;
> @@ -74,7 +66,6 @@ __cp_kstat_stat64 (const struct kernel_stat *kst,
> struct stat64 *st) st->st_mtim.tv_nsec = kst->st_mtime_nsec;
>    st->st_ctim.tv_sec = kst->st_ctime_sec;
>    st->st_ctim.tv_nsec = kst->st_ctime_nsec;
> -  memset (&st->st_pad4, 0, sizeof (st->st_pad4));
>  
>    return 0;
>  }
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/statx_cp.c
> b/sysdeps/unix/sysv/linux/mips/mips64/statx_cp.c deleted file mode
> 100644 index 260cda987e..0000000000
> --- a/sysdeps/unix/sysv/linux/mips/mips64/statx_cp.c
> +++ /dev/null
> @@ -1,3 +0,0 @@
> -/* Override the generic statx_cp.c which is only needed for new
> 32-bit arch
> -   without stat64 family support.
> - */
> diff --git a/sysdeps/unix/sysv/linux/stat.c
> b/sysdeps/unix/sysv/linux/stat.c index a77502eb95..dcbc22da29 100644
> --- a/sysdeps/unix/sysv/linux/stat.c
> +++ b/sysdeps/unix/sysv/linux/stat.c
> @@ -19,13 +19,24 @@
>  #include <sys/stat.h>
>  #include <fcntl.h>
>  #include <kernel_stat.h>
> +#include <stat_t64_cp.h>
>  
>  #if !XSTAT_IS_XSTAT64
> +int
> +__stat_time64 (const char *file, struct __stat_t64 *buf)
> +{
> +  return __fstatat_time64 (AT_FDCWD, file, buf, 0);
> +}
> +# if __TIMESIZE != 64
> +libc_hidden_def (__stat_time64);
> +
>  int
>  __stat (const char *file, struct stat *buf)
>  {
> -  return __fstatat (AT_FDCWD, file, buf, 0);
> +  struct __stat_t64 st_t64;
> +  return __stat_time64 (file, &st_t64) ?: __cp_stat_t64_stat
> (&st_t64, buf); }
> +# endif
>  
>  weak_alias (__stat, stat)
>  #endif
> diff --git a/sysdeps/unix/sysv/linux/stat64.c
> b/sysdeps/unix/sysv/linux/stat64.c index 2f40037c2c..bd8b17ac49 100644
> --- a/sysdeps/unix/sysv/linux/stat64.c
> +++ b/sysdeps/unix/sysv/linux/stat64.c
> @@ -19,16 +19,30 @@
>  #define __stat __redirect___stat
>  #define stat   __redirect_stat
>  #include <sys/stat.h>
> -#undef __stat
> -#undef stat
>  #include <fcntl.h>
>  #include <kernel_stat.h>
> +#include <stat_t64_cp.h>
> +
> +int
> +__stat64_time64 (const char *file, struct __stat64_t64 *buf)
> +{
> +  return __fstatat64_time64 (AT_FDCWD, file, buf, 0);
> +}
> +#if __TIMESIZE != 64
> +hidden_def (__stat64_time64)
>  
>  int
>  __stat64 (const char *file, struct stat64 *buf)
>  {
> -  return __fstatat64 (AT_FDCWD, file, buf, 0);
> +  struct __stat64_t64 st_t64;
> +  return __stat64_time64 (file, &st_t64)
> +	 ?: __cp_stat64_t64_stat64 (&st_t64, buf);
>  }
> +#endif
> +
> +#undef __stat
> +#undef stat
> +
>  hidden_def (__stat64)
>  weak_alias (__stat64, stat64)
>  
> diff --git a/sysdeps/unix/sysv/linux/stat_t64_cp.c
> b/sysdeps/unix/sysv/linux/stat_t64_cp.c new file mode 100644
> index 0000000000..56459b6266
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/stat_t64_cp.c
> @@ -0,0 +1,92 @@
> +/* Struct stat/stat64 to stat/stat64 conversion for Linux.
> +   Copyright (C) 2020 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 <stat_t64_cp.h>
> +#include <string.h>
> +#include <errno.h>
> +#include <time.h>
> +
> +#if __TIMESIZE != 64
> +/* Convert the 64-bit time_t stat ST_T64 to the non-LFS ST stat and
> returns
> +   EOVERFLOW if any of time (access, modification, status) is larger
> than
> +   32-bit time_t.  It is used on non-LFS stat, fstat, lstat, and
> fstatat to
> +   convert from the the 64-bit time_t call.  */
> +int
> +__cp_stat_t64_stat (const struct __stat_t64 *st_t64, struct stat *st)
> +{
> +  if (! in_time_t_range (st_t64->st_atim.tv_sec)
> +      || ! in_time_t_range (st_t64->st_mtim.tv_sec)
> +      || ! in_time_t_range (st_t64->st_ctim.tv_sec))
> +    {
> +      __set_errno (EOVERFLOW);
> +      return -1;
> +    }
> +
> +  /* Clear both pad and reserved fields.  */
> +  memset (st, 0, sizeof (*st));
> +
> +  st->st_dev = st_t64->st_dev,
> +  st->st_ino = st_t64->st_ino;
> +  st->st_mode = st_t64->st_mode;
> +  st->st_nlink = st_t64->st_nlink;
> +  st->st_uid = st_t64->st_uid;
> +  st->st_gid = st_t64->st_gid;
> +  st->st_rdev = st_t64->st_rdev;
> +  st->st_size = st_t64->st_size;
> +  st->st_blksize = st_t64->st_blksize;
> +  st->st_blocks  = st_t64->st_blocks;
> +  st->st_atim = valid_timespec64_to_timespec (st_t64->st_atim);
> +  st->st_mtim = valid_timespec64_to_timespec (st_t64->st_mtim);
> +  st->st_ctim = valid_timespec64_to_timespec (st_t64->st_ctim);
> +
> +  return 0;
> +}
> +
> +int
> +__cp_stat64_t64_stat64 (const struct __stat64_t64 *st64_t64,
> +			struct stat64 *st64)
> +{
> +  if (! in_time_t_range (st64_t64->st_atim.tv_sec)
> +      || ! in_time_t_range (st64_t64->st_mtim.tv_sec)
> +      || ! in_time_t_range (st64_t64->st_ctim.tv_sec))
> +    {
> +      __set_errno (EOVERFLOW);
> +      return -1;
> +    }
> +
> +  /* Clear both pad and reserved fields.  */
> +  memset (st64, 0, sizeof (*st64));
> +
> +  st64->st_dev = st64_t64->st_dev,
> +  st64->st_ino = st64_t64->st_ino;
> +  st64->st_mode = st64_t64->st_mode;
> +  st64->st_nlink = st64_t64->st_nlink;
> +  st64->st_uid = st64_t64->st_uid;
> +  st64->st_gid = st64_t64->st_gid;
> +  st64->st_rdev = st64_t64->st_rdev;
> +  st64->st_size = st64_t64->st_size;
> +  st64->st_blksize = st64_t64->st_blksize;
> +  st64->st_blocks  = st64_t64->st_blocks;
> +  st64->st_atim = valid_timespec64_to_timespec (st64_t64->st_atim);
> +  st64->st_mtim = valid_timespec64_to_timespec (st64_t64->st_mtim);
> +  st64->st_ctim = valid_timespec64_to_timespec (st64_t64->st_ctim);
> +
> +  return 0;
> +}
> +
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/stat_t64_cp.h
> b/sysdeps/unix/sysv/linux/stat_t64_cp.h new file mode 100644
> index 0000000000..ad2bcc7a04
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/stat_t64_cp.h
> @@ -0,0 +1,28 @@
> +/* Copy to/from struct stat with and without 64-bit time_t support.
> +   Copyright (C) 2020 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 <sys/stat.h>
> +
> +#if __TIMESIZE != 64
> +extern int __cp_stat_t64_stat (const struct __stat_t64 *st_t64,
> +			       struct stat *st)
> +  attribute_hidden;
> +extern int __cp_stat64_t64_stat64 (const struct __stat64_t64
> *st64_t64,
> +				   struct stat64 *st64)
> +  attribute_hidden;
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/statx_cp.c
> b/sysdeps/unix/sysv/linux/statx_cp.c index cc6e17929e..4b35e86f8d
> 100644 --- a/sysdeps/unix/sysv/linux/statx_cp.c
> +++ b/sysdeps/unix/sysv/linux/statx_cp.c
> @@ -47,3 +47,57 @@ __cp_stat64_statx (struct stat64 *to, struct statx
> *from) to->st_blksize = from->stx_blksize;
>  }
>  #endif
> +
> +void
> +__cp_stat_t64_statx (struct __stat_t64 *to, const struct statx *from)
> +{
> +  /* Clear both pad and reserved fields.  */
> +  memset (to, 0, sizeof (*to));
> +
> +  to->st_dev = ((from->stx_dev_minor & 0xff) | (from->stx_dev_major
> << 8)
> +		| ((from->stx_dev_minor & ~0xff) << 12));
> +  to->st_ino = from->stx_ino;
> +  to->st_mode = from->stx_mode;
> +  to->st_nlink = from->stx_nlink;
> +  to->st_uid = from->stx_uid;
> +  to->st_gid = from->stx_gid;
> +  to->st_rdev = ((from->stx_rdev_minor & 0xff) |
> (from->stx_rdev_major << 8)
> +		 | ((from->stx_rdev_minor & ~0xff) << 12));
> +  to->st_size = from->stx_size;
> +  to->st_blksize = from->stx_blksize;
> +  to->st_blocks = from->stx_blocks;
> +
> +  to->st_atime = from->stx_atime.tv_sec;
> +  to->st_atim.tv_nsec = from->stx_atime.tv_nsec;
> +  to->st_mtime = from->stx_mtime.tv_sec;
> +  to->st_mtim.tv_nsec = from->stx_mtime.tv_nsec;
> +  to->st_ctime = from->stx_ctime.tv_sec;
> +  to->st_ctim.tv_nsec = from->stx_ctime.tv_nsec;
> +}
> +
> +void
> +__cp_stat64_t64_statx (struct __stat64_t64 *to, const struct statx
> *from) +{
> +  /* Clear both pad and reserved fields.  */
> +  memset (to, 0, sizeof (*to));
> +
> +  to->st_dev = ((from->stx_dev_minor & 0xff) | (from->stx_dev_major
> << 8)
> +		| ((from->stx_dev_minor & ~0xff) << 12));
> +  to->st_ino = from->stx_ino;
> +  to->st_mode = from->stx_mode;
> +  to->st_nlink = from->stx_nlink;
> +  to->st_uid = from->stx_uid;
> +  to->st_gid = from->stx_gid;
> +  to->st_rdev = ((from->stx_rdev_minor & 0xff) |
> (from->stx_rdev_major << 8)
> +		 | ((from->stx_rdev_minor & ~0xff) << 12));
> +  to->st_size = from->stx_size;
> +  to->st_blksize = from->stx_blksize;
> +  to->st_blocks = from->stx_blocks;
> +
> +  to->st_atime = from->stx_atime.tv_sec;
> +  to->st_atim.tv_nsec = from->stx_atime.tv_nsec;
> +  to->st_mtime = from->stx_mtime.tv_sec;
> +  to->st_mtim.tv_nsec = from->stx_mtime.tv_nsec;
> +  to->st_ctime = from->stx_ctime.tv_sec;
> +  to->st_ctim.tv_nsec = from->stx_ctime.tv_nsec;
> +}
> diff --git a/sysdeps/unix/sysv/linux/statx_cp.h
> b/sysdeps/unix/sysv/linux/statx_cp.h index fdbb807a31..bf3186ffac
> 100644 --- a/sysdeps/unix/sysv/linux/statx_cp.h
> +++ b/sysdeps/unix/sysv/linux/statx_cp.h
> @@ -18,3 +18,9 @@
>  
>  extern void __cp_stat64_statx (struct stat64 *to, struct statx *from)
>    attribute_hidden;
> +extern void __cp_stat_t64_statx (struct __stat_t64 *to,
> +				 const struct statx *from)
> +  attribute_hidden;
> +extern void __cp_stat64_t64_statx (struct __stat64_t64 *to,
> +				   const struct statx *from)
> +  attribute_hidden;
> diff --git a/sysdeps/unix/sysv/linux/struct_stat_time64.h
> b/sysdeps/unix/sysv/linux/struct_stat_time64.h new file mode 100644
> index 0000000000..b2a51927d0
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/struct_stat_time64.h
> @@ -0,0 +1,122 @@
> +/* Struct stat with 64-bit time support.
> +   Copyright (C) 2020 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/>.  */
> +
> +#ifndef _BITS_STRUCT_STAT_TIME64_H
> +#define _BITS_STRUCT_STAT_TIME64_H 1
> +
> +#if __TIMESIZE == 64
> +# define __stat_t64   stat
> +# define __stat64_t64 stat64
> +#else
> +# include <endian.h>
> +
> +# ifdef __USE_FILE_OFFSET64
> +#  define __field64(type, type64, name) type64 name
> +# else
> +#  define __field64(type, type64, name) type name
> +# endif
> +
> +/* The definition should be equal to the 'struct __timespec64'
> internal
> +   layout.  */
> +# if BYTE_ORDER == BIG_ENDIAN
> +#  define __fieldts64(name) 					\
> +   __time64_t name; __int32_t :32; __int32_t name ## nsec
> +# else
> +#  define __fieldts64(name)					\
> +   __time64_t name; __int32_t name ## nsec; __int32_t :32
> +# endif
> +
> +/* Workaround for the definition from struct_stat.h  */
> +# undef st_atime
> +# undef st_mtime
> +# undef st_ctime
> +
> +struct __stat_t64
> +  {
> +    __dev_t st_dev;			/* Device.  */
> +    __field64(__ino_t, __ino64_t, st_ino);  /* File serial number.
> */
> +    __mode_t st_mode;			/* File mode.  */
> +    __nlink_t st_nlink;			/* Link count.  */
> +    __uid_t st_uid;			/* User ID of the file's
> owner.	*/
> +    __gid_t st_gid;			/* Group ID of the file's
> group.*/
> +    __dev_t st_rdev;			/* Device number, if
> device.  */
> +    __field64(__off_t, __off64_t, st_size);  /* Size of file, in
> bytes. */
> +    __blksize_t st_blksize;		/* Optimal block size for
> I/O.  */
> +    __field64(__blkcnt_t, __blkcnt64_t, st_blocks);  /* 512-byte
> blocks */ +# ifdef __USE_XOPEN2K8
> +    /* Nanosecond resolution timestamps are stored in a format
> +       equivalent to 'struct timespec'.  This is the type used
> +       whenever possible but the Unix namespace rules do not allow
> the
> +       identifier 'timespec' to appear in the <sys/stat.h> header.
> +       Therefore we have to handle the use of this header in strictly
> +       standard-compliant sources special.  */
> +    struct __timespec64 st_atim;	/* Time of last access.  */
> +    struct __timespec64 st_mtim;	/* Time of last
> modification.  */
> +    struct __timespec64 st_ctim;	/* Time of last status
> change.  */ +#  define st_atime st_atim.tv_sec	/* Backward
> compatibility.  */ +#  define st_mtime st_mtim.tv_sec
> +#  define st_ctime st_ctim.tv_sec
> +# else
> +    __fieldts64 (st_atime);
> +    __fieldts64 (st_mtime);
> +    __fieldts64 (st_ctime);
> +# endif /* __USE_XOPEN2K8  */
> +  };
> +
> +# undef __field64
> +
> +#ifdef __USE_LARGEFILE64
> +struct __stat64_t64
> +  {
> +    __dev_t st_dev;			/* Device.  */
> +    __ino64_t st_ino;			/* file serial
> number.	*/
> +    __mode_t st_mode;			/* File mode.  */
> +    __nlink_t st_nlink;			/* Link count.  */
> +    __uid_t st_uid;			/* User ID of the file's
> owner.	*/
> +    __gid_t st_gid;			/* Group ID of the file's
> group.*/
> +    __dev_t st_rdev;			/* Device number, if
> device.  */
> +    __off64_t st_size;			/* Size of file, in
> bytes.  */
> +    __blksize_t st_blksize;		/* Optimal block size for
> I/O.  */
> +    __blkcnt64_t st_blocks;		/* Number 512-byte blocks
> allocated. */ +# ifdef __USE_XOPEN2K8
> +    /* Nanosecond resolution timestamps are stored in a format
> +       equivalent to 'struct timespec'.  This is the type used
> +       whenever possible but the Unix namespace rules do not allow
> the
> +       identifier 'timespec' to appear in the <sys/stat.h> header.
> +       Therefore we have to handle the use of this header in strictly
> +       standard-compliant sources special.  */
> +    struct __timespec64 st_atim;	/* Time of last access.  */
> +    struct __timespec64 st_mtim;	/* Time of last
> modification.  */
> +    struct __timespec64 st_ctim;	/* Time of last status
> change.  */ +# else
> +    __fieldts64 (st_atime);
> +    __fieldts64 (st_mtime);
> +    __fieldts64 (st_ctime);
> +# endif /* __USE_XOPEN2K8  */
> +  };
> +# endif /* __USE_LARGEFILE64  */
> +
> +# undef __fieldts64
> +
> +# define _STATBUF_ST_BLKSIZE
> +# define _STATBUF_ST_RDEV
> +# define _STATBUF_ST_NSEC
> +
> +# endif /* __TIMESIZE == 64  */
> +
> +#endif /* _BITS_STRUCT_STAT_TIME64_H  */

Despite some very minor comments,

Acked-by: Lukasz Majewski <lukma@denx.de>


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
  
Adhemerval Zanella July 30, 2020, 12:42 p.m. UTC | #4
On 24/07/2020 07:53, Lukasz Majewski wrote:
>>  
>> diff --git a/sysdeps/unix/sysv/linux/fstatat.c
>> b/sysdeps/unix/sysv/linux/fstatat.c index 03ddb3f493..f65d3b74a6
>> 100644 --- a/sysdeps/unix/sysv/linux/fstatat.c
>> +++ b/sysdeps/unix/sysv/linux/fstatat.c
>> -#  ifdef __NR_fstatat64
>> -  /* Old KABIs with old non-LFS support, e.g. arm, i386, hppa, m68k,
>> mips32,
>> -     microblaze, s390, sh, powerpc, and sparc.  */
>> +  struct statx stx;
>> +  int r = INLINE_SYSCALL_CALL (statx, fd, file, flag,
>> STATX_BASIC_STATS,
>> +			       &stx);
> 
> I'm wondering about the indentation here - I do see 3*TAB and some
> spaces. Shouldn't we only use spaces?

Afaik the GNU code guidelines requires to use TAB indentations instead
of space in this case.  


> 
> And one more question what is the correct alignment:
> 		(statx, fd, file, flag
> 		 &stx);
> 
> or
> 		(statx, fd, file, flag
> 		&stx);

My understanding the latter.

> 
>> +  if (r == 0 || errno != ENOSYS)
>> +    {
>> +      if (r == 0)
>> +	__cp_stat_t64_statx (st, &stx);
>> +      return r;
>> +    }
> 
> Great that the statx is used here.
> 
>> +
>> +# ifdef __NR_fstatat64
>> +  /* Both new kABI which uses generic pre 64-bit time Linux ABI
>> (e.g. csky
>> +     and nios) and old kABI with non-LFS support (e.g. arm, i386,
>> hppa, m68k,
>> +     mips32, microblaze, s390, sh, powerpc, and sparc32).  */
>>    struct stat64 st64;
>> -  int r = INLINE_SYSCALL_CALL (fstatat64, fd, file, &st64, flag);
>> +  r = INLINE_SYSCALL_CALL (fstatat64, fd, file, &st64, flag);
>>    if (r == 0)
>>      {
>>        if (! in_ino_t_range (st64.st_ino)
>> @@ -48,7 +51,7 @@ __fstatat (int fd, const char *file, struct stat
>> *st, int flag) || ! in_blkcnt_t_range (st64.st_blocks))
>>  	return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
>>  
>> -      /* Clear internal pad and reserved fields.  */
>> +      /* Clear both pad and reserved fields.  */
>>        memset (st, 0, sizeof (*st));
>>  
>>        st->st_dev = st64.st_dev,
>> @@ -61,22 +64,29 @@ __fstatat (int fd, const char *file, struct stat
>> *st, int flag) st->st_size = st64.st_size;
>>        st->st_blksize = st64.st_blksize;
>>        st->st_blocks  = st64.st_blocks;
>> -      st->st_atim.tv_sec = st64.st_atim.tv_sec;
>> -      st->st_atim.tv_nsec = st64.st_atim.tv_nsec;
>> -      st->st_mtim.tv_sec = st64.st_mtim.tv_sec;
>> -      st->st_mtim.tv_nsec = st64.st_mtim.tv_nsec;
>> -      st->st_ctim.tv_sec = st64.st_ctim.tv_sec;
>> -      st->st_ctim.tv_nsec = st64.st_ctim.tv_nsec;
>> +      st->st_atim = valid_timespec_to_timespec64 (st64.st_atim);
>> +      st->st_mtim = valid_timespec_to_timespec64 (st64.st_mtim);
>> +      st->st_ctim = valid_timespec_to_timespec64 (st64.st_ctim);
>>      }
>>    return r;
>> -#  else
>> +# else
>>    /* 64-bit kabi outlier, e.g. mips64 and mips64-n32.  */
>>    struct kernel_stat kst;
>> -  int r = INTERNAL_SYSCALL_CALL (newfstatat, fd, file, &kst, flag);
>> -  return r ?: __cp_kstat_stat (&kst, st);
>> -#  endif /* __nr_fstatat64  */
>> -# endif /* STAT_IS_KERNEL_STAT  */
>> +  r = INTERNAL_SYSCALL_CALL (newfstatat, fd, file, &kst, flag);
>> +  return r ?: __cp_kstat_stat_t64 (&kst, st);
>> +# endif /* __NR_fstatat64  */
>> +}
>> +# if __TIMESIZE != 64
>> +libc_hidden_def (__fstatat_time64)
>> +
>> +int
>> +__fstatat (int fd, const char *file, struct stat *buf, int flags)
>> +{
>> +  struct __stat_t64 st_t64;
>> +  return __fstatat_time64 (fd, file, &st_t64, flags)
>> +	 ?: __cp_stat_t64_stat (&st_t64, buf);
>>  }
>> +# endif
>>  
>>  weak_alias (__fstatat, fstatat)
>>  #endif
>> diff --git a/sysdeps/unix/sysv/linux/fstatat64.c
>> b/sysdeps/unix/sysv/linux/fstatat64.c index 82fab107a5..b3940f0d20
>> 100644 --- a/sysdeps/unix/sysv/linux/fstatat64.c
>> +++ b/sysdeps/unix/sysv/linux/fstatat64.c
>> @@ -19,56 +19,102 @@
>>  #define __fstatat __redirect___fstatat
>>  #define fstatat   __redirect_fstatat
>>  #include <sys/stat.h>
>> -#undef __fstatat
>> -#undef fstatat
>>  #include <fcntl.h>
>> -
>> +#include <string.h>
>>  #include <kernel_stat.h>
>>  #include <sysdep.h>
>> -
>> +#include <time.h>
>>  #include <statx_cp.h>
>>  #include <kstat_cp.h>
>> +#include <stat_t64_cp.h>
>>  
>>  int
>> -__fstatat64 (int fd, const char *file, struct stat64 *st, int flag)
>> +__fstatat64_time64 (int fd, const char *file, struct __stat64_t64
>> *st,
>> +		    int flag)
>>  {
>> +  int r;
>> +
>> +#if (__WORDSIZE == 32 \
>> +     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
> 
> I do guess that the above condition is to ensure that 32 bit archs
> (excluding x86_64-x32 - e.g. arm, riscv, etc) use statx?

Yes, this is similar for what is done by SysVIPC fixes.
  
Maciej W. Rozycki Aug. 2, 2020, 7:46 p.m. UTC | #5
On Thu, 30 Jul 2020, Adhemerval Zanella via Libc-alpha wrote:

> > And one more question what is the correct alignment:
> > 		(statx, fd, file, flag
> > 		 &stx);
> > 
> > or
> > 		(statx, fd, file, flag
> > 		&stx);
> 
> My understanding the latter.

 The opposite AFAIK, and you can always use `indent -gnu' to get the stuff 
right as far as "The GNU Coding Standards" are concerned, except perhaps 
for some really obscure code such as I believe some multi-line macros, and 
also some newer constructs such as ISO C99 compound literals may not work 
out well and have to be fixed up by hand (at least with older versions of 
GNU indent; I haven't checked what the most recent behaves like).

 Of course GNU indent will not handle project-specific extra rules such as 
ours: <https://sourceware.org/glibc/wiki/Style_and_Conventions>.

  Maciej
  
Lukasz Majewski Oct. 6, 2020, 9:48 a.m. UTC | #6
Hi Adhemerval,

> A new struct __stat{64}_t64 type is added with the required
> __timespec64 time definition.  Both non-LFS and LFS support were
> done with an extra __NR_statx call plus a conversion to the new
> __stat{64}_t64 type.  The statx call is done only for architectures
> with support for 32-bit time_t ABI.
> 
> Internally some extra routines to copy from/to struct stat{64}
> to struct __stat{64} used on multiple implementations (stat, fstat,
> lstat, and fstatat) are added on a extra file (stat_t64_cp.c).  Aslo
> some extra routines to copy from statx to __stat{64} is added on
> statx_cp.c.
> 
> Checked with a build for all affected ABIs. I also checked on x86_64,
> i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and s390x.

When do you plan to pull this patch set to -master?
Those patches have been available for review on the mailing list for
more than two months now.

Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
  
Adhemerval Zanella Oct. 7, 2020, 12:52 p.m. UTC | #7
On 06/10/2020 06:48, Lukasz Majewski wrote:
> Hi Adhemerval,
> 
>> A new struct __stat{64}_t64 type is added with the required
>> __timespec64 time definition.  Both non-LFS and LFS support were
>> done with an extra __NR_statx call plus a conversion to the new
>> __stat{64}_t64 type.  The statx call is done only for architectures
>> with support for 32-bit time_t ABI.
>>
>> Internally some extra routines to copy from/to struct stat{64}
>> to struct __stat{64} used on multiple implementations (stat, fstat,
>> lstat, and fstatat) are added on a extra file (stat_t64_cp.c).  Aslo
>> some extra routines to copy from statx to __stat{64} is added on
>> statx_cp.c.
>>
>> Checked with a build for all affected ABIs. I also checked on x86_64,
>> i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and s390x.
> 
> When do you plan to pull this patch set to -master?
> Those patches have been available for review on the mailing list for
> more than two months now.

Hi Lukasz, thanks to remind me. I will rebase against master and run
some regressions tests against some platforms and push it.
  
Adhemerval Zanella Oct. 7, 2020, 2:25 p.m. UTC | #8
On 07/10/2020 09:52, Adhemerval Zanella wrote:
> 
> 
> On 06/10/2020 06:48, Lukasz Majewski wrote:
>> Hi Adhemerval,
>>
>>> A new struct __stat{64}_t64 type is added with the required
>>> __timespec64 time definition.  Both non-LFS and LFS support were
>>> done with an extra __NR_statx call plus a conversion to the new
>>> __stat{64}_t64 type.  The statx call is done only for architectures
>>> with support for 32-bit time_t ABI.
>>>
>>> Internally some extra routines to copy from/to struct stat{64}
>>> to struct __stat{64} used on multiple implementations (stat, fstat,
>>> lstat, and fstatat) are added on a extra file (stat_t64_cp.c).  Aslo
>>> some extra routines to copy from statx to __stat{64} is added on
>>> statx_cp.c.
>>>
>>> Checked with a build for all affected ABIs. I also checked on x86_64,
>>> i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and s390x.
>>
>> When do you plan to pull this patch set to -master?
>> Those patches have been available for review on the mailing list for
>> more than two months now.
> 
> Hi Lukasz, thanks to remind me. I will rebase against master and run
> some regressions tests against some platforms and push it.
> 

One required change with the rebase is adapt the riscv32 ABI to exclude 
the __{f,l}xstat{at} symbol and replace with proper {f,l}stat ones. 
It is possible because the new ABI was added on current development
branch, however one minor inconvenient is the toolchain need to be
rebuild with a updated glibc branch to avoid linking failures with
libstd++ (which uses __{f,l}xstat{at}).
  
Lukasz Majewski Oct. 7, 2020, 8:20 p.m. UTC | #9
Hi Adhemerval,

> On 07/10/2020 09:52, Adhemerval Zanella wrote:
> > 
> > 
> > On 06/10/2020 06:48, Lukasz Majewski wrote:  
> >> Hi Adhemerval,
> >>  
> >>> A new struct __stat{64}_t64 type is added with the required
> >>> __timespec64 time definition.  Both non-LFS and LFS support were
> >>> done with an extra __NR_statx call plus a conversion to the new
> >>> __stat{64}_t64 type.  The statx call is done only for
> >>> architectures with support for 32-bit time_t ABI.
> >>>
> >>> Internally some extra routines to copy from/to struct stat{64}
> >>> to struct __stat{64} used on multiple implementations (stat,
> >>> fstat, lstat, and fstatat) are added on a extra file
> >>> (stat_t64_cp.c).  Aslo some extra routines to copy from statx to
> >>> __stat{64} is added on statx_cp.c.
> >>>
> >>> Checked with a build for all affected ABIs. I also checked on
> >>> x86_64, i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and
> >>> s390x.  
> >>
> >> When do you plan to pull this patch set to -master?
> >> Those patches have been available for review on the mailing list
> >> for more than two months now.  
> > 
> > Hi Lukasz, thanks to remind me. I will rebase against master and run
> > some regressions tests against some platforms and push it.
> >   
> 
> One required change with the rebase is adapt the riscv32 ABI to
> exclude the __{f,l}xstat{at} symbol and replace with proper {f,l}stat
> ones. It is possible because the new ABI was added on current
> development branch, however one minor inconvenient is the toolchain
> need to be rebuild with a updated glibc branch to avoid linking
> failures with libstd++ (which uses __{f,l}xstat{at}).
> 

Does it mean that we would need to run glibc-many-builds with
{checkout,host-libraries,compilers} after we update the branch?

We would need to rebuild the toolchain anyway for rv32 anyway?


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
  
Adhemerval Zanella Oct. 7, 2020, 9:01 p.m. UTC | #10
On 07/10/2020 17:20, Lukasz Majewski wrote:
> Hi Adhemerval,
> 
>> On 07/10/2020 09:52, Adhemerval Zanella wrote:
>>>
>>>
>>> On 06/10/2020 06:48, Lukasz Majewski wrote:  
>>>> Hi Adhemerval,
>>>>  
>>>>> A new struct __stat{64}_t64 type is added with the required
>>>>> __timespec64 time definition.  Both non-LFS and LFS support were
>>>>> done with an extra __NR_statx call plus a conversion to the new
>>>>> __stat{64}_t64 type.  The statx call is done only for
>>>>> architectures with support for 32-bit time_t ABI.
>>>>>
>>>>> Internally some extra routines to copy from/to struct stat{64}
>>>>> to struct __stat{64} used on multiple implementations (stat,
>>>>> fstat, lstat, and fstatat) are added on a extra file
>>>>> (stat_t64_cp.c).  Aslo some extra routines to copy from statx to
>>>>> __stat{64} is added on statx_cp.c.
>>>>>
>>>>> Checked with a build for all affected ABIs. I also checked on
>>>>> x86_64, i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and
>>>>> s390x.  
>>>>
>>>> When do you plan to pull this patch set to -master?
>>>> Those patches have been available for review on the mailing list
>>>> for more than two months now.  
>>>
>>> Hi Lukasz, thanks to remind me. I will rebase against master and run
>>> some regressions tests against some platforms and push it.
>>>   
>>
>> One required change with the rebase is adapt the riscv32 ABI to
>> exclude the __{f,l}xstat{at} symbol and replace with proper {f,l}stat
>> ones. It is possible because the new ABI was added on current
>> development branch, however one minor inconvenient is the toolchain
>> need to be rebuild with a updated glibc branch to avoid linking
>> failures with libstd++ (which uses __{f,l}xstat{at}).
>>
> 
> Does it mean that we would need to run glibc-many-builds with
> {checkout,host-libraries,compilers} after we update the branch?
> 
> We would need to rebuild the toolchain anyway for rv32 anyway?

Yes, at least 'checkout' to get the most recent glibc and 'compilers'
to build a proper toolchain with the expect baseline ABI.
  
Adhemerval Zanella Oct. 7, 2020, 9:07 p.m. UTC | #11
On 07/10/2020 11:25, Adhemerval Zanella wrote:
> 
> 
> On 07/10/2020 09:52, Adhemerval Zanella wrote:
>>
>>
>> On 06/10/2020 06:48, Lukasz Majewski wrote:
>>> Hi Adhemerval,
>>>
>>>> A new struct __stat{64}_t64 type is added with the required
>>>> __timespec64 time definition.  Both non-LFS and LFS support were
>>>> done with an extra __NR_statx call plus a conversion to the new
>>>> __stat{64}_t64 type.  The statx call is done only for architectures
>>>> with support for 32-bit time_t ABI.
>>>>
>>>> Internally some extra routines to copy from/to struct stat{64}
>>>> to struct __stat{64} used on multiple implementations (stat, fstat,
>>>> lstat, and fstatat) are added on a extra file (stat_t64_cp.c).  Aslo
>>>> some extra routines to copy from statx to __stat{64} is added on
>>>> statx_cp.c.
>>>>
>>>> Checked with a build for all affected ABIs. I also checked on x86_64,
>>>> i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and s390x.
>>>
>>> When do you plan to pull this patch set to -master?
>>> Those patches have been available for review on the mailing list for
>>> more than two months now.
>>
>> Hi Lukasz, thanks to remind me. I will rebase against master and run
>> some regressions tests against some platforms and push it.
>>
> 
> One required change with the rebase is adapt the riscv32 ABI to exclude 
> the __{f,l}xstat{at} symbol and replace with proper {f,l}stat ones. 
> It is possible because the new ABI was added on current development
> branch, however one minor inconvenient is the toolchain need to be
> rebuild with a updated glibc branch to avoid linking failures with
> libstd++ (which uses __{f,l}xstat{at}).
> 

Ok, I have ran the testsuite on x86_64, x32, i686, aarch64, armhf,
powerpc, powerpc64, powerpc64le, sparc64, sparcv9, s390x, and s390
without regression. I will just finish the testing on mips, mips64,
and alpha since they require some specific implementations.
  
Lukasz Majewski Oct. 8, 2020, 7:57 a.m. UTC | #12
Hi Adhemerval,

> On 07/10/2020 11:25, Adhemerval Zanella wrote:
> > 
> > 
> > On 07/10/2020 09:52, Adhemerval Zanella wrote:  
> >>
> >>
> >> On 06/10/2020 06:48, Lukasz Majewski wrote:  
> >>> Hi Adhemerval,
> >>>  
> >>>> A new struct __stat{64}_t64 type is added with the required
> >>>> __timespec64 time definition.  Both non-LFS and LFS support were
> >>>> done with an extra __NR_statx call plus a conversion to the new
> >>>> __stat{64}_t64 type.  The statx call is done only for
> >>>> architectures with support for 32-bit time_t ABI.
> >>>>
> >>>> Internally some extra routines to copy from/to struct stat{64}
> >>>> to struct __stat{64} used on multiple implementations (stat,
> >>>> fstat, lstat, and fstatat) are added on a extra file
> >>>> (stat_t64_cp.c).  Aslo some extra routines to copy from statx to
> >>>> __stat{64} is added on statx_cp.c.
> >>>>
> >>>> Checked with a build for all affected ABIs. I also checked on
> >>>> x86_64, i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and
> >>>> s390x.  
> >>>
> >>> When do you plan to pull this patch set to -master?
> >>> Those patches have been available for review on the mailing list
> >>> for more than two months now.  
> >>
> >> Hi Lukasz, thanks to remind me. I will rebase against master and
> >> run some regressions tests against some platforms and push it.
> >>  
> > 
> > One required change with the rebase is adapt the riscv32 ABI to
> > exclude the __{f,l}xstat{at} symbol and replace with proper
> > {f,l}stat ones. It is possible because the new ABI was added on
> > current development branch, however one minor inconvenient is the
> > toolchain need to be rebuild with a updated glibc branch to avoid
> > linking failures with libstd++ (which uses __{f,l}xstat{at}).
> >   
> 
> Ok, I have ran the testsuite on x86_64, x32, i686, aarch64, armhf,
> powerpc, powerpc64, powerpc64le, sparc64, sparcv9, s390x, and s390
> without regression. I will just finish the testing on mips, mips64,
> and alpha since they require some specific implementations.
> 

That would be a huge step forward.

According to list in the following commit message:
https://github.com/lmajewski/y2038_glibc/commit/73215359e184d96b415e87b585a4396b5bd0936c

Then I will send an RFC for enabling support for 64 bit time on
eligible architectures.

Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
  
Adhemerval Zanella Oct. 9, 2020, 2:05 p.m. UTC | #13
On 08/10/2020 04:57, Lukasz Majewski wrote:
> Hi Adhemerval,
> 
>> On 07/10/2020 11:25, Adhemerval Zanella wrote:
>>>
>>>
>>> On 07/10/2020 09:52, Adhemerval Zanella wrote:  
>>>>
>>>>
>>>> On 06/10/2020 06:48, Lukasz Majewski wrote:  
>>>>> Hi Adhemerval,
>>>>>  
>>>>>> A new struct __stat{64}_t64 type is added with the required
>>>>>> __timespec64 time definition.  Both non-LFS and LFS support were
>>>>>> done with an extra __NR_statx call plus a conversion to the new
>>>>>> __stat{64}_t64 type.  The statx call is done only for
>>>>>> architectures with support for 32-bit time_t ABI.
>>>>>>
>>>>>> Internally some extra routines to copy from/to struct stat{64}
>>>>>> to struct __stat{64} used on multiple implementations (stat,
>>>>>> fstat, lstat, and fstatat) are added on a extra file
>>>>>> (stat_t64_cp.c).  Aslo some extra routines to copy from statx to
>>>>>> __stat{64} is added on statx_cp.c.
>>>>>>
>>>>>> Checked with a build for all affected ABIs. I also checked on
>>>>>> x86_64, i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and
>>>>>> s390x.  
>>>>>
>>>>> When do you plan to pull this patch set to -master?
>>>>> Those patches have been available for review on the mailing list
>>>>> for more than two months now.  
>>>>
>>>> Hi Lukasz, thanks to remind me. I will rebase against master and
>>>> run some regressions tests against some platforms and push it.
>>>>  
>>>
>>> One required change with the rebase is adapt the riscv32 ABI to
>>> exclude the __{f,l}xstat{at} symbol and replace with proper
>>> {f,l}stat ones. It is possible because the new ABI was added on
>>> current development branch, however one minor inconvenient is the
>>> toolchain need to be rebuild with a updated glibc branch to avoid
>>> linking failures with libstd++ (which uses __{f,l}xstat{at}).
>>>   
>>
>> Ok, I have ran the testsuite on x86_64, x32, i686, aarch64, armhf,
>> powerpc, powerpc64, powerpc64le, sparc64, sparcv9, s390x, and s390
>> without regression. I will just finish the testing on mips, mips64,
>> and alpha since they require some specific implementations.
>>
> 
> That would be a huge step forward.
> 
> According to list in the following commit message:
> https://github.com/lmajewski/y2038_glibc/commit/73215359e184d96b415e87b585a4396b5bd0936c

The mips testing caught an issue on where the "linux: Disentangle 
fstatat from fxstatat" patch uses INTERNAL_SYSCALL_CALL where
it should use INLINE_SYSCALL_CALL (which sets the errno).  I have
fixed and this only affects mips, so my testing should cover all
the affects architectures (I got access to a ia64 machine again
and I will run a regression test once I commit this to master).

> 
> Then I will send an RFC for enabling support for 64 bit time on
> eligible architectures.

There still some missing implementations I have on my local tree:

 1. wait3: it is a straightforward fix since it just calls __wait4_time64.
 2. ftime: we need to move it to a compatibility symbol, so there will
    be no need to add a time64 variant to support the deprecated symbol.
 3. futimesat: we need to remove the implementation on generic folder
    and handle UTIME_NOW and UTIME_OMIT correctly.
 4. recvvmsg/recvmsg: we need to handle ancillary data. I recently send
    patch that tries to handle it [1] [2] [3]. It is more in a RFC and
    I don't think it is strictly necessary.
 5. utmp/utmpx/lastlog: I also sent a fix to handle the 64-bit support
    on this [4]

I will send 1. 2. 3., since they are the easiest one to review.

[1] https://sourceware.org/pipermail/libc-alpha/2020-September/117484.html
[2] https://sourceware.org/pipermail/libc-alpha/2020-September/117485.html
[3] https://sourceware.org/pipermail/libc-alpha/2020-September/117486.html
[4] https://sourceware.org/pipermail/libc-alpha/2020-August/116850.html
  
Lukasz Majewski Oct. 9, 2020, 3:39 p.m. UTC | #14
Hi Adhemerval,

> On 08/10/2020 04:57, Lukasz Majewski wrote:
> > Hi Adhemerval,
> >   
> >> On 07/10/2020 11:25, Adhemerval Zanella wrote:  
> >>>
> >>>
> >>> On 07/10/2020 09:52, Adhemerval Zanella wrote:    
> >>>>
> >>>>
> >>>> On 06/10/2020 06:48, Lukasz Majewski wrote:    
> >>>>> Hi Adhemerval,
> >>>>>    
> >>>>>> A new struct __stat{64}_t64 type is added with the required
> >>>>>> __timespec64 time definition.  Both non-LFS and LFS support
> >>>>>> were done with an extra __NR_statx call plus a conversion to
> >>>>>> the new __stat{64}_t64 type.  The statx call is done only for
> >>>>>> architectures with support for 32-bit time_t ABI.
> >>>>>>
> >>>>>> Internally some extra routines to copy from/to struct stat{64}
> >>>>>> to struct __stat{64} used on multiple implementations (stat,
> >>>>>> fstat, lstat, and fstatat) are added on a extra file
> >>>>>> (stat_t64_cp.c).  Aslo some extra routines to copy from statx
> >>>>>> to __stat{64} is added on statx_cp.c.
> >>>>>>
> >>>>>> Checked with a build for all affected ABIs. I also checked on
> >>>>>> x86_64, i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and
> >>>>>> s390x.    
> >>>>>
> >>>>> When do you plan to pull this patch set to -master?
> >>>>> Those patches have been available for review on the mailing list
> >>>>> for more than two months now.    
> >>>>
> >>>> Hi Lukasz, thanks to remind me. I will rebase against master and
> >>>> run some regressions tests against some platforms and push it.
> >>>>    
> >>>
> >>> One required change with the rebase is adapt the riscv32 ABI to
> >>> exclude the __{f,l}xstat{at} symbol and replace with proper
> >>> {f,l}stat ones. It is possible because the new ABI was added on
> >>> current development branch, however one minor inconvenient is the
> >>> toolchain need to be rebuild with a updated glibc branch to avoid
> >>> linking failures with libstd++ (which uses __{f,l}xstat{at}).
> >>>     
> >>
> >> Ok, I have ran the testsuite on x86_64, x32, i686, aarch64, armhf,
> >> powerpc, powerpc64, powerpc64le, sparc64, sparcv9, s390x, and s390
> >> without regression. I will just finish the testing on mips, mips64,
> >> and alpha since they require some specific implementations.
> >>  
> > 
> > That would be a huge step forward.
> > 
> > According to list in the following commit message:
> > https://github.com/lmajewski/y2038_glibc/commit/73215359e184d96b415e87b585a4396b5bd0936c
> >  
> 
> The mips testing caught an issue on where the "linux: Disentangle 
> fstatat from fxstatat" patch uses INTERNAL_SYSCALL_CALL where
> it should use INLINE_SYSCALL_CALL (which sets the errno).  I have
> fixed and this only affects mips, so my testing should cover all
> the affects architectures (I got access to a ia64 machine again
> and I will run a regression test once I commit this to master).

Ok. Does it mean that we can expect those patches being pull to -master
soon?

> 
> > 
> > Then I will send an RFC for enabling support for 64 bit time on
> > eligible architectures.  
> 
> There still some missing implementations I have on my local tree:
> 
>  1. wait3: it is a straightforward fix since it just calls
> __wait4_time64. 

Ok.

>2. ftime: we need to move it to a compatibility
> symbol, so there will be no need to add a time64 variant to support
> the deprecated symbol.

IIRC, such deprecation patch for ftime was already pulled to master:

SHA1: 2b5fea833bcd0f651579afd16ed7842770ecbae1
"Consolidate and deprecate ftime"

From the commit description - it shall be removed by Y2038 :-)

> 3. futimesat: we need to remove the
> implementation on generic folder and handle UTIME_NOW and UTIME_OMIT
> correctly.

Ok.

> 4. recvvmsg/recvmsg: we need to handle ancillary data. I
> recently send patch that tries to handle it [1] [2] [3]. It is more
> in a RFC and I don't think it is strictly necessary.

Ok.

>  5. utmp/utmpx/lastlog: I also sent a fix to handle the 64-bit support
>     on this [4]

I saw conversion patches in your y2038 tree (sourceware/azanella/y2038)
on top of the stat conversion work, so I guess that it will be next in
the queue.

> 
> I will send 1. 2. 3., since they are the easiest one to review.

Ok. Thanks :-)

> 
> [1]
> https://sourceware.org/pipermail/libc-alpha/2020-September/117484.html
> [2]
> https://sourceware.org/pipermail/libc-alpha/2020-September/117485.html
> [3]
> https://sourceware.org/pipermail/libc-alpha/2020-September/117486.html
> [4]
> https://sourceware.org/pipermail/libc-alpha/2020-August/116850.html
> 




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
  
Adhemerval Zanella Oct. 9, 2020, 8:06 p.m. UTC | #15
On 09/10/2020 12:39, Lukasz Majewski wrote:
> 
> Ok. Does it mean that we can expect those patches being pull to -master
> soon?
> 

Yes, I just push it upstream.

>>
>>>
>>> Then I will send an RFC for enabling support for 64 bit time on
>>> eligible architectures.  
>>
>> There still some missing implementations I have on my local tree:
>>
>>  1. wait3: it is a straightforward fix since it just calls
>> __wait4_time64. 
> 
> Ok.
> 
>> 2. ftime: we need to move it to a compatibility
>> symbol, so there will be no need to add a time64 variant to support
>> the deprecated symbol.
> 
> IIRC, such deprecation patch for ftime was already pulled to master:
> 
> SHA1: 2b5fea833bcd0f651579afd16ed7842770ecbae1
> "Consolidate and deprecate ftime"
> 
> From the commit description - it shall be removed by Y2038 :-)

This patch just make the prototype deprecated, it is still exported on
all architecture and built for newer ABIs (riscv32 for instance).
The idea of my patch is move it to a compat symbol only, meaning that
it won't be available to binaries build against glibc 2.33 and new
ABIs won't provide it (which will be the case for riscv32). 

> 
>> 3. futimesat: we need to remove the
>> implementation on generic folder and handle UTIME_NOW and UTIME_OMIT
>> correctly.
> 
> Ok.
> 
>> 4. recvvmsg/recvmsg: we need to handle ancillary data. I
>> recently send patch that tries to handle it [1] [2] [3]. It is more
>> in a RFC and I don't think it is strictly necessary.
> 
> Ok.
> 
>>  5. utmp/utmpx/lastlog: I also sent a fix to handle the 64-bit support
>>     on this [4]
> 
> I saw conversion patches in your y2038 tree (sourceware/azanella/y2038)
> on top of the stat conversion work, so I guess that it will be next in
> the queue.

I will rebase my y2038 changes and update my tree.
  
Lukasz Majewski Oct. 13, 2020, 1:58 p.m. UTC | #16
Hi Adhemerval,

> On 07/10/2020 09:52, Adhemerval Zanella wrote:
> > 
> > 
> > On 06/10/2020 06:48, Lukasz Majewski wrote:  
> >> Hi Adhemerval,
> >>  
> >>> A new struct __stat{64}_t64 type is added with the required
> >>> __timespec64 time definition.  Both non-LFS and LFS support were
> >>> done with an extra __NR_statx call plus a conversion to the new
> >>> __stat{64}_t64 type.  The statx call is done only for
> >>> architectures with support for 32-bit time_t ABI.
> >>>
> >>> Internally some extra routines to copy from/to struct stat{64}
> >>> to struct __stat{64} used on multiple implementations (stat,
> >>> fstat, lstat, and fstatat) are added on a extra file
> >>> (stat_t64_cp.c).  Aslo some extra routines to copy from statx to
> >>> __stat{64} is added on statx_cp.c.
> >>>
> >>> Checked with a build for all affected ABIs. I also checked on
> >>> x86_64, i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and
> >>> s390x.  
> >>
> >> When do you plan to pull this patch set to -master?
> >> Those patches have been available for review on the mailing list
> >> for more than two months now.  
> > 
> > Hi Lukasz, thanks to remind me. I will rebase against master and run
> > some regressions tests against some platforms and push it.
> >   
> 
> One required change with the rebase is adapt the riscv32 ABI to
> exclude the __{f,l}xstat{at} symbol and replace with proper {f,l}stat
> ones. It is possible because the new ABI was added on current
> development branch, however one minor inconvenient is the toolchain
> need to be rebuild with a updated glibc branch to avoid linking
> failures with libstd++ (which uses __{f,l}xstat{at}).
> 

I'm not sure if this is related, but on my ARMv7 (32 bit) sandbox there
is an issue with fstat accesses to files.

When I try to run a program build against newest glibc (installed in
/opt/lib) I do see issues with {f}stat on other libraries (e.g.
/opt/lib/librt.so). To be more specific I do experience the EOVERFLOW
error:

error while loading shared libraries: librt.so.1: cannot stat shared
object: Error 75

The "base" glibc is 2.28 (installed in /lib). The glibc under test is
the newest master installed in /opt/lib.

I'm now investigating this issue.


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
  
Adhemerval Zanella Oct. 13, 2020, 2:18 p.m. UTC | #17
On 13/10/2020 10:58, Lukasz Majewski wrote:
> Hi Adhemerval,
> 
>> On 07/10/2020 09:52, Adhemerval Zanella wrote:
>>>
>>>
>>> On 06/10/2020 06:48, Lukasz Majewski wrote:  
>>>> Hi Adhemerval,
>>>>  
>>>>> A new struct __stat{64}_t64 type is added with the required
>>>>> __timespec64 time definition.  Both non-LFS and LFS support were
>>>>> done with an extra __NR_statx call plus a conversion to the new
>>>>> __stat{64}_t64 type.  The statx call is done only for
>>>>> architectures with support for 32-bit time_t ABI.
>>>>>
>>>>> Internally some extra routines to copy from/to struct stat{64}
>>>>> to struct __stat{64} used on multiple implementations (stat,
>>>>> fstat, lstat, and fstatat) are added on a extra file
>>>>> (stat_t64_cp.c).  Aslo some extra routines to copy from statx to
>>>>> __stat{64} is added on statx_cp.c.
>>>>>
>>>>> Checked with a build for all affected ABIs. I also checked on
>>>>> x86_64, i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and
>>>>> s390x.  
>>>>
>>>> When do you plan to pull this patch set to -master?
>>>> Those patches have been available for review on the mailing list
>>>> for more than two months now.  
>>>
>>> Hi Lukasz, thanks to remind me. I will rebase against master and run
>>> some regressions tests against some platforms and push it.
>>>   
>>
>> One required change with the rebase is adapt the riscv32 ABI to
>> exclude the __{f,l}xstat{at} symbol and replace with proper {f,l}stat
>> ones. It is possible because the new ABI was added on current
>> development branch, however one minor inconvenient is the toolchain
>> need to be rebuild with a updated glibc branch to avoid linking
>> failures with libstd++ (which uses __{f,l}xstat{at}).
>>
> 
> I'm not sure if this is related, but on my ARMv7 (32 bit) sandbox there
> is an issue with fstat accesses to files.
> 
> When I try to run a program build against newest glibc (installed in
> /opt/lib) I do see issues with {f}stat on other libraries (e.g.
> /opt/lib/librt.so). To be more specific I do experience the EOVERFLOW
> error:
> 
> error while loading shared libraries: librt.so.1: cannot stat shared
> object: Error 75
> 
> The "base" glibc is 2.28 (installed in /lib). The glibc under test is
> the newest master installed in /opt/lib.
> 
> I'm now investigating this issue.

I am not sure what it might be based on these information, could you
provide a strace so we can pinpoint what might the issue?  

The arm-linux-gnueabihf testing I did was on a aarch64 kernel (4.12.13).
Besides the make check without regression, I could run system binaries 
with ./testrun.sh.

I will check on a different kernel/system with a 32-bit kernel.
  
H.J. Lu Oct. 13, 2020, 2:23 p.m. UTC | #18
On Tue, Oct 13, 2020 at 7:18 AM Adhemerval Zanella via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
>
>
> On 13/10/2020 10:58, Lukasz Majewski wrote:
> > Hi Adhemerval,
> >
> >> On 07/10/2020 09:52, Adhemerval Zanella wrote:
> >>>
> >>>
> >>> On 06/10/2020 06:48, Lukasz Majewski wrote:
> >>>> Hi Adhemerval,
> >>>>
> >>>>> A new struct __stat{64}_t64 type is added with the required
> >>>>> __timespec64 time definition.  Both non-LFS and LFS support were
> >>>>> done with an extra __NR_statx call plus a conversion to the new
> >>>>> __stat{64}_t64 type.  The statx call is done only for
> >>>>> architectures with support for 32-bit time_t ABI.
> >>>>>
> >>>>> Internally some extra routines to copy from/to struct stat{64}
> >>>>> to struct __stat{64} used on multiple implementations (stat,
> >>>>> fstat, lstat, and fstatat) are added on a extra file
> >>>>> (stat_t64_cp.c).  Aslo some extra routines to copy from statx to
> >>>>> __stat{64} is added on statx_cp.c.
> >>>>>
> >>>>> Checked with a build for all affected ABIs. I also checked on
> >>>>> x86_64, i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and
> >>>>> s390x.
> >>>>
> >>>> When do you plan to pull this patch set to -master?
> >>>> Those patches have been available for review on the mailing list
> >>>> for more than two months now.
> >>>
> >>> Hi Lukasz, thanks to remind me. I will rebase against master and run
> >>> some regressions tests against some platforms and push it.
> >>>
> >>
> >> One required change with the rebase is adapt the riscv32 ABI to
> >> exclude the __{f,l}xstat{at} symbol and replace with proper {f,l}stat
> >> ones. It is possible because the new ABI was added on current
> >> development branch, however one minor inconvenient is the toolchain
> >> need to be rebuild with a updated glibc branch to avoid linking
> >> failures with libstd++ (which uses __{f,l}xstat{at}).
> >>
> >
> > I'm not sure if this is related, but on my ARMv7 (32 bit) sandbox there
> > is an issue with fstat accesses to files.
> >
> > When I try to run a program build against newest glibc (installed in
> > /opt/lib) I do see issues with {f}stat on other libraries (e.g.
> > /opt/lib/librt.so). To be more specific I do experience the EOVERFLOW
> > error:
> >
> > error while loading shared libraries: librt.so.1: cannot stat shared
> > object: Error 75
> >
> > The "base" glibc is 2.28 (installed in /lib). The glibc under test is
> > the newest master installed in /opt/lib.
> >
> > I'm now investigating this issue.
>
> I am not sure what it might be based on these information, could you
> provide a strace so we can pinpoint what might the issue?
>
> The arm-linux-gnueabihf testing I did was on a aarch64 kernel (4.12.13).
> Besides the make check without regression, I could run system binaries
> with ./testrun.sh.
>
> I will check on a different kernel/system with a 32-bit kernel.

FWIW, I got

FAIL: glibcs-armeb-linux-gnueabi-be8 check
FAIL: glibcs-armeb-linux-gnueabi check
FAIL: glibcs-armeb-linux-gnueabihf-be8 check
FAIL: glibcs-armeb-linux-gnueabihf check
FAIL: glibcs-m68k-linux-gnu-coldfire check
FAIL: glibcs-m68k-linux-gnu-coldfire-soft check
FAIL: glibcs-microblazeel-linux-gnu check
FAIL: glibcs-mipsel-linux-gnu-nan2008-soft check
FAIL: glibcs-mipsel-linux-gnu-soft check
FAIL: glibcs-mips-linux-gnu-nan2008-soft check
FAIL: glibcs-mips-linux-gnu-soft check
FAIL: glibcs-powerpc-linux-gnu-soft check
FAIL: glibcs-riscv32-linux-gnu-rv32imac-ilp32 build
FAIL: glibcs-riscv32-linux-gnu-rv32imafdc-ilp32 build
FAIL: glibcs-riscv32-linux-gnu-rv32imafdc-ilp32d build
FAIL: glibcs-sh3eb-linux-gnu check
FAIL: glibcs-sh4eb-linux-gnu check
FAIL: glibcs-sh4eb-linux-gnu-soft check
UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imac-ilp32 check
UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imac-ilp32 install
UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imac-ilp32 mkdir-lib
UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imafdc-ilp32 check
UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imafdc-ilp32d check
UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imafdc-ilp32d install
UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imafdc-ilp32d mkdir-lib
UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imafdc-ilp32 install
UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imafdc-ilp32 mkdir-lib
  
Adhemerval Zanella Oct. 13, 2020, 2:27 p.m. UTC | #19
On 13/10/2020 11:23, H.J. Lu wrote:
> On Tue, Oct 13, 2020 at 7:18 AM Adhemerval Zanella via Libc-alpha
> <libc-alpha@sourceware.org> wrote:
>>
>>
>>
>> On 13/10/2020 10:58, Lukasz Majewski wrote:
>>> Hi Adhemerval,
>>>
>>>> On 07/10/2020 09:52, Adhemerval Zanella wrote:
>>>>>
>>>>>
>>>>> On 06/10/2020 06:48, Lukasz Majewski wrote:
>>>>>> Hi Adhemerval,
>>>>>>
>>>>>>> A new struct __stat{64}_t64 type is added with the required
>>>>>>> __timespec64 time definition.  Both non-LFS and LFS support were
>>>>>>> done with an extra __NR_statx call plus a conversion to the new
>>>>>>> __stat{64}_t64 type.  The statx call is done only for
>>>>>>> architectures with support for 32-bit time_t ABI.
>>>>>>>
>>>>>>> Internally some extra routines to copy from/to struct stat{64}
>>>>>>> to struct __stat{64} used on multiple implementations (stat,
>>>>>>> fstat, lstat, and fstatat) are added on a extra file
>>>>>>> (stat_t64_cp.c).  Aslo some extra routines to copy from statx to
>>>>>>> __stat{64} is added on statx_cp.c.
>>>>>>>
>>>>>>> Checked with a build for all affected ABIs. I also checked on
>>>>>>> x86_64, i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and
>>>>>>> s390x.
>>>>>>
>>>>>> When do you plan to pull this patch set to -master?
>>>>>> Those patches have been available for review on the mailing list
>>>>>> for more than two months now.
>>>>>
>>>>> Hi Lukasz, thanks to remind me. I will rebase against master and run
>>>>> some regressions tests against some platforms and push it.
>>>>>
>>>>
>>>> One required change with the rebase is adapt the riscv32 ABI to
>>>> exclude the __{f,l}xstat{at} symbol and replace with proper {f,l}stat
>>>> ones. It is possible because the new ABI was added on current
>>>> development branch, however one minor inconvenient is the toolchain
>>>> need to be rebuild with a updated glibc branch to avoid linking
>>>> failures with libstd++ (which uses __{f,l}xstat{at}).
>>>>
>>>
>>> I'm not sure if this is related, but on my ARMv7 (32 bit) sandbox there
>>> is an issue with fstat accesses to files.
>>>
>>> When I try to run a program build against newest glibc (installed in
>>> /opt/lib) I do see issues with {f}stat on other libraries (e.g.
>>> /opt/lib/librt.so). To be more specific I do experience the EOVERFLOW
>>> error:
>>>
>>> error while loading shared libraries: librt.so.1: cannot stat shared
>>> object: Error 75
>>>
>>> The "base" glibc is 2.28 (installed in /lib). The glibc under test is
>>> the newest master installed in /opt/lib.
>>>
>>> I'm now investigating this issue.
>>
>> I am not sure what it might be based on these information, could you
>> provide a strace so we can pinpoint what might the issue?
>>
>> The arm-linux-gnueabihf testing I did was on a aarch64 kernel (4.12.13).
>> Besides the make check without regression, I could run system binaries
>> with ./testrun.sh.
>>
>> I will check on a different kernel/system with a 32-bit kernel.
> 
> FWIW, I got
> 
> FAIL: glibcs-armeb-linux-gnueabi-be8 check
> FAIL: glibcs-armeb-linux-gnueabi check
> FAIL: glibcs-armeb-linux-gnueabihf-be8 check
> FAIL: glibcs-armeb-linux-gnueabihf check
> FAIL: glibcs-m68k-linux-gnu-coldfire check
> FAIL: glibcs-m68k-linux-gnu-coldfire-soft check
> FAIL: glibcs-microblazeel-linux-gnu check
> FAIL: glibcs-mipsel-linux-gnu-nan2008-soft check
> FAIL: glibcs-mipsel-linux-gnu-soft check
> FAIL: glibcs-mips-linux-gnu-nan2008-soft check
> FAIL: glibcs-mips-linux-gnu-soft check
> FAIL: glibcs-powerpc-linux-gnu-soft check
> FAIL: glibcs-riscv32-linux-gnu-rv32imac-ilp32 build
> FAIL: glibcs-riscv32-linux-gnu-rv32imafdc-ilp32 build
> FAIL: glibcs-riscv32-linux-gnu-rv32imafdc-ilp32d build
> FAIL: glibcs-sh3eb-linux-gnu check
> FAIL: glibcs-sh4eb-linux-gnu check
> FAIL: glibcs-sh4eb-linux-gnu-soft check

Joseph has raised this earlier, I just pushed a fix to update
the libc.abilist (880a12e96df8b330350f565d93677bccf4237e1d).

> UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imac-ilp32 check
> UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imac-ilp32 install
> UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imac-ilp32 mkdir-lib
> UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imafdc-ilp32 check
> UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imafdc-ilp32d check
> UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imafdc-ilp32d install
> UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imafdc-ilp32d mkdir-lib
> UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imafdc-ilp32 install
> UNRESOLVED: glibcs-riscv32-linux-gnu-rv32imafdc-ilp32 mkdir-lib

Since this moved the __{f,l}xstat{at}{64} symbols to compatibility
ones and made it the {f,l}stat{at}{64} the ones exported by libc,
it requires to rebuild the riscv32 toolchain (since libstdc++.so
is linked against the __xstat symbols).
  
Adhemerval Zanella Oct. 13, 2020, 6:14 p.m. UTC | #20
On 13/10/2020 11:18, Adhemerval Zanella wrote:
> 
> 
> On 13/10/2020 10:58, Lukasz Majewski wrote:
>> Hi Adhemerval,
>>
>>> On 07/10/2020 09:52, Adhemerval Zanella wrote:
>>>>
>>>>
>>>> On 06/10/2020 06:48, Lukasz Majewski wrote:  
>>>>> Hi Adhemerval,
>>>>>  
>>>>>> A new struct __stat{64}_t64 type is added with the required
>>>>>> __timespec64 time definition.  Both non-LFS and LFS support were
>>>>>> done with an extra __NR_statx call plus a conversion to the new
>>>>>> __stat{64}_t64 type.  The statx call is done only for
>>>>>> architectures with support for 32-bit time_t ABI.
>>>>>>
>>>>>> Internally some extra routines to copy from/to struct stat{64}
>>>>>> to struct __stat{64} used on multiple implementations (stat,
>>>>>> fstat, lstat, and fstatat) are added on a extra file
>>>>>> (stat_t64_cp.c).  Aslo some extra routines to copy from statx to
>>>>>> __stat{64} is added on statx_cp.c.
>>>>>>
>>>>>> Checked with a build for all affected ABIs. I also checked on
>>>>>> x86_64, i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and
>>>>>> s390x.  
>>>>>
>>>>> When do you plan to pull this patch set to -master?
>>>>> Those patches have been available for review on the mailing list
>>>>> for more than two months now.  
>>>>
>>>> Hi Lukasz, thanks to remind me. I will rebase against master and run
>>>> some regressions tests against some platforms and push it.
>>>>   
>>>
>>> One required change with the rebase is adapt the riscv32 ABI to
>>> exclude the __{f,l}xstat{at} symbol and replace with proper {f,l}stat
>>> ones. It is possible because the new ABI was added on current
>>> development branch, however one minor inconvenient is the toolchain
>>> need to be rebuild with a updated glibc branch to avoid linking
>>> failures with libstd++ (which uses __{f,l}xstat{at}).
>>>
>>
>> I'm not sure if this is related, but on my ARMv7 (32 bit) sandbox there
>> is an issue with fstat accesses to files.
>>
>> When I try to run a program build against newest glibc (installed in
>> /opt/lib) I do see issues with {f}stat on other libraries (e.g.
>> /opt/lib/librt.so). To be more specific I do experience the EOVERFLOW
>> error:
>>
>> error while loading shared libraries: librt.so.1: cannot stat shared
>> object: Error 75
>>
>> The "base" glibc is 2.28 (installed in /lib). The glibc under test is
>> the newest master installed in /opt/lib.
>>
>> I'm now investigating this issue.
> 
> I am not sure what it might be based on these information, could you
> provide a strace so we can pinpoint what might the issue?  
> 
> The arm-linux-gnueabihf testing I did was on a aarch64 kernel (4.12.13).
> Besides the make check without regression, I could run system binaries 
> with ./testrun.sh.
> 
> I will check on a different kernel/system with a 32-bit kernel.

Ok, this change in fact triggered a very subtle issue at dl-load.c that
I saw in both arm-linux-gnueabihf system with a 32-bit kernel and on
mips-linux-gnu.

The issue is at:

elf/dl-load.c

1982       if (here_any && (err = errno) != ENOENT && err != EACCES)
1983         /* The file exists and is readable, but something went wrong.  */
1984         return -1;

And it is just triggered on system where {f,l}stat{at}{64} issues
__NR_statx and it fails with ENOSYS but later success with the system
stat* syscall.

This code here checks the errno value without checking whether the
previous function call that might change err actually has failed
(in this specific case the stat64 at line 1931). And this due how we 
currently implement the y2038 support with INLINE_SYSCALL_CALL 
(a function that succeeds is allowed to change errno and it simplifies 
the resulting y2038 support a bit).

In fact this check does not really make sense, since either 'fd' will
be different than '0' (meaning it has being opened) or the 'stat64'
at line 1931 failed and 'here_any' won't be set (the stat64 at line
1951 already explicit sets errno in failure case).  

Also, git history does not give much information on why it was added
at fist place.  So I think we just need to remove this extra check,
you can check if the following patch helps (I am running some
regression tests before sensing it upstream):

diff --git a/elf/dl-load.c b/elf/dl-load.c
index f3201e7c14..39ae43c6ce 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1878,7 +1878,6 @@ open_path (const char *name, size_t namelen, int mode,
       size_t cnt;
       char *edp;
       int here_any = 0;
-      int err;
 
       /* If we are debugging the search for libraries print the path
         now if it hasn't happened now.  */
@@ -1979,9 +1978,6 @@ open_path (const char *name, size_t namelen, int mode,
              return -1;
            }
        }
-      if (here_any && (err = errno) != ENOENT && err != EACCES)
-       /* The file exists and is readable, but something went wrong.  */
-       return -1;
 
       /* Remember whether we found anything.  */
       any |= here_any;
  
Lukasz Majewski Oct. 13, 2020, 9:20 p.m. UTC | #21
Hi Adhemerval,

> On 13/10/2020 11:18, Adhemerval Zanella wrote:
> > 
> > 
> > On 13/10/2020 10:58, Lukasz Majewski wrote:  
> >> Hi Adhemerval,
> >>  
> >>> On 07/10/2020 09:52, Adhemerval Zanella wrote:  
> >>>>
> >>>>
> >>>> On 06/10/2020 06:48, Lukasz Majewski wrote:    
> >>>>> Hi Adhemerval,
> >>>>>    
> >>>>>> A new struct __stat{64}_t64 type is added with the required
> >>>>>> __timespec64 time definition.  Both non-LFS and LFS support
> >>>>>> were done with an extra __NR_statx call plus a conversion to
> >>>>>> the new __stat{64}_t64 type.  The statx call is done only for
> >>>>>> architectures with support for 32-bit time_t ABI.
> >>>>>>
> >>>>>> Internally some extra routines to copy from/to struct stat{64}
> >>>>>> to struct __stat{64} used on multiple implementations (stat,
> >>>>>> fstat, lstat, and fstatat) are added on a extra file
> >>>>>> (stat_t64_cp.c).  Aslo some extra routines to copy from statx
> >>>>>> to __stat{64} is added on statx_cp.c.
> >>>>>>
> >>>>>> Checked with a build for all affected ABIs. I also checked on
> >>>>>> x86_64, i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and
> >>>>>> s390x.    
> >>>>>
> >>>>> When do you plan to pull this patch set to -master?
> >>>>> Those patches have been available for review on the mailing list
> >>>>> for more than two months now.    
> >>>>
> >>>> Hi Lukasz, thanks to remind me. I will rebase against master and
> >>>> run some regressions tests against some platforms and push it.
> >>>>     
> >>>
> >>> One required change with the rebase is adapt the riscv32 ABI to
> >>> exclude the __{f,l}xstat{at} symbol and replace with proper
> >>> {f,l}stat ones. It is possible because the new ABI was added on
> >>> current development branch, however one minor inconvenient is the
> >>> toolchain need to be rebuild with a updated glibc branch to avoid
> >>> linking failures with libstd++ (which uses __{f,l}xstat{at}).
> >>>  
> >>
> >> I'm not sure if this is related, but on my ARMv7 (32 bit) sandbox
> >> there is an issue with fstat accesses to files.
> >>
> >> When I try to run a program build against newest glibc (installed
> >> in /opt/lib) I do see issues with {f}stat on other libraries (e.g.
> >> /opt/lib/librt.so). To be more specific I do experience the
> >> EOVERFLOW error:
> >>
> >> error while loading shared libraries: librt.so.1: cannot stat
> >> shared object: Error 75
> >>
> >> The "base" glibc is 2.28 (installed in /lib). The glibc under test
> >> is the newest master installed in /opt/lib.
> >>
> >> I'm now investigating this issue.  
> > 
> > I am not sure what it might be based on these information, could you
> > provide a strace so we can pinpoint what might the issue?  
> > 
> > The arm-linux-gnueabihf testing I did was on a aarch64 kernel
> > (4.12.13). Besides the make check without regression, I could run
> > system binaries with ./testrun.sh.
> > 
> > I will check on a different kernel/system with a 32-bit kernel.  
> 
> Ok, this change in fact triggered a very subtle issue at dl-load.c
> that I saw in both arm-linux-gnueabihf system with a 32-bit kernel
> and on mips-linux-gnu.
> 
> The issue is at:
> 
> elf/dl-load.c
> 
> 1982       if (here_any && (err = errno) != ENOENT && err != EACCES)
> 1983         /* The file exists and is readable, but something went
> wrong.  */ 1984         return -1;
> 
> And it is just triggered on system where {f,l}stat{at}{64} issues
> __NR_statx and it fails with ENOSYS but later success with the system
> stat* syscall.
> 
> This code here checks the errno value without checking whether the
> previous function call that might change err actually has failed
> (in this specific case the stat64 at line 1931). And this due how we 
> currently implement the y2038 support with INLINE_SYSCALL_CALL 
> (a function that succeeds is allowed to change errno and it
> simplifies the resulting y2038 support a bit).
> 
> In fact this check does not really make sense, since either 'fd' will
> be different than '0' (meaning it has being opened) or the 'stat64'
> at line 1931 failed and 'here_any' won't be set (the stat64 at line
> 1951 already explicit sets errno in failure case).  
> 
> Also, git history does not give much information on why it was added
> at fist place.  So I think we just need to remove this extra check,
> you can check if the following patch helps (I am running some
> regression tests before sensing it upstream):
> 
> diff --git a/elf/dl-load.c b/elf/dl-load.c
> index f3201e7c14..39ae43c6ce 100644
> --- a/elf/dl-load.c
> +++ b/elf/dl-load.c
> @@ -1878,7 +1878,6 @@ open_path (const char *name, size_t namelen,
> int mode, size_t cnt;
>        char *edp;
>        int here_any = 0;
> -      int err;
>  
>        /* If we are debugging the search for libraries print the path
>          now if it hasn't happened now.  */
> @@ -1979,9 +1978,6 @@ open_path (const char *name, size_t namelen,
> int mode, return -1;
>             }
>         }
> -      if (here_any && (err = errno) != ENOENT && err != EACCES)
> -       /* The file exists and is readable, but something went wrong.
>  */
> -       return -1;
>  
>        /* Remember whether we found anything.  */
>        any |= here_any;
> 
> 

I've tested this patch and it doesn't fix my issue.

> 
> 




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
  
Lukasz Majewski Oct. 13, 2020, 9:40 p.m. UTC | #22
Hi Adhemerval,

> On 13/10/2020 10:58, Lukasz Majewski wrote:
> > Hi Adhemerval,
> >   
> >> On 07/10/2020 09:52, Adhemerval Zanella wrote:  
> >>>
> >>>
> >>> On 06/10/2020 06:48, Lukasz Majewski wrote:    
> >>>> Hi Adhemerval,
> >>>>    
> >>>>> A new struct __stat{64}_t64 type is added with the required
> >>>>> __timespec64 time definition.  Both non-LFS and LFS support were
> >>>>> done with an extra __NR_statx call plus a conversion to the new
> >>>>> __stat{64}_t64 type.  The statx call is done only for
> >>>>> architectures with support for 32-bit time_t ABI.
> >>>>>
> >>>>> Internally some extra routines to copy from/to struct stat{64}
> >>>>> to struct __stat{64} used on multiple implementations (stat,
> >>>>> fstat, lstat, and fstatat) are added on a extra file
> >>>>> (stat_t64_cp.c).  Aslo some extra routines to copy from statx to
> >>>>> __stat{64} is added on statx_cp.c.
> >>>>>
> >>>>> Checked with a build for all affected ABIs. I also checked on
> >>>>> x86_64, i686, powerpc, powerpc64le, sparcv9, sparc64, s390, and
> >>>>> s390x.    
> >>>>
> >>>> When do you plan to pull this patch set to -master?
> >>>> Those patches have been available for review on the mailing list
> >>>> for more than two months now.    
> >>>
> >>> Hi Lukasz, thanks to remind me. I will rebase against master and
> >>> run some regressions tests against some platforms and push it.
> >>>     
> >>
> >> One required change with the rebase is adapt the riscv32 ABI to
> >> exclude the __{f,l}xstat{at} symbol and replace with proper
> >> {f,l}stat ones. It is possible because the new ABI was added on
> >> current development branch, however one minor inconvenient is the
> >> toolchain need to be rebuild with a updated glibc branch to avoid
> >> linking failures with libstd++ (which uses __{f,l}xstat{at}).
> >>  
> > 
> > I'm not sure if this is related, but on my ARMv7 (32 bit) sandbox
> > there is an issue with fstat accesses to files.
> > 
> > When I try to run a program build against newest glibc (installed in
> > /opt/lib) I do see issues with {f}stat on other libraries (e.g.
> > /opt/lib/librt.so). To be more specific I do experience the
> > EOVERFLOW error:
> > 
> > error while loading shared libraries: librt.so.1: cannot stat shared
> > object: Error 75
> > 
> > The "base" glibc is 2.28 (installed in /lib). The glibc under test
> > is the newest master installed in /opt/lib.
> > 
> > I'm now investigating this issue.  
> 
> I am not sure what it might be based on these information, could you
> provide a strace so we can pinpoint what might the issue?  

Things are getting more and more interesting.

Let's consider the /opt/lib/librt.so.1

After qemu boot:

root@y2038arm:~# stat /opt/lib/librt.so.1
  File: /opt/lib/librt.so.1 -> librt-2.32.9000.so
  Size: 18              Blocks: 0          IO Block: 4096   symbolic
link Device: b300h/45824d    Inode: 17490       Links: 1
Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2020-10-13 23:14:56.800000000 +0000      ----> OK
Modify: 2020-10-13 23:14:52.770000000 +0000
Change: 2020-10-13 23:14:52.770000000 +0000

Then I do run gdb (which was build with 2.28 glibc as a base and gcc
8.1, which uses the same library):

gdb test_y2038:
...
(gdb) run
Starting program: /usr/bin/test_y2038
/usr/bin/test_y2038: error while loading shared libraries: librt.so.1:
cannot stat shared object: Error 75 [Inferior 1 (process 1045) exited
with code 0177]

So I've accessed the librt.so.1 with some old - i.e. 2.28 ABI - now:

root@y2038arm:~# stat /opt/lib/librt.so.1
  File: /opt/lib/librt.so.1 -> librt-2.32.9000.so
  Size: 18              Blocks: 0          IO Block: 4096   symbolic
link Device: b300h/45824d    Inode: 17490       Links: 1
Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 1901-12-13 20:46:33.625721000 +0000  ----> Overflow
Modify: 2020-10-13 23:14:52.770000000 +0000
Change: 2020-10-13 23:14:52.770000000 +0000

root@y2038arm:~# strace -v -Tf -e trace=file test_y2038

openat(AT_FDCWD, "/opt/lib/librt.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC)
= 3 <0.000409> statx(3, "",
AT_STATX_SYNC_AS_STAT|AT_NO_AUTOMOUNT|AT_EMPTY_PATH, STATX_BASIC_STATS,
{stx_mask=STATX_ALL, stx_blksize=4096, stx_attributes=0, stx_nlink=1,
stx_uid=0, stx_gid=0, stx_mode=S_IFREG|0755, stx_ino=17487,
stx_size=425008, stx_blocks=832,
stx_attributes_mask=STATX_ATTR_COMPRESSED|STATX_ATTR_IMMUTABLE|STATX_ATTR_APPEND|STATX_ATTR_NODUMP|STATX_ATTR_ENCRYPTED,
stx_atime={tv_sec=1602625090, tv_nsec=600000000} /*
2020-10-13T21:38:10.600000000+0000 */, stx_btime={tv_sec=1602622592,
tv_nsec=0} /* 2020-10-13T20:56:32+0000 */,
stx_ctime={tv_sec=2147484284, tv_nsec=335721000},
stx_mtime={tv_sec=2147484263, tv_nsec=545721000}, stx_rdev_major=0,
stx_rdev_minor=0, stx_dev_major=179, stx_dev_minor=0}) = 0 <0.000494>
test_y2038: error while loading shared libraries: librt.so.1: cannot
stat shared object: Error 75 +++ exited with 127 +++


Here the ctime and mtime are wrong - i.e. overflowed.

The system date is not changed:
root@y2038arm:~# date
Tue Oct 13 21:40:02 UTC 2020
root@y2038arm:~# date +%s
1602625224

I will continue investigation tomorrow...

> 
> The arm-linux-gnueabihf testing I did was on a aarch64 kernel
> (4.12.13). Besides the make check without regression, I could run
> system binaries with ./testrun.sh.
> 
> I will check on a different kernel/system with a 32-bit kernel.
> 




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
  
Lukasz Majewski Oct. 14, 2020, 1:15 p.m. UTC | #23
Dear Community,

> Hi Adhemerval,
> 
> > On 13/10/2020 10:58, Lukasz Majewski wrote:  
> > > Hi Adhemerval,
> > >     
> > >> On 07/10/2020 09:52, Adhemerval Zanella wrote:    
> > >>>
> > >>>
> > >>> On 06/10/2020 06:48, Lukasz Majewski wrote:      
> > >>>> Hi Adhemerval,
> > >>>>      
> > >>>>> A new struct __stat{64}_t64 type is added with the required
> > >>>>> __timespec64 time definition.  Both non-LFS and LFS support
> > >>>>> were done with an extra __NR_statx call plus a conversion to
> > >>>>> the new __stat{64}_t64 type.  The statx call is done only for
> > >>>>> architectures with support for 32-bit time_t ABI.
> > >>>>>
> > >>>>> Internally some extra routines to copy from/to struct stat{64}
> > >>>>> to struct __stat{64} used on multiple implementations (stat,
> > >>>>> fstat, lstat, and fstatat) are added on a extra file
> > >>>>> (stat_t64_cp.c).  Aslo some extra routines to copy from statx
> > >>>>> to __stat{64} is added on statx_cp.c.
> > >>>>>
> > >>>>> Checked with a build for all affected ABIs. I also checked on
> > >>>>> x86_64, i686, powerpc, powerpc64le, sparcv9, sparc64, s390,
> > >>>>> and s390x.      
> > >>>>
> > >>>> When do you plan to pull this patch set to -master?
> > >>>> Those patches have been available for review on the mailing
> > >>>> list for more than two months now.      
> > >>>
> > >>> Hi Lukasz, thanks to remind me. I will rebase against master and
> > >>> run some regressions tests against some platforms and push it.
> > >>>       
> > >>
> > >> One required change with the rebase is adapt the riscv32 ABI to
> > >> exclude the __{f,l}xstat{at} symbol and replace with proper
> > >> {f,l}stat ones. It is possible because the new ABI was added on
> > >> current development branch, however one minor inconvenient is the
> > >> toolchain need to be rebuild with a updated glibc branch to avoid
> > >> linking failures with libstd++ (which uses __{f,l}xstat{at}).
> > >>    
> > > 
> > > I'm not sure if this is related, but on my ARMv7 (32 bit) sandbox
> > > there is an issue with fstat accesses to files.
> > > 
> > > When I try to run a program build against newest glibc (installed
> > > in /opt/lib) I do see issues with {f}stat on other libraries (e.g.
> > > /opt/lib/librt.so). To be more specific I do experience the
> > > EOVERFLOW error:
> > > 
> > > error while loading shared libraries: librt.so.1: cannot stat
> > > shared object: Error 75
> > > 
> > > The "base" glibc is 2.28 (installed in /lib). The glibc under test
> > > is the newest master installed in /opt/lib.
> > > 
> > > I'm now investigating this issue.    
> > 
> > I am not sure what it might be based on these information, could you
> > provide a strace so we can pinpoint what might the issue?    
> 
> Things are getting more and more interesting.
> 
> Let's consider the /opt/lib/librt.so.1
> 
> After qemu boot:
> 
> root@y2038arm:~# stat /opt/lib/librt.so.1
>   File: /opt/lib/librt.so.1 -> librt-2.32.9000.so
>   Size: 18              Blocks: 0          IO Block: 4096   symbolic
> link Device: b300h/45824d    Inode: 17490       Links: 1
> Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/
> root) Access: 2020-10-13 23:14:56.800000000 +0000      ----> OK
> Modify: 2020-10-13 23:14:52.770000000 +0000
> Change: 2020-10-13 23:14:52.770000000 +0000
> 
> Then I do run gdb (which was build with 2.28 glibc as a base and gcc
> 8.1, which uses the same library):
> 
> gdb test_y2038:
> ...
> (gdb) run
> Starting program: /usr/bin/test_y2038
> /usr/bin/test_y2038: error while loading shared libraries: librt.so.1:
> cannot stat shared object: Error 75 [Inferior 1 (process 1045) exited
> with code 0177]
> 
> So I've accessed the librt.so.1 with some old - i.e. 2.28 ABI - now:
> 
> root@y2038arm:~# stat /opt/lib/librt.so.1
>   File: /opt/lib/librt.so.1 -> librt-2.32.9000.so
>   Size: 18              Blocks: 0          IO Block: 4096   symbolic
> link Device: b300h/45824d    Inode: 17490       Links: 1
> Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/
> root) Access: 1901-12-13 20:46:33.625721000 +0000  ----> Overflow
> Modify: 2020-10-13 23:14:52.770000000 +0000
> Change: 2020-10-13 23:14:52.770000000 +0000
> 
> root@y2038arm:~# strace -v -Tf -e trace=file test_y2038
> 
> openat(AT_FDCWD, "/opt/lib/librt.so.1",
> O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3 <0.000409> statx(3, "",
> AT_STATX_SYNC_AS_STAT|AT_NO_AUTOMOUNT|AT_EMPTY_PATH,
> STATX_BASIC_STATS, {stx_mask=STATX_ALL, stx_blksize=4096,
> stx_attributes=0, stx_nlink=1, stx_uid=0, stx_gid=0,
> stx_mode=S_IFREG|0755, stx_ino=17487, stx_size=425008, stx_blocks=832,
> stx_attributes_mask=STATX_ATTR_COMPRESSED|STATX_ATTR_IMMUTABLE|STATX_ATTR_APPEND|STATX_ATTR_NODUMP|STATX_ATTR_ENCRYPTED,
> stx_atime={tv_sec=1602625090, tv_nsec=600000000} /*
> 2020-10-13T21:38:10.600000000+0000 */, stx_btime={tv_sec=1602622592,
> tv_nsec=0} /* 2020-10-13T20:56:32+0000 */,
> stx_ctime={tv_sec=2147484284, tv_nsec=335721000},
> stx_mtime={tv_sec=2147484263, tv_nsec=545721000}, stx_rdev_major=0,
> stx_rdev_minor=0, stx_dev_major=179, stx_dev_minor=0}) = 0 <0.000494>
> test_y2038: error while loading shared libraries: librt.so.1: cannot
> stat shared object: Error 75 +++ exited with 127 +++
> 
> 
> Here the ctime and mtime are wrong - i.e. overflowed.
> 
> The system date is not changed:
> root@y2038arm:~# date
> Tue Oct 13 21:40:02 UTC 2020
> root@y2038arm:~# date +%s
> 1602625224
> 
> I will continue investigation tomorrow...

And now the penny has dropped...

The issue was that:

1. Adhemerval has added extra checks for overflowing the time in
{f}stat{at} patches - this is obviously good :-)

2. In my test system - I've been using "time" syscall (glibc function)
to get the seconds after epoch. This was not yet [*] converted to
support 64 bit time.

3. Some tests (like clock_gettime / clock_settime) require time
modifications after Y2038. Broken time() caused wrong data after
casting from __time_t to __time64_t and the proper time couldn't be
restored.

4. As a result - the date was wrong during the following tests
execution and {mac}time for external files (like librt.so.1,
libgcc_s.so) was set to wrong value.

5. Each subsequent call of {fl}stat{64} returned error due to date
overflow check.

Fix:

Convert time to support 64 bit time.

[*] I will send patches after build-many-glibcs.py and xcheck finish.

> 
> > 
> > The arm-linux-gnueabihf testing I did was on a aarch64 kernel
> > (4.12.13). Besides the make check without regression, I could run
> > system binaries with ./testrun.sh.
> > 
> > I will check on a different kernel/system with a 32-bit kernel.
> >   
> 
> 
> 
> 
> Best regards,
> 
> Lukasz Majewski
> 
> --
> 
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email:
> lukma@denx.de




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
  
Adhemerval Zanella Oct. 14, 2020, 1:39 p.m. UTC | #24
On 14/10/2020 10:15, Lukasz Majewski wrote:
> Dear Community,
> 
>> Hi Adhemerval,
>>
>>> On 13/10/2020 10:58, Lukasz Majewski wrote:  
>>>> Hi Adhemerval,
>>>>     
>>>>> On 07/10/2020 09:52, Adhemerval Zanella wrote:    
>>>>>>
>>>>>>
>>>>>> On 06/10/2020 06:48, Lukasz Majewski wrote:      
>>>>>>> Hi Adhemerval,
>>>>>>>      
>>>>>>>> A new struct __stat{64}_t64 type is added with the required
>>>>>>>> __timespec64 time definition.  Both non-LFS and LFS support
>>>>>>>> were done with an extra __NR_statx call plus a conversion to
>>>>>>>> the new __stat{64}_t64 type.  The statx call is done only for
>>>>>>>> architectures with support for 32-bit time_t ABI.
>>>>>>>>
>>>>>>>> Internally some extra routines to copy from/to struct stat{64}
>>>>>>>> to struct __stat{64} used on multiple implementations (stat,
>>>>>>>> fstat, lstat, and fstatat) are added on a extra file
>>>>>>>> (stat_t64_cp.c).  Aslo some extra routines to copy from statx
>>>>>>>> to __stat{64} is added on statx_cp.c.
>>>>>>>>
>>>>>>>> Checked with a build for all affected ABIs. I also checked on
>>>>>>>> x86_64, i686, powerpc, powerpc64le, sparcv9, sparc64, s390,
>>>>>>>> and s390x.      
>>>>>>>
>>>>>>> When do you plan to pull this patch set to -master?
>>>>>>> Those patches have been available for review on the mailing
>>>>>>> list for more than two months now.      
>>>>>>
>>>>>> Hi Lukasz, thanks to remind me. I will rebase against master and
>>>>>> run some regressions tests against some platforms and push it.
>>>>>>       
>>>>>
>>>>> One required change with the rebase is adapt the riscv32 ABI to
>>>>> exclude the __{f,l}xstat{at} symbol and replace with proper
>>>>> {f,l}stat ones. It is possible because the new ABI was added on
>>>>> current development branch, however one minor inconvenient is the
>>>>> toolchain need to be rebuild with a updated glibc branch to avoid
>>>>> linking failures with libstd++ (which uses __{f,l}xstat{at}).
>>>>>    
>>>>
>>>> I'm not sure if this is related, but on my ARMv7 (32 bit) sandbox
>>>> there is an issue with fstat accesses to files.
>>>>
>>>> When I try to run a program build against newest glibc (installed
>>>> in /opt/lib) I do see issues with {f}stat on other libraries (e.g.
>>>> /opt/lib/librt.so). To be more specific I do experience the
>>>> EOVERFLOW error:
>>>>
>>>> error while loading shared libraries: librt.so.1: cannot stat
>>>> shared object: Error 75
>>>>
>>>> The "base" glibc is 2.28 (installed in /lib). The glibc under test
>>>> is the newest master installed in /opt/lib.
>>>>
>>>> I'm now investigating this issue.    
>>>
>>> I am not sure what it might be based on these information, could you
>>> provide a strace so we can pinpoint what might the issue?    
>>
>> Things are getting more and more interesting.
>>
>> Let's consider the /opt/lib/librt.so.1
>>
>> After qemu boot:
>>
>> root@y2038arm:~# stat /opt/lib/librt.so.1
>>   File: /opt/lib/librt.so.1 -> librt-2.32.9000.so
>>   Size: 18              Blocks: 0          IO Block: 4096   symbolic
>> link Device: b300h/45824d    Inode: 17490       Links: 1
>> Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/
>> root) Access: 2020-10-13 23:14:56.800000000 +0000      ----> OK
>> Modify: 2020-10-13 23:14:52.770000000 +0000
>> Change: 2020-10-13 23:14:52.770000000 +0000
>>
>> Then I do run gdb (which was build with 2.28 glibc as a base and gcc
>> 8.1, which uses the same library):
>>
>> gdb test_y2038:
>> ...
>> (gdb) run
>> Starting program: /usr/bin/test_y2038
>> /usr/bin/test_y2038: error while loading shared libraries: librt.so.1:
>> cannot stat shared object: Error 75 [Inferior 1 (process 1045) exited
>> with code 0177]
>>
>> So I've accessed the librt.so.1 with some old - i.e. 2.28 ABI - now:
>>
>> root@y2038arm:~# stat /opt/lib/librt.so.1
>>   File: /opt/lib/librt.so.1 -> librt-2.32.9000.so
>>   Size: 18              Blocks: 0          IO Block: 4096   symbolic
>> link Device: b300h/45824d    Inode: 17490       Links: 1
>> Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/
>> root) Access: 1901-12-13 20:46:33.625721000 +0000  ----> Overflow
>> Modify: 2020-10-13 23:14:52.770000000 +0000
>> Change: 2020-10-13 23:14:52.770000000 +0000
>>
>> root@y2038arm:~# strace -v -Tf -e trace=file test_y2038
>>
>> openat(AT_FDCWD, "/opt/lib/librt.so.1",
>> O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3 <0.000409> statx(3, "",
>> AT_STATX_SYNC_AS_STAT|AT_NO_AUTOMOUNT|AT_EMPTY_PATH,
>> STATX_BASIC_STATS, {stx_mask=STATX_ALL, stx_blksize=4096,
>> stx_attributes=0, stx_nlink=1, stx_uid=0, stx_gid=0,
>> stx_mode=S_IFREG|0755, stx_ino=17487, stx_size=425008, stx_blocks=832,
>> stx_attributes_mask=STATX_ATTR_COMPRESSED|STATX_ATTR_IMMUTABLE|STATX_ATTR_APPEND|STATX_ATTR_NODUMP|STATX_ATTR_ENCRYPTED,
>> stx_atime={tv_sec=1602625090, tv_nsec=600000000} /*
>> 2020-10-13T21:38:10.600000000+0000 */, stx_btime={tv_sec=1602622592,
>> tv_nsec=0} /* 2020-10-13T20:56:32+0000 */,
>> stx_ctime={tv_sec=2147484284, tv_nsec=335721000},
>> stx_mtime={tv_sec=2147484263, tv_nsec=545721000}, stx_rdev_major=0,
>> stx_rdev_minor=0, stx_dev_major=179, stx_dev_minor=0}) = 0 <0.000494>
>> test_y2038: error while loading shared libraries: librt.so.1: cannot
>> stat shared object: Error 75 +++ exited with 127 +++
>>
>>
>> Here the ctime and mtime are wrong - i.e. overflowed.
>>
>> The system date is not changed:
>> root@y2038arm:~# date
>> Tue Oct 13 21:40:02 UTC 2020
>> root@y2038arm:~# date +%s
>> 1602625224
>>
>> I will continue investigation tomorrow...
> 
> And now the penny has dropped...
> 
> The issue was that:
> 
> 1. Adhemerval has added extra checks for overflowing the time in
> {f}stat{at} patches - this is obviously good :-)
> 
> 2. In my test system - I've been using "time" syscall (glibc function)
> to get the seconds after epoch. This was not yet [*] converted to
> support 64 bit time.
> 
> 3. Some tests (like clock_gettime / clock_settime) require time
> modifications after Y2038. Broken time() caused wrong data after
> casting from __time_t to __time64_t and the proper time couldn't be
> restored.
> 
> 4. As a result - the date was wrong during the following tests
> execution and {mac}time for external files (like librt.so.1,
> libgcc_s.so) was set to wrong value.
> 
> 5. Each subsequent call of {fl}stat{64} returned error due to date
> overflow check.
> 
> Fix:
> 
> Convert time to support 64 bit time.
> 
> [*] I will send patches after build-many-glibcs.py and xcheck finish.

Good to know this is an issue not related to the stat patches itself.
I was confused because you initially didn't describe the test you
are doing in details, so it was hard to pinpoint the issue.
  

Patch

diff --git a/include/sys/stat.h b/include/sys/stat.h
index 199173b007..87d4a5ec4f 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -3,6 +3,8 @@ 
 
 #ifndef _ISOMAC
 # include <xstatver.h>
+# include <struct___timespec64.h>
+# include <struct_stat_time64.h>
 # include <stdbool.h>
 
 static inline bool
@@ -44,6 +46,36 @@  hidden_proto (__lstat64)
 hidden_proto (__fstatat64)
 # endif
 
+# if __TIMESIZE == 64
+#  define __stat_time64  __stat
+#  define __stat64_time64  __stat64
+#  define __fstat_time64  __fstat
+#  define __fstat64_time64  __fstat64
+#  define __lstat_time64  __lstat
+#  define __lstat64_time64  __lstat64
+#  define __fstatat_time64  __fstatat
+#  define __fstatat64_time64 __fstatat64
+# else
+extern int __stat_time64 (const char *file, struct __stat_t64 *buf);
+libc_hidden_proto (__stat_time64);
+extern int __stat64_time64 (const char *file, struct __stat64_t64 *buf);
+hidden_proto (__stat64_time64);
+extern int __lstat_time64 (const char *file, struct __stat_t64 *buf);
+libc_hidden_proto (__lstat_time64);
+extern int __lstat64_time64 (const char *file, struct __stat64_t64 *buf);
+hidden_proto (__lstat64_time64);
+extern int __fstat_time64 (int fd, struct __stat_t64 *buf);
+libc_hidden_proto (__fstat_time64);
+extern int __fstat64_time64 (int fd, struct __stat64_t64 *buf);
+hidden_proto (__fstat64_time64);
+extern int __fstatat_time64 (int dirfd, const char *pathname,
+			     struct __stat_t64 *buf, int flags);
+libc_hidden_proto (__fstatat_time64);
+extern int __fstatat64_time64 (int dirfd, const char *pathname,
+			       struct __stat64_t64 *buf, int flags);
+hidden_proto (__fstatat64_time64);
+# endif
+
 extern int __chmod (const char *__file, __mode_t __mode);
 libc_hidden_proto (__chmod)
 extern int __fchmod (int __fd, __mode_t __mode);
diff --git a/sysdeps/generic/struct_stat_time64.h b/sysdeps/generic/struct_stat_time64.h
new file mode 100644
index 0000000000..24bb9f75cb
--- /dev/null
+++ b/sysdeps/generic/struct_stat_time64.h
@@ -0,0 +1,7 @@ 
+#ifndef _BITS_STRUCT_STAT_TIME64_H
+#define _BITS_STRUCT_STAT_TIME64_H 1
+
+#define __stat_t64   stat
+#define __stat64_t64 stat64
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index f189f65daf..95a51ee4f2 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -273,7 +273,7 @@  sysdep_routines += xstatconv internal_statvfs internal_statvfs64 \
 		   open_nocancel open64_nocancel \
 		   openat_nocancel openat64_nocancel \
 		   read_nocancel pread64_nocancel \
-		   write_nocancel statx_cp
+		   write_nocancel statx_cp stat_t64_cp
 
 sysdep_headers += bits/fcntl-linux.h
 
diff --git a/sysdeps/unix/sysv/linux/fstat.c b/sysdeps/unix/sysv/linux/fstat.c
index bdbeded956..0981dbaa95 100644
--- a/sysdeps/unix/sysv/linux/fstat.c
+++ b/sysdeps/unix/sysv/linux/fstat.c
@@ -19,13 +19,24 @@ 
 #include <sys/stat.h>
 #include <kernel_stat.h>
 #include <fcntl.h>
+#include <stat_t64_cp.h>
 
 #if !XSTAT_IS_XSTAT64
+int
+__fstat_time64 (int fd, struct __stat_t64 *buf)
+{
+  return __fstatat_time64 (fd, "", buf, AT_EMPTY_PATH);
+}
+# if __TIMESIZE != 64
+libc_hidden_def (__fstat_time64)
+
 int
 __fstat (int fd, struct stat *buf)
 {
-  return __fstatat (fd, "", buf, AT_EMPTY_PATH);
+  struct __stat_t64 st_t64;
+  return __fstat_time64 (fd, &st_t64) ?: __cp_stat_t64_stat (&st_t64, buf);
 }
+# endif
 
 weak_alias (__fstat, fstat)
 #endif
diff --git a/sysdeps/unix/sysv/linux/fstat64.c b/sysdeps/unix/sysv/linux/fstat64.c
index c2ff1ff577..67667e79d8 100644
--- a/sysdeps/unix/sysv/linux/fstat64.c
+++ b/sysdeps/unix/sysv/linux/fstat64.c
@@ -19,16 +19,30 @@ 
 #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>
+
+int
+__fstat64_time64 (int fd, struct __stat64_t64 *buf)
+{
+  return __fstatat64_time64 (fd, "", buf, AT_EMPTY_PATH);
+}
+#if __TIMESIZE != 64
+hidden_def (__fstat64_time64)
 
 int
 __fstat64 (int fd, struct stat64 *buf)
 {
-  return __fstatat64 (fd, "", buf, AT_EMPTY_PATH);
+  struct __stat64_t64 st_t64;
+  return __fstat64_time64 (fd, &st_t64)
+	 ?: __cp_stat64_t64_stat64 (&st_t64, buf);
 }
+#endif
+
+#undef __fstat
+#undef fstat
+
 hidden_def (__fstat64)
 weak_alias (__fstat64, fstat64)
 
diff --git a/sysdeps/unix/sysv/linux/fstatat.c b/sysdeps/unix/sysv/linux/fstatat.c
index 03ddb3f493..f65d3b74a6 100644
--- a/sysdeps/unix/sysv/linux/fstatat.c
+++ b/sysdeps/unix/sysv/linux/fstatat.c
@@ -22,25 +22,28 @@ 
 
 #if !XSTAT_IS_XSTAT64
 # include <kstat_cp.h>
+# include <statx_cp.h>
+# include <stat_t64_cp.h>
 
 int
-__fstatat (int fd, const char *file, struct stat *st, int flag)
+__fstatat_time64 (int fd, const char *file, struct __stat_t64 *st, int flag)
 {
-# if STAT_IS_KERNEL_STAT
-  /* New kABIs which uses generic pre 64-bit time Linux ABI, e.g.
-     csky, nios2  */
-  int r = INLINE_SYSCALL_CALL (fstatat64, fd, file, st, flag);
-  if (r == 0 && (st->__st_ino_pad != 0
-		 || st->__st_size_pad != 0
-		 || st->__st_blocks_pad != 0))
-    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
-  return r;
-# else
-#  ifdef __NR_fstatat64
-  /* Old KABIs with old non-LFS support, e.g. arm, i386, hppa, m68k, mips32,
-     microblaze, s390, sh, powerpc, and sparc.  */
+  struct statx stx;
+  int r = INLINE_SYSCALL_CALL (statx, fd, file, flag, STATX_BASIC_STATS,
+			       &stx);
+  if (r == 0 || errno != ENOSYS)
+    {
+      if (r == 0)
+	__cp_stat_t64_statx (st, &stx);
+      return r;
+    }
+
+# ifdef __NR_fstatat64
+  /* Both new kABI which uses generic pre 64-bit time Linux ABI (e.g. csky
+     and nios) and old kABI with non-LFS support (e.g. arm, i386, hppa, m68k,
+     mips32, microblaze, s390, sh, powerpc, and sparc32).  */
   struct stat64 st64;
-  int r = INLINE_SYSCALL_CALL (fstatat64, fd, file, &st64, flag);
+  r = INLINE_SYSCALL_CALL (fstatat64, fd, file, &st64, flag);
   if (r == 0)
     {
       if (! in_ino_t_range (st64.st_ino)
@@ -48,7 +51,7 @@  __fstatat (int fd, const char *file, struct stat *st, int flag)
 	  || ! in_blkcnt_t_range (st64.st_blocks))
 	return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
 
-      /* Clear internal pad and reserved fields.  */
+      /* Clear both pad and reserved fields.  */
       memset (st, 0, sizeof (*st));
 
       st->st_dev = st64.st_dev,
@@ -61,22 +64,29 @@  __fstatat (int fd, const char *file, struct stat *st, int flag)
       st->st_size = st64.st_size;
       st->st_blksize = st64.st_blksize;
       st->st_blocks  = st64.st_blocks;
-      st->st_atim.tv_sec = st64.st_atim.tv_sec;
-      st->st_atim.tv_nsec = st64.st_atim.tv_nsec;
-      st->st_mtim.tv_sec = st64.st_mtim.tv_sec;
-      st->st_mtim.tv_nsec = st64.st_mtim.tv_nsec;
-      st->st_ctim.tv_sec = st64.st_ctim.tv_sec;
-      st->st_ctim.tv_nsec = st64.st_ctim.tv_nsec;
+      st->st_atim = valid_timespec_to_timespec64 (st64.st_atim);
+      st->st_mtim = valid_timespec_to_timespec64 (st64.st_mtim);
+      st->st_ctim = valid_timespec_to_timespec64 (st64.st_ctim);
     }
   return r;
-#  else
+# else
   /* 64-bit kabi outlier, e.g. mips64 and mips64-n32.  */
   struct kernel_stat kst;
-  int r = INTERNAL_SYSCALL_CALL (newfstatat, fd, file, &kst, flag);
-  return r ?: __cp_kstat_stat (&kst, st);
-#  endif /* __nr_fstatat64  */
-# endif /* STAT_IS_KERNEL_STAT  */
+  r = INTERNAL_SYSCALL_CALL (newfstatat, fd, file, &kst, flag);
+  return r ?: __cp_kstat_stat_t64 (&kst, st);
+# endif /* __NR_fstatat64  */
+}
+# if __TIMESIZE != 64
+libc_hidden_def (__fstatat_time64)
+
+int
+__fstatat (int fd, const char *file, struct stat *buf, int flags)
+{
+  struct __stat_t64 st_t64;
+  return __fstatat_time64 (fd, file, &st_t64, flags)
+	 ?: __cp_stat_t64_stat (&st_t64, buf);
 }
+# endif
 
 weak_alias (__fstatat, fstatat)
 #endif
diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
index 82fab107a5..b3940f0d20 100644
--- a/sysdeps/unix/sysv/linux/fstatat64.c
+++ b/sysdeps/unix/sysv/linux/fstatat64.c
@@ -19,56 +19,102 @@ 
 #define __fstatat __redirect___fstatat
 #define fstatat   __redirect_fstatat
 #include <sys/stat.h>
-#undef __fstatat
-#undef fstatat
 #include <fcntl.h>
-
+#include <string.h>
 #include <kernel_stat.h>
 #include <sysdep.h>
-
+#include <time.h>
 #include <statx_cp.h>
 #include <kstat_cp.h>
+#include <stat_t64_cp.h>
 
 int
-__fstatat64 (int fd, const char *file, struct stat64 *st, int flag)
+__fstatat64_time64 (int fd, const char *file, struct __stat64_t64 *st,
+		    int flag)
 {
+  int r;
+
+#if (__WORDSIZE == 32 \
+     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
+  struct statx tmp;
+  r = INLINE_SYSCALL_CALL (statx, fd, file, AT_NO_AUTOMOUNT | flag,
+			   STATX_BASIC_STATS, &tmp);
+  if (r == 0 || errno != ENOSYS)
+    {
+      if (r == 0)
+	__cp_stat64_t64_statx (st, &tmp);
+      return r;
+    }
+#endif
+
 #if XSTAT_IS_XSTAT64
 # ifdef __NR_newfstatat
   /* 64-bit kABI, e.g. aarch64, ia64, powerpc64*, s390x, riscv64, and
      x86_64.  */
-  return INLINE_SYSCALL_CALL (newfstatat, fd, file, st, flag);
+  r = INLINE_SYSCALL_CALL (newfstatat, fd, file, st, flag);
 # elif defined __NR_fstatat64
 #  if STAT64_IS_KERNEL_STAT64
-  /* 64-bit kABI outlier, e.g. alpha.  */
-  return INLINE_SYSCALL_CALL (fstatat64, fd, file, st, flag);
+  /* 64-bit kABI outlier, e.g. alpha  */
+  r = INLINE_SYSCALL_CALL (fstatat64, fd, file, st, flag);
 #  else
   /* 64-bit kABI outlier, e.g. sparc64.  */
   struct kernel_stat64 kst64;
-  int r = INLINE_SYSCALL_CALL (fstatat64, fd, file, &kst64, flag);
-  return r ?: __cp_stat64_kstat64 (st, &kst64);
-#  endif
-# else
-  /* 32-bit kABI with default 64-bit time_t, e.g. arc, riscv32.  */
-  struct statx tmp;
-  int r = INLINE_SYSCALL_CALL (statx, fd, file, AT_NO_AUTOMOUNT | flag,
-			       STATX_BASIC_STATS, &tmp);
+  r = INLINE_SYSCALL_CALL (fstatat64, fd, file, &kst64, flag);
   if (r == 0)
-    __cp_stat64_statx (st, &tmp);
-  return r;
+    r = __cp_stat64_kstat64 (st, &kst64);
+#  endif
 # endif
 #else
 # ifdef __NR_fstatat64
   /* All kABIs with non-LFS support, e.g. arm, csky, i386, hppa, m68k,
      microblaze, nios2, sh, powerpc32, and sparc32.  */
-  return INLINE_SYSCALL_CALL (fstatat64, fd, file, st, flag);
+  struct stat64 st64;
+  r = INLINE_SYSCALL_CALL (fstatat64, fd, file, &st64, flag);
+  if (r == 0)
+    {
+      /* Clear both pad and reserved fields.  */
+      memset (st, 0, sizeof (*st));
+
+      st->st_dev = st64.st_dev,
+      st->st_ino = st64.st_ino;
+      st->st_mode = st64.st_mode;
+      st->st_nlink = st64.st_nlink;
+      st->st_uid = st64.st_uid;
+      st->st_gid = st64.st_gid;
+      st->st_rdev = st64.st_rdev;
+      st->st_size = st64.st_size;
+      st->st_blksize = st64.st_blksize;
+      st->st_blocks  = st64.st_blocks;
+      st->st_atim = valid_timespec_to_timespec64 (st64.st_atim);
+      st->st_mtim = valid_timespec_to_timespec64 (st64.st_mtim);
+      st->st_ctim = valid_timespec_to_timespec64 (st64.st_ctim);
+    }
 # else
   /* 64-bit kabi outlier, e.g. mips64 and mips64-n32.  */
   struct kernel_stat kst;
-  int r = INTERNAL_SYSCALL_CALL (newfstatat, fd, file, &kst, flag);
-  return r ?: __cp_kstat_stat64 (&kst, st);
+  r = INTERNAL_SYSCALL_CALL (newfstatat, fd, file, &kst, flag);
+  if (r == 0)
+    r =  __cp_kstat_stat64_t64 (&kst, st);
 # endif
 #endif
+
+  return r;
 }
+#if __TIMESIZE != 64
+hidden_def (__fstatat64_time64)
+
+int
+__fstatat64 (int fd, const char *file, struct stat64 *st, int flags)
+{
+  struct __stat64_t64 st_t64;
+  return __fstatat64_time64 (fd, file, &st_t64, flags)
+	 ?: __cp_stat64_t64_stat64 (&st_t64, st);
+}
+#endif
+
+#undef __fstatat
+#undef fstatat
+
 hidden_def (__fstatat64)
 weak_alias (__fstatat64, fstatat64)
 
diff --git a/sysdeps/unix/sysv/linux/lstat.c b/sysdeps/unix/sysv/linux/lstat.c
index b0bdeee9e9..803ad78171 100644
--- a/sysdeps/unix/sysv/linux/lstat.c
+++ b/sysdeps/unix/sysv/linux/lstat.c
@@ -19,13 +19,24 @@ 
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <kernel_stat.h>
+#include <stat_t64_cp.h>
 
 #if !XSTAT_IS_XSTAT64
+int
+__lstat_time64 (const char *file, struct __stat_t64 *buf)
+{
+  return __fstatat_time64 (AT_FDCWD, file, buf, AT_SYMLINK_NOFOLLOW);
+}
+# if __TIMESIZE != 64
+libc_hidden_def (__lstat_time64)
+
 int
 __lstat (const char *file, struct stat *buf)
 {
-  return __fstatat (AT_FDCWD, file, buf, AT_SYMLINK_NOFOLLOW);
+  struct __stat_t64 st_t64;
+  return __lstat_time64 (file, &st_t64) ?: __cp_stat_t64_stat (&st_t64, buf);
 }
+# endif
 
 weak_alias (__lstat, lstat)
 #endif
diff --git a/sysdeps/unix/sysv/linux/lstat64.c b/sysdeps/unix/sysv/linux/lstat64.c
index e5f02e9822..971ab8469d 100644
--- a/sysdeps/unix/sysv/linux/lstat64.c
+++ b/sysdeps/unix/sysv/linux/lstat64.c
@@ -19,19 +19,32 @@ 
 #define __lstat __redirect___lstat
 #define lstat   __redirect_lstat
 #include <sys/stat.h>
-#undef __lstat
-#undef lstat
 #include <fcntl.h>
 #include <kernel_stat.h>
+#include <stat_t64_cp.h>
+
+int
+__lstat64_time64 (const char *file, struct __stat64_t64 *buf)
+{
+  return __fstatat64_time64 (AT_FDCWD, file, buf, AT_SYMLINK_NOFOLLOW);
+}
+#if __TIMESIZE != 64
+hidden_def (__lstat64_time64)
 
 int
 __lstat64 (const char *file, struct stat64 *buf)
 {
-  return __fstatat64 (AT_FDCWD, file, buf, AT_SYMLINK_NOFOLLOW);
+  struct __stat64_t64 st_t64;
+  return __lstat64_time64 (file, &st_t64)
+	 ?: __cp_stat64_t64_stat64 (&st_t64, buf);
 }
+#endif
 hidden_def (__lstat64)
 weak_alias (__lstat64, lstat64)
 
+#undef __lstat
+#undef lstat
+
 #if XSTAT_IS_XSTAT64
 strong_alias (__lstat64, __lstat)
 weak_alias (__lstat64, lstat)
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/kstat_cp.h b/sysdeps/unix/sysv/linux/mips/mips64/kstat_cp.h
index 7f226416f9..553f4226bc 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/kstat_cp.h
+++ b/sysdeps/unix/sysv/linux/mips/mips64/kstat_cp.h
@@ -20,23 +20,21 @@ 
 #include <kernel_stat.h>
 
 static inline int
-__cp_kstat_stat (const struct kernel_stat *kst, struct stat *st)
+__cp_kstat_stat_t64 (const struct kernel_stat *kst, struct __stat_t64 *st)
 {
+  if (! in_ino_t_range (kst->st_ino)
+      || ! in_off_t_range (kst->st_size)
+      || ! in_blkcnt_t_range (kst->st_blocks))
+    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
+
   st->st_dev = kst->st_dev;
-  memset (&st->st_pad1, 0, sizeof (st->st_pad1));
   st->st_ino = kst->st_ino;
-  if (st->st_ino != kst->st_ino)
-    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
   st->st_mode = kst->st_mode;
   st->st_nlink = kst->st_nlink;
   st->st_uid = kst->st_uid;
   st->st_gid = kst->st_gid;
   st->st_rdev = kst->st_rdev;
-  memset (&st->st_pad2, 0, sizeof (st->st_pad2));
   st->st_size = kst->st_size;
-  if (st->st_size != kst->st_size)
-    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
-  st->st_pad3 = 0;
   st->st_atim.tv_sec = kst->st_atime_sec;
   st->st_atim.tv_nsec = kst->st_atime_nsec;
   st->st_mtim.tv_sec = kst->st_mtime_sec;
@@ -45,26 +43,20 @@  __cp_kstat_stat (const struct kernel_stat *kst, struct stat *st)
   st->st_ctim.tv_nsec = kst->st_ctime_nsec;
   st->st_blksize = kst->st_blksize;
   st->st_blocks = kst->st_blocks;
-  if (st->st_blocks != kst->st_blocks)
-    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EOVERFLOW);
-  memset (&st->st_pad5, 0, sizeof (st->st_pad5));
 
   return 0;
 }
 
 static inline int
-__cp_kstat_stat64 (const struct kernel_stat *kst, struct stat64 *st)
+__cp_kstat_stat64_t64 (const struct kernel_stat *kst, struct __stat64_t64 *st)
 {
   st->st_dev = kst->st_dev;
-  memset (&st->st_pad1, 0, sizeof (st->st_pad1));
   st->st_ino = kst->st_ino;
   st->st_mode = kst->st_mode;
   st->st_nlink = kst->st_nlink;
   st->st_uid = kst->st_uid;
   st->st_gid = kst->st_gid;
   st->st_rdev = kst->st_rdev;
-  memset (&st->st_pad2, 0, sizeof (st->st_pad2));
-  st->st_pad3 = 0;
   st->st_size = kst->st_size;
   st->st_blksize = kst->st_blksize;
   st->st_blocks = kst->st_blocks;
@@ -74,7 +66,6 @@  __cp_kstat_stat64 (const struct kernel_stat *kst, struct stat64 *st)
   st->st_mtim.tv_nsec = kst->st_mtime_nsec;
   st->st_ctim.tv_sec = kst->st_ctime_sec;
   st->st_ctim.tv_nsec = kst->st_ctime_nsec;
-  memset (&st->st_pad4, 0, sizeof (st->st_pad4));
 
   return 0;
 }
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/statx_cp.c b/sysdeps/unix/sysv/linux/mips/mips64/statx_cp.c
deleted file mode 100644
index 260cda987e..0000000000
--- a/sysdeps/unix/sysv/linux/mips/mips64/statx_cp.c
+++ /dev/null
@@ -1,3 +0,0 @@ 
-/* Override the generic statx_cp.c which is only needed for new 32-bit arch
-   without stat64 family support.
- */
diff --git a/sysdeps/unix/sysv/linux/stat.c b/sysdeps/unix/sysv/linux/stat.c
index a77502eb95..dcbc22da29 100644
--- a/sysdeps/unix/sysv/linux/stat.c
+++ b/sysdeps/unix/sysv/linux/stat.c
@@ -19,13 +19,24 @@ 
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <kernel_stat.h>
+#include <stat_t64_cp.h>
 
 #if !XSTAT_IS_XSTAT64
+int
+__stat_time64 (const char *file, struct __stat_t64 *buf)
+{
+  return __fstatat_time64 (AT_FDCWD, file, buf, 0);
+}
+# if __TIMESIZE != 64
+libc_hidden_def (__stat_time64);
+
 int
 __stat (const char *file, struct stat *buf)
 {
-  return __fstatat (AT_FDCWD, file, buf, 0);
+  struct __stat_t64 st_t64;
+  return __stat_time64 (file, &st_t64) ?: __cp_stat_t64_stat (&st_t64, buf);
 }
+# endif
 
 weak_alias (__stat, stat)
 #endif
diff --git a/sysdeps/unix/sysv/linux/stat64.c b/sysdeps/unix/sysv/linux/stat64.c
index 2f40037c2c..bd8b17ac49 100644
--- a/sysdeps/unix/sysv/linux/stat64.c
+++ b/sysdeps/unix/sysv/linux/stat64.c
@@ -19,16 +19,30 @@ 
 #define __stat __redirect___stat
 #define stat   __redirect_stat
 #include <sys/stat.h>
-#undef __stat
-#undef stat
 #include <fcntl.h>
 #include <kernel_stat.h>
+#include <stat_t64_cp.h>
+
+int
+__stat64_time64 (const char *file, struct __stat64_t64 *buf)
+{
+  return __fstatat64_time64 (AT_FDCWD, file, buf, 0);
+}
+#if __TIMESIZE != 64
+hidden_def (__stat64_time64)
 
 int
 __stat64 (const char *file, struct stat64 *buf)
 {
-  return __fstatat64 (AT_FDCWD, file, buf, 0);
+  struct __stat64_t64 st_t64;
+  return __stat64_time64 (file, &st_t64)
+	 ?: __cp_stat64_t64_stat64 (&st_t64, buf);
 }
+#endif
+
+#undef __stat
+#undef stat
+
 hidden_def (__stat64)
 weak_alias (__stat64, stat64)
 
diff --git a/sysdeps/unix/sysv/linux/stat_t64_cp.c b/sysdeps/unix/sysv/linux/stat_t64_cp.c
new file mode 100644
index 0000000000..56459b6266
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/stat_t64_cp.c
@@ -0,0 +1,92 @@ 
+/* Struct stat/stat64 to stat/stat64 conversion for Linux.
+   Copyright (C) 2020 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 <stat_t64_cp.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+#if __TIMESIZE != 64
+/* Convert the 64-bit time_t stat ST_T64 to the non-LFS ST stat and returns
+   EOVERFLOW if any of time (access, modification, status) is larger than
+   32-bit time_t.  It is used on non-LFS stat, fstat, lstat, and fstatat to
+   convert from the the 64-bit time_t call.  */
+int
+__cp_stat_t64_stat (const struct __stat_t64 *st_t64, struct stat *st)
+{
+  if (! in_time_t_range (st_t64->st_atim.tv_sec)
+      || ! in_time_t_range (st_t64->st_mtim.tv_sec)
+      || ! in_time_t_range (st_t64->st_ctim.tv_sec))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  /* Clear both pad and reserved fields.  */
+  memset (st, 0, sizeof (*st));
+
+  st->st_dev = st_t64->st_dev,
+  st->st_ino = st_t64->st_ino;
+  st->st_mode = st_t64->st_mode;
+  st->st_nlink = st_t64->st_nlink;
+  st->st_uid = st_t64->st_uid;
+  st->st_gid = st_t64->st_gid;
+  st->st_rdev = st_t64->st_rdev;
+  st->st_size = st_t64->st_size;
+  st->st_blksize = st_t64->st_blksize;
+  st->st_blocks  = st_t64->st_blocks;
+  st->st_atim = valid_timespec64_to_timespec (st_t64->st_atim);
+  st->st_mtim = valid_timespec64_to_timespec (st_t64->st_mtim);
+  st->st_ctim = valid_timespec64_to_timespec (st_t64->st_ctim);
+
+  return 0;
+}
+
+int
+__cp_stat64_t64_stat64 (const struct __stat64_t64 *st64_t64,
+			struct stat64 *st64)
+{
+  if (! in_time_t_range (st64_t64->st_atim.tv_sec)
+      || ! in_time_t_range (st64_t64->st_mtim.tv_sec)
+      || ! in_time_t_range (st64_t64->st_ctim.tv_sec))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  /* Clear both pad and reserved fields.  */
+  memset (st64, 0, sizeof (*st64));
+
+  st64->st_dev = st64_t64->st_dev,
+  st64->st_ino = st64_t64->st_ino;
+  st64->st_mode = st64_t64->st_mode;
+  st64->st_nlink = st64_t64->st_nlink;
+  st64->st_uid = st64_t64->st_uid;
+  st64->st_gid = st64_t64->st_gid;
+  st64->st_rdev = st64_t64->st_rdev;
+  st64->st_size = st64_t64->st_size;
+  st64->st_blksize = st64_t64->st_blksize;
+  st64->st_blocks  = st64_t64->st_blocks;
+  st64->st_atim = valid_timespec64_to_timespec (st64_t64->st_atim);
+  st64->st_mtim = valid_timespec64_to_timespec (st64_t64->st_mtim);
+  st64->st_ctim = valid_timespec64_to_timespec (st64_t64->st_ctim);
+
+  return 0;
+}
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/stat_t64_cp.h b/sysdeps/unix/sysv/linux/stat_t64_cp.h
new file mode 100644
index 0000000000..ad2bcc7a04
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/stat_t64_cp.h
@@ -0,0 +1,28 @@ 
+/* Copy to/from struct stat with and without 64-bit time_t support.
+   Copyright (C) 2020 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 <sys/stat.h>
+
+#if __TIMESIZE != 64
+extern int __cp_stat_t64_stat (const struct __stat_t64 *st_t64,
+			       struct stat *st)
+  attribute_hidden;
+extern int __cp_stat64_t64_stat64 (const struct __stat64_t64 *st64_t64,
+				   struct stat64 *st64)
+  attribute_hidden;
+#endif
diff --git a/sysdeps/unix/sysv/linux/statx_cp.c b/sysdeps/unix/sysv/linux/statx_cp.c
index cc6e17929e..4b35e86f8d 100644
--- a/sysdeps/unix/sysv/linux/statx_cp.c
+++ b/sysdeps/unix/sysv/linux/statx_cp.c
@@ -47,3 +47,57 @@  __cp_stat64_statx (struct stat64 *to, struct statx *from)
   to->st_blksize = from->stx_blksize;
 }
 #endif
+
+void
+__cp_stat_t64_statx (struct __stat_t64 *to, const struct statx *from)
+{
+  /* Clear both pad and reserved fields.  */
+  memset (to, 0, sizeof (*to));
+
+  to->st_dev = ((from->stx_dev_minor & 0xff) | (from->stx_dev_major << 8)
+		| ((from->stx_dev_minor & ~0xff) << 12));
+  to->st_ino = from->stx_ino;
+  to->st_mode = from->stx_mode;
+  to->st_nlink = from->stx_nlink;
+  to->st_uid = from->stx_uid;
+  to->st_gid = from->stx_gid;
+  to->st_rdev = ((from->stx_rdev_minor & 0xff) | (from->stx_rdev_major << 8)
+		 | ((from->stx_rdev_minor & ~0xff) << 12));
+  to->st_size = from->stx_size;
+  to->st_blksize = from->stx_blksize;
+  to->st_blocks = from->stx_blocks;
+
+  to->st_atime = from->stx_atime.tv_sec;
+  to->st_atim.tv_nsec = from->stx_atime.tv_nsec;
+  to->st_mtime = from->stx_mtime.tv_sec;
+  to->st_mtim.tv_nsec = from->stx_mtime.tv_nsec;
+  to->st_ctime = from->stx_ctime.tv_sec;
+  to->st_ctim.tv_nsec = from->stx_ctime.tv_nsec;
+}
+
+void
+__cp_stat64_t64_statx (struct __stat64_t64 *to, const struct statx *from)
+{
+  /* Clear both pad and reserved fields.  */
+  memset (to, 0, sizeof (*to));
+
+  to->st_dev = ((from->stx_dev_minor & 0xff) | (from->stx_dev_major << 8)
+		| ((from->stx_dev_minor & ~0xff) << 12));
+  to->st_ino = from->stx_ino;
+  to->st_mode = from->stx_mode;
+  to->st_nlink = from->stx_nlink;
+  to->st_uid = from->stx_uid;
+  to->st_gid = from->stx_gid;
+  to->st_rdev = ((from->stx_rdev_minor & 0xff) | (from->stx_rdev_major << 8)
+		 | ((from->stx_rdev_minor & ~0xff) << 12));
+  to->st_size = from->stx_size;
+  to->st_blksize = from->stx_blksize;
+  to->st_blocks = from->stx_blocks;
+
+  to->st_atime = from->stx_atime.tv_sec;
+  to->st_atim.tv_nsec = from->stx_atime.tv_nsec;
+  to->st_mtime = from->stx_mtime.tv_sec;
+  to->st_mtim.tv_nsec = from->stx_mtime.tv_nsec;
+  to->st_ctime = from->stx_ctime.tv_sec;
+  to->st_ctim.tv_nsec = from->stx_ctime.tv_nsec;
+}
diff --git a/sysdeps/unix/sysv/linux/statx_cp.h b/sysdeps/unix/sysv/linux/statx_cp.h
index fdbb807a31..bf3186ffac 100644
--- a/sysdeps/unix/sysv/linux/statx_cp.h
+++ b/sysdeps/unix/sysv/linux/statx_cp.h
@@ -18,3 +18,9 @@ 
 
 extern void __cp_stat64_statx (struct stat64 *to, struct statx *from)
   attribute_hidden;
+extern void __cp_stat_t64_statx (struct __stat_t64 *to,
+				 const struct statx *from)
+  attribute_hidden;
+extern void __cp_stat64_t64_statx (struct __stat64_t64 *to,
+				   const struct statx *from)
+  attribute_hidden;
diff --git a/sysdeps/unix/sysv/linux/struct_stat_time64.h b/sysdeps/unix/sysv/linux/struct_stat_time64.h
new file mode 100644
index 0000000000..b2a51927d0
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/struct_stat_time64.h
@@ -0,0 +1,122 @@ 
+/* Struct stat with 64-bit time support.
+   Copyright (C) 2020 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/>.  */
+
+#ifndef _BITS_STRUCT_STAT_TIME64_H
+#define _BITS_STRUCT_STAT_TIME64_H 1
+
+#if __TIMESIZE == 64
+# define __stat_t64   stat
+# define __stat64_t64 stat64
+#else
+# include <endian.h>
+
+# ifdef __USE_FILE_OFFSET64
+#  define __field64(type, type64, name) type64 name
+# else
+#  define __field64(type, type64, name) type name
+# endif
+
+/* The definition should be equal to the 'struct __timespec64' internal
+   layout.  */
+# if BYTE_ORDER == BIG_ENDIAN
+#  define __fieldts64(name) 					\
+   __time64_t name; __int32_t :32; __int32_t name ## nsec
+# else
+#  define __fieldts64(name)					\
+   __time64_t name; __int32_t name ## nsec; __int32_t :32
+# endif
+
+/* Workaround for the definition from struct_stat.h  */
+# undef st_atime
+# undef st_mtime
+# undef st_ctime
+
+struct __stat_t64
+  {
+    __dev_t st_dev;			/* Device.  */
+    __field64(__ino_t, __ino64_t, st_ino);  /* File serial number.  */
+    __mode_t st_mode;			/* File mode.  */
+    __nlink_t st_nlink;			/* Link count.  */
+    __uid_t st_uid;			/* User ID of the file's owner.	*/
+    __gid_t st_gid;			/* Group ID of the file's group.*/
+    __dev_t st_rdev;			/* Device number, if device.  */
+    __field64(__off_t, __off64_t, st_size);  /* Size of file, in bytes. */
+    __blksize_t st_blksize;		/* Optimal block size for I/O.  */
+    __field64(__blkcnt_t, __blkcnt64_t, st_blocks);  /* 512-byte blocks */
+# ifdef __USE_XOPEN2K8
+    /* Nanosecond resolution timestamps are stored in a format
+       equivalent to 'struct timespec'.  This is the type used
+       whenever possible but the Unix namespace rules do not allow the
+       identifier 'timespec' to appear in the <sys/stat.h> header.
+       Therefore we have to handle the use of this header in strictly
+       standard-compliant sources special.  */
+    struct __timespec64 st_atim;	/* Time of last access.  */
+    struct __timespec64 st_mtim;	/* Time of last modification.  */
+    struct __timespec64 st_ctim;	/* Time of last status change.  */
+#  define st_atime st_atim.tv_sec	/* Backward compatibility.  */
+#  define st_mtime st_mtim.tv_sec
+#  define st_ctime st_ctim.tv_sec
+# else
+    __fieldts64 (st_atime);
+    __fieldts64 (st_mtime);
+    __fieldts64 (st_ctime);
+# endif /* __USE_XOPEN2K8  */
+  };
+
+# undef __field64
+
+#ifdef __USE_LARGEFILE64
+struct __stat64_t64
+  {
+    __dev_t st_dev;			/* Device.  */
+    __ino64_t st_ino;			/* file serial number.	*/
+    __mode_t st_mode;			/* File mode.  */
+    __nlink_t st_nlink;			/* Link count.  */
+    __uid_t st_uid;			/* User ID of the file's owner.	*/
+    __gid_t st_gid;			/* Group ID of the file's group.*/
+    __dev_t st_rdev;			/* Device number, if device.  */
+    __off64_t st_size;			/* Size of file, in bytes.  */
+    __blksize_t st_blksize;		/* Optimal block size for I/O.  */
+    __blkcnt64_t st_blocks;		/* Number 512-byte blocks allocated. */
+# ifdef __USE_XOPEN2K8
+    /* Nanosecond resolution timestamps are stored in a format
+       equivalent to 'struct timespec'.  This is the type used
+       whenever possible but the Unix namespace rules do not allow the
+       identifier 'timespec' to appear in the <sys/stat.h> header.
+       Therefore we have to handle the use of this header in strictly
+       standard-compliant sources special.  */
+    struct __timespec64 st_atim;	/* Time of last access.  */
+    struct __timespec64 st_mtim;	/* Time of last modification.  */
+    struct __timespec64 st_ctim;	/* Time of last status change.  */
+# else
+    __fieldts64 (st_atime);
+    __fieldts64 (st_mtime);
+    __fieldts64 (st_ctime);
+# endif /* __USE_XOPEN2K8  */
+  };
+# endif /* __USE_LARGEFILE64  */
+
+# undef __fieldts64
+
+# define _STATBUF_ST_BLKSIZE
+# define _STATBUF_ST_RDEV
+# define _STATBUF_ST_NSEC
+
+# endif /* __TIMESIZE == 64  */
+
+#endif /* _BITS_STRUCT_STAT_TIME64_H  */