diff mbox series

MIPS: fix y2106 problem on N64 with statx

Message ID 20210312034920.14846-1-yunqiang.su@cipunited.com
State Dropped
Headers show
Series MIPS: fix y2106 problem on N64 with statx | expand

Commit Message

YunQiang Su March 12, 2021, 3:49 a.m. UTC
the stat series syscall of N64 use uint32 as its time.
Glibc converts it to int64 then. For example a file with timestamp -1:
   syscall(stat) gets 0xffffffff
   Glibc convert it to 0x00000000ffffffff
Then, -1 becomes a time in y2106.

In this patch, we use statx syscall to replace stat-series syscall.
statx always return int64 timestamp, and the `struct stat' in userland
of N64 always has 64bit timestamp. We can convert between them without
any problem.
---
 io/tst-fstatat.c                              | 26 +++++++-
 sysdeps/unix/sysv/linux/fstatat64.c           |  8 ++-
 .../unix/sysv/linux/mips/mips64/n64/fstatat.c | 52 +++++++++++++++
 .../unix/sysv/linux/mips/mips64/n64/fxstat.c  | 51 +++++++++++++++
 .../sysv/linux/mips/mips64/n64/fxstat64.c     | 43 +++++++++++++
 .../sysv/linux/mips/mips64/n64/fxstatat.c     | 63 +++++++++++++++++++
 .../sysv/linux/mips/mips64/n64/fxstatat64.c   | 53 ++++++++++++++++
 .../unix/sysv/linux/mips/mips64/n64/lxstat.c  | 51 +++++++++++++++
 .../sysv/linux/mips/mips64/n64/lxstat64.c     | 43 +++++++++++++
 .../unix/sysv/linux/mips/mips64/n64/xstat.c   | 51 +++++++++++++++
 .../unix/sysv/linux/mips/mips64/n64/xstat64.c | 43 +++++++++++++
 11 files changed, 482 insertions(+), 2 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
 create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
 create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
 create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
 create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
 create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
 create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
 create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
 create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c

Comments

Adhemerval Zanella March 12, 2021, 12:34 p.m. UTC | #1
On 12/03/2021 00:49, YunQiang Su wrote:
> the stat series syscall of N64 use uint32 as its time.
> Glibc converts it to int64 then. For example a file with timestamp -1:
>    syscall(stat) gets 0xffffffff
>    Glibc convert it to 0x00000000ffffffff
> Then, -1 becomes a time in y2106.

Sigh, another MIPS ABI idissionacracy that I am not aware about...

> 
> In this patch, we use statx syscall to replace stat-series syscall.
> statx always return int64 timestamp, and the `struct stat' in userland
> of N64 always has 64bit timestamp. We can convert between them without
> any problem
Some comments below.

> ---
>  io/tst-fstatat.c                              | 26 +++++++-
>  sysdeps/unix/sysv/linux/fstatat64.c           |  8 ++-
>  .../unix/sysv/linux/mips/mips64/n64/fstatat.c | 52 +++++++++++++++
>  .../unix/sysv/linux/mips/mips64/n64/fxstat.c  | 51 +++++++++++++++
>  .../sysv/linux/mips/mips64/n64/fxstat64.c     | 43 +++++++++++++
>  .../sysv/linux/mips/mips64/n64/fxstatat.c     | 63 +++++++++++++++++++
>  .../sysv/linux/mips/mips64/n64/fxstatat64.c   | 53 ++++++++++++++++
>  .../unix/sysv/linux/mips/mips64/n64/lxstat.c  | 51 +++++++++++++++
>  .../sysv/linux/mips/mips64/n64/lxstat64.c     | 43 +++++++++++++
>  .../unix/sysv/linux/mips/mips64/n64/xstat.c   | 51 +++++++++++++++
>  .../unix/sysv/linux/mips/mips64/n64/xstat64.c | 43 +++++++++++++
>  11 files changed, 482 insertions(+), 2 deletions(-)
>  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
>  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
>  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
>  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
>  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
>  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
>  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
>  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
>  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
> 
> diff --git a/io/tst-fstatat.c b/io/tst-fstatat.c
> index 4766bb2e71..8297b14479 100644
> --- a/io/tst-fstatat.c
> +++ b/io/tst-fstatat.c
> @@ -5,7 +5,7 @@
>  #include <string.h>
>  #include <unistd.h>
>  #include <sys/stat.h>
> -
> +#include <kernel-features.h>
>  
>  static void prepare (void);
>  #define PREPARE(argc, argv) prepare ()
> @@ -134,6 +134,30 @@ do_test (void)
>        puts ("stat results do not match");
>        return 1;
>      }
> +#if defined(__mips64) &&  (_MIPS_SIM == _ABI64) && defined(__ASSUME_STATX)
> +  /* fstatat syscall has y2106 problem on MIPS N64
> +     Now we use statx to implement *stat* functions
> +     So the problem should have gone */
> +  struct timespec tm_1[2] = {{-1, 0}, {-1, 0}};
> +  if (utimensat(dir_fd, "some-file", tm_1, 0) != 0)
> +    {
> +      puts ("utimensat fail");
> +      return 1;
> +    }
> +
> +  if (fstatat64 (dir_fd, "some-file", &st2, 0) != 0)
> +    {
> +      puts ("fstatat64 failed");
> +      return 1;
> +    }
> +
> +  if (st2.st_mtim.tv_sec != -1
> +      || st2.st_atim.tv_sec != -1)
> +    {
> +      puts ("fstatat64 has y2106 problem?");
> +      return 1;
> +    }
> +#endif
>  
>    if (unlinkat (dir_fd, "some-file", 0) != 0)
>      {

I am about to push a way to check in if the file has support for y2038 [1],
so please use this instead.  Also this tests does not really check 
any file timestamps so I don't think this is the place add this warning
(and making it mips specific it not a good approach, neither by using
__ASSUME_STATX which is Linux specific and it should be used on internal
tests).

Instead please add the y2106 checks on Linux specific tests:

  sysdeps/unix/sysv/linux/tst-futimens.c
  sysdeps/unix/sysv/linux/tst-utime.c
  sysdeps/unix/sysv/linux/tst-utimes.c

Since they use fstat to check against the set timestamps.

[1] https://patchwork.sourceware.org/project/glibc/patch/20210311123557.3486677-1-adhemerval.zanella@linaro.org/

> diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
> index 490226a8ec..220321be9c 100644
> --- a/sysdeps/unix/sysv/linux/fstatat64.c
> +++ b/sysdeps/unix/sysv/linux/fstatat64.c
> @@ -47,15 +47,21 @@ __fstatat64_time64 (int fd, const char *file, struct __stat64_t64 *buf,
>    int r;
>  
>  #if (__WORDSIZE == 32 \
> -     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
> +     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
> +    || defined(__mips64)

I would prefer to add a define added on kernel_stat.h, even though it seems
from a briefly inspecting on kernel sources that it is only mips64 that
has this issue.  I think we should avoid the preprocessor archirecture
define on Linux generic code.

So add a STAT_KERNEL_UNSIGNED_TIME_T with a proper comment on mips.h
kernel_stat.h

>    /* 32-bit kABI with default 64-bit time_t, e.g. arc, riscv32.   Also
>       64-bit time_t support is done through statx syscall.  */
> +  /* Also use statx syscall for MIPS N64, since newfstatat has y2106 problem */
>    struct statx tmp;

Merge it with the previous comment.

>    r = INTERNAL_SYSCALL_CALL (statx, fd, file, AT_NO_AUTOMOUNT | flag,
>  			     STATX_BASIC_STATS, &tmp);
>    if (r == 0)
>      {
> +#if defined(__mips64) && (_MIPS_SIM == _ABI64)
> +      __cp_stat64_statx (buf, &tmp);
> +#else
>        __cp_stat64_t64_statx (buf, &tmp);
> +#endif
>        return 0;
>      }
>    if (-r != ENOSYS)
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
> new file mode 100644
> index 0000000000..5000cd0715
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
> @@ -0,0 +1,52 @@
> +/* Copyright (C) 2005-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/>.  */
> +
> +/* Ho hum, since fxstatat == fxstatat64 we must get rid of the
> +   prototype or gcc will complain since they don't strictly match.  */
> +
> +#include <kernel-features.h>
> +#include <sys/syscall.h>
> +#if defined(__ASSUME_STATX) && defined(__NR_statx)
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <stddef.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <sys/stat.h>
> +
> +#include <sysdep.h>
> +#include <kernel_stat.h>
> +#include <statx_cp.h>
> +
> +
> +/* Get information about the file NAME relative to FD in ST.  */
> +int
> +__fstatat (int fd, const char *file, struct stat *st, int flag)
> +{
> +  struct statx xbuf;
> +  int r = INLINE_SYSCALL (statx, 5, fd, file, flag&AT_SYMLINK_NOFOLLOW,
> +	      STATX_BASIC_STATS, &xbuf);
> +  if (r == 0)
> +    __cp_stat64_statx((struct stat64 *)st, &xbuf);
> +  return r;
> +}
> +
> +weak_alias (__fstatat, fstatat)
> +
> +#else /* __ASSUME_STATX && __NR_statx */
> +#include <sysdeps/unix/sysv/linux/fstatat.c>
> +#endif

I see no point in such optimization, which adds another mips specific file.
If glibc is still alive near 2106 most likely we would had increases the
minimum kernel version to include __NR_statx...

> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
> new file mode 100644
> index 0000000000..acd929dfaa
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
> @@ -0,0 +1,51 @@
> +/* fxstat using old-style Unix stat system call.
> +   Copyright (C) 1991-2021 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 <kernel-features.h>
> +#include <sys/syscall.h>
> +#if defined(__ASSUME_STATX) && defined(__NR_statx)
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <kernel_stat.h>
> +#include <sysdep.h>
> +#include <statx_cp.h>
> +
> +/* Get information about the file NAME in BUF.  */
> +int
> +__fxstat (int vers, int fd, struct stat *buf)
> +{
> +  switch (vers)
> +    {
> +    case _STAT_VER_KERNEL:
> +      return INLINE_SYSCALL_CALL (fstat, fd, buf);
> +
> +    default:
> +      {
> +	struct statx xbuf;
> +	int r = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH,
> +		      STATX_BASIC_STATS, &xbuf);
> +	if (r == 0)
> +	  __cp_stat64_statx((struct stat64 *)buf, &xbuf);
> +	return r;
> +      }
> +    }
> +}
> +
> +#else /* __ASSUME_STATX && __NR_statx */
> +#include <sysdeps/unix/sysv/linux/mips/fxstat.c>
> +#endif

As for the mips specific implementation, the __fxstat are compatibilty 
symbols and I don't want us to change their semantic.  If user really 
care about y2106 they should use the newer stat symbols.  

> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
> new file mode 100644
> index 0000000000..a8da108347
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
> @@ -0,0 +1,43 @@
> +/* fxstat64 using 64-bit MIPS fstat system call.
> +   Copyright (C) 1997-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 <kernel-features.h>
> +#include <sys/syscall.h>
> +#if defined(__ASSUME_STATX) && defined(__NR_statx)
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <kernel_stat.h>
> +#include <sysdep.h>
> +#include <statx_cp.h>
> +
> +/* Get information about the file FD in BUF.  */
> +
> +int
> +__fxstat64 (int vers, int fd, struct stat64 *buf)
> +{
> +  struct statx xbuf;
> +  int r = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH,
> +	      STATX_BASIC_STATS, &xbuf);
> +  if (r == 0)
> +    __cp_stat64_statx(buf, &xbuf);
> +  return r;
> +}
> +
> +#else /* __ASSUME_STATX && __NR_statx */
> +#include <sysdeps/unix/sysv/linux/mips/mips64/fxstat64.c>
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
> new file mode 100644
> index 0000000000..935888efe6
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
> @@ -0,0 +1,63 @@
> +/* Copyright (C) 2005-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/>.  */
> +
> +/* Ho hum, since fxstatat == fxstatat64 we must get rid of the
> +   prototype or gcc will complain since they don't strictly match.  */
> +
> +#include <kernel-features.h>
> +#include <sys/syscall.h>
> +#if defined(__ASSUME_STATX) && defined(__NR_statx)
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <stddef.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <sys/stat.h>
> +
> +#include <sysdep.h>
> +#include <kernel_stat.h>
> +#include <statx_cp.h>
> +
> +
> +/* Get information about the file NAME relative to FD in ST.  */
> +int
> +__fxstatat (int vers, int fd, const char *file, struct stat *st, int flag)
> +{
> +  switch (vers)
> +    {
> +    case _STAT_VER_KERNEL:
> +	return INLINE_SYSCALL (newfstatat, 4, fd, file, st, flag);
> +
> +    case _STAT_VER_LINUX:
> +      {
> +	struct statx xbuf;
> +	int r = INLINE_SYSCALL (statx, 5, fd, file, flag&AT_SYMLINK_NOFOLLOW,
> +		      STATX_BASIC_STATS, &xbuf);
> +	if (r == 0)
> +	  __cp_stat64_statx((struct stat64 *)st, &xbuf);
> +	return r;
> +      }
> +
> +    default:
> +      __set_errno (EINVAL);
> +      return -1;
> +    }
> +}
> +
> +#else /* __ASSUME_STATX && __NR_statx */
> +#include <sysdeps/unix/sysv/linux/mips/mips64/fxstatat.c>
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
> new file mode 100644
> index 0000000000..80bd0f1d09
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
> @@ -0,0 +1,53 @@
> +/* Copyright (C) 2005-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 <kernel-features.h>
> +#include <sys/syscall.h>
> +#if defined(__ASSUME_STATX) && defined(__NR_statx)
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <stddef.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <sys/stat.h>
> +#include <kernel_stat.h>
> +
> +#include <sysdep.h>
> +#include <statx_cp.h>
> +
> +/* Get information about the file NAME in BUF.  */
> +
> +int
> +__fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag)
> +{
> +  if (__builtin_expect (vers != _STAT_VER_LINUX, 0))
> +    {
> +      __set_errno (EINVAL);
> +      return -1;
> +    }
> +
> +  struct statx xbuf;
> +  int r = INLINE_SYSCALL (statx, 5, fd, file, flag&AT_SYMLINK_NOFOLLOW,
> +	      STATX_BASIC_STATS, &xbuf);
> +  if (r == 0)
> +    __cp_stat64_statx(st, &xbuf);
> +  return r;
> +}
> +
> +#else /* __ASSUME_STATX && __NR_statx */
> +#include <sysdeps/unix/sysv/linux/mips/mips64/fxstatat64.c>
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
> new file mode 100644
> index 0000000000..f9c28b753b
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
> @@ -0,0 +1,51 @@
> +/* lxstat using old-style Unix stat system call.
> +   Copyright (C) 1991-2021 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 <kernel-features.h>
> +#include <sys/syscall.h>
> +#if defined(__ASSUME_STATX) && defined(__NR_statx)
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <kernel_stat.h>
> +#include <sysdep.h>
> +#include <statx_cp.h>
> +
> +/* Get information about the file NAME in BUF.  */
> +int
> +__lxstat (int vers, const char *name, struct stat *buf)
> +{
> +  switch (vers)
> +    {
> +    case _STAT_VER_KERNEL:
> +      return INLINE_SYSCALL_CALL (lstat, name, buf);
> +
> +    default:
> +      {
> +	struct statx xbuf;
> +	int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, AT_SYMLINK_NOFOLLOW,
> +			STATX_BASIC_STATS, &xbuf);
> +	if (r == 0)
> +	  __cp_stat64_statx((struct stat64 *)buf, &xbuf);
> +	return r;
> +      }
> +    }
> +}
> +
> +#else /* __ASSUME_STATX && __NR_statx */
> +#include <sysdeps/unix/sysv/linux/mips/lxstat.c>
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
> new file mode 100644
> index 0000000000..927c542ca7
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
> @@ -0,0 +1,43 @@
> +/* lxstat64 using 64-bit MIPS lstat system call.
> +   Copyright (C) 1997-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 <kernel-features.h>
> +#include <sys/syscall.h>
> +#if defined(__ASSUME_STATX) && defined(__NR_statx)
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <kernel_stat.h>
> +#include <sysdep.h>
> +#include <statx_cp.h>
> +
> +/* Get information about the file NAME in BUF.  */
> +int
> +__lxstat64 (int vers, const char *name, struct stat64 *buf)
> +{
> +  struct statx xbuf;
> +  int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, AT_SYMLINK_NOFOLLOW,
> +		STATX_BASIC_STATS, &xbuf);
> +  // cast to struct stat from struct stat64 is OK for N64.
> +  if (r == 0)
> +    __cp_stat64_statx(buf, &xbuf);
> +  return r;
> +}
> +
> +#else /* __ASSUME_STATX && __NR_statx */
> +#include <sysdeps/unix/sysv/linux/mips/mips64/lxstat64.c>
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
> new file mode 100644
> index 0000000000..6c735e5365
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
> @@ -0,0 +1,51 @@
> +/* xstat using old-style Unix stat system call.
> +   Copyright (C) 1991-2021 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 <kernel-features.h>
> +#include <sys/syscall.h>
> +#if defined(__ASSUME_STATX) && defined(__NR_statx)
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <kernel_stat.h>
> +#include <sysdep.h>
> +#include <statx_cp.h>
> +
> +/* Get information about the file NAME in BUF.  */
> +int
> +__xstat (int vers, const char *name, struct stat *buf)
> +{
> +  switch (vers)
> +    {
> +    case _STAT_VER_KERNEL:
> +      return INLINE_SYSCALL_CALL (stat, name, buf);
> +
> +    default:
> +      {
> +	struct statx xbuf;
> +	int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, 0,
> +			STATX_BASIC_STATS, &xbuf);
> +	if (r == 0)
> +	  __cp_stat64_statx((struct stat64 *)buf, &xbuf);
> +	return r;
> +      }
> +    }
> +}
> +
> +#else /* __ASSUME_STATX && __NR_statx */
> +#include <sysdeps/unix/sysv/linux/mips/xstat.c>
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
> new file mode 100644
> index 0000000000..84db1b7a85
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
> @@ -0,0 +1,43 @@
> +/* xstat64 using 64-bit MIPS stat system call.
> +   Copyright (C) 1991-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 <kernel-features.h>
> +#include <sys/syscall.h>
> +#if defined(__ASSUME_STATX) && defined(__NR_statx)
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <kernel_stat.h>
> +#include <sysdep.h>
> +#include <statx_cp.h>
> +
> +/* Get information about the file NAME in BUF.  */
> +
> +int
> +__xstat64 (int vers, const char *name, struct stat64 *buf)
> +{
> +  struct statx xbuf;
> +  int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, 0,
> +		STATX_BASIC_STATS, &xbuf);
> +  if (r == 0)
> +    __cp_stat64_statx(buf, &xbuf);
> +  return r;
> +}
> +
> +#else /* __ASSUME_STATX && __NR_statx */
> +#include <sysdeps/unix/sysv/linux/mips/mips64/xstat64.c>
> +#endif
>
YunQiang Su March 17, 2021, 7:25 a.m. UTC | #2
> -----邮件原件-----
> 发件人: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> 发送时间: 2021年3月12日 20:35
> 收件人: YunQiang Su <yunqiang.su@cipunited.com>;
> libc-alpha@sourceware.org
> 抄送: aurelien@aurel32.net; jiaxun.yang@flygoat.com; macro@orcam.me.uk
> 主题: Re: [PATCH] MIPS: fix y2106 problem on N64 with statx
> 
> 
> 
> On 12/03/2021 00:49, YunQiang Su wrote:
> > the stat series syscall of N64 use uint32 as its time.
> > Glibc converts it to int64 then. For example a file with timestamp -1:
> >    syscall(stat) gets 0xffffffff
> >    Glibc convert it to 0x00000000ffffffff Then, -1 becomes a time in
> > y2106.
> 
> Sigh, another MIPS ABI idissionacracy that I am not aware about...
> 
> >
> > In this patch, we use statx syscall to replace stat-series syscall.
> > statx always return int64 timestamp, and the `struct stat' in userland
> > of N64 always has 64bit timestamp. We can convert between them without
> > any problem
> Some comments below.
> 
> > ---
> >  io/tst-fstatat.c                              | 26 +++++++-
> >  sysdeps/unix/sysv/linux/fstatat64.c           |  8 ++-
> >  .../unix/sysv/linux/mips/mips64/n64/fstatat.c | 52 +++++++++++++++
> > .../unix/sysv/linux/mips/mips64/n64/fxstat.c  | 51 +++++++++++++++
> >  .../sysv/linux/mips/mips64/n64/fxstat64.c     | 43 +++++++++++++
> >  .../sysv/linux/mips/mips64/n64/fxstatat.c     | 63
> +++++++++++++++++++
> >  .../sysv/linux/mips/mips64/n64/fxstatat64.c   | 53 ++++++++++++++++
> >  .../unix/sysv/linux/mips/mips64/n64/lxstat.c  | 51 +++++++++++++++
> >  .../sysv/linux/mips/mips64/n64/lxstat64.c     | 43 +++++++++++++
> >  .../unix/sysv/linux/mips/mips64/n64/xstat.c   | 51 +++++++++++++++
> >  .../unix/sysv/linux/mips/mips64/n64/xstat64.c | 43 +++++++++++++
> >  11 files changed, 482 insertions(+), 2 deletions(-)  create mode
> > 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
> >  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
> >  create mode 100644
> sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
> >  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
> >  create mode 100644
> > sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
> >  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
> >  create mode 100644
> sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
> >  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
> >  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
> >
> > diff --git a/io/tst-fstatat.c b/io/tst-fstatat.c index
> > 4766bb2e71..8297b14479 100644
> > --- a/io/tst-fstatat.c
> > +++ b/io/tst-fstatat.c
> > @@ -5,7 +5,7 @@
> >  #include <string.h>
> >  #include <unistd.h>
> >  #include <sys/stat.h>
> > -
> > +#include <kernel-features.h>
> >
> >  static void prepare (void);
> >  #define PREPARE(argc, argv) prepare () @@ -134,6 +134,30 @@ do_test
> > (void)
> >        puts ("stat results do not match");
> >        return 1;
> >      }
> > +#if defined(__mips64) &&  (_MIPS_SIM == _ABI64) &&
> > +defined(__ASSUME_STATX)
> > +  /* fstatat syscall has y2106 problem on MIPS N64
> > +     Now we use statx to implement *stat* functions
> > +     So the problem should have gone */
> > +  struct timespec tm_1[2] = {{-1, 0}, {-1, 0}};
> > +  if (utimensat(dir_fd, "some-file", tm_1, 0) != 0)
> > +    {
> > +      puts ("utimensat fail");
> > +      return 1;
> > +    }
> > +
> > +  if (fstatat64 (dir_fd, "some-file", &st2, 0) != 0)
> > +    {
> > +      puts ("fstatat64 failed");
> > +      return 1;
> > +    }
> > +
> > +  if (st2.st_mtim.tv_sec != -1
> > +      || st2.st_atim.tv_sec != -1)
> > +    {
> > +      puts ("fstatat64 has y2106 problem?");
> > +      return 1;
> > +    }
> > +#endif
> >
> >    if (unlinkat (dir_fd, "some-file", 0) != 0)
> >      {
> 
> I am about to push a way to check in if the file has support for y2038 [1], so
> please use this instead.  Also this tests does not really check any file
> timestamps so I don't think this is the place add this warning (and making it
> mips specific it not a good approach, neither by using __ASSUME_STATX
> which is Linux specific and it should be used on internal tests).
> 
> Instead please add the y2106 checks on Linux specific tests:
> 
>   sysdeps/unix/sysv/linux/tst-futimens.c
>   sysdeps/unix/sysv/linux/tst-utime.c
>   sysdeps/unix/sysv/linux/tst-utimes.c
> 
> Since they use fstat to check against the set timestamps.
> 
> [1]
> https://patchwork.sourceware.org/project/glibc/patch/20210311123557.348
> 6677-1-adhemerval.zanella@linaro.org/
> 

That's a great idea to add the test here.

> > diff --git a/sysdeps/unix/sysv/linux/fstatat64.c
> > b/sysdeps/unix/sysv/linux/fstatat64.c
> > index 490226a8ec..220321be9c 100644
> > --- a/sysdeps/unix/sysv/linux/fstatat64.c
> > +++ b/sysdeps/unix/sysv/linux/fstatat64.c
> > @@ -47,15 +47,21 @@ __fstatat64_time64 (int fd, const char *file, struct
> __stat64_t64 *buf,
> >    int r;
> >
> >  #if (__WORDSIZE == 32 \
> > -     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE ==
> 32))
> > +     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE ==
> 32)) \
> > +    || defined(__mips64)
> 
> I would prefer to add a define added on kernel_stat.h, even though it seems
> from a briefly inspecting on kernel sources that it is only mips64 that has this
> issue.  I think we should avoid the preprocessor archirecture define on Linux
> generic code.
> 
> So add a STAT_KERNEL_UNSIGNED_TIME_T with a proper comment on
> mips.h kernel_stat.h
> 

Yes. It is much cleaner.

> >    /* 32-bit kABI with default 64-bit time_t, e.g. arc, riscv32.   Also
> >       64-bit time_t support is done through statx syscall.  */
> > +  /* Also use statx syscall for MIPS N64, since newfstatat has y2106
> > + problem */
> >    struct statx tmp;
> 
> Merge it with the previous comment.
> 
> >    r = INTERNAL_SYSCALL_CALL (statx, fd, file, AT_NO_AUTOMOUNT |
> flag,
> >  			     STATX_BASIC_STATS, &tmp);
> >    if (r == 0)
> >      {
> > +#if defined(__mips64) && (_MIPS_SIM == _ABI64)
> > +      __cp_stat64_statx (buf, &tmp);
> > +#else
> >        __cp_stat64_t64_statx (buf, &tmp);
> > +#endif
> >        return 0;
> >      }
> >    if (-r != ENOSYS)
> > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
> > b/sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
> > new file mode 100644
> > index 0000000000..5000cd0715
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
> > @@ -0,0 +1,52 @@
> > +/* Copyright (C) 2005-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/>.  */
> > +
> > +/* Ho hum, since fxstatat == fxstatat64 we must get rid of the
> > +   prototype or gcc will complain since they don't strictly match.
> > +*/
> > +
> > +#include <kernel-features.h>
> > +#include <sys/syscall.h>
> > +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include <errno.h>
> > +#include <fcntl.h> #include <stddef.h> #include <stdio.h> #include
> > +<string.h> #include <sys/stat.h>
> > +
> > +#include <sysdep.h>
> > +#include <kernel_stat.h>
> > +#include <statx_cp.h>
> > +
> > +
> > +/* Get information about the file NAME relative to FD in ST.  */ int
> > +__fstatat (int fd, const char *file, struct stat *st, int flag) {
> > +  struct statx xbuf;
> > +  int r = INLINE_SYSCALL (statx, 5, fd, file, flag&AT_SYMLINK_NOFOLLOW,
> > +	      STATX_BASIC_STATS, &xbuf);
> > +  if (r == 0)
> > +    __cp_stat64_statx((struct stat64 *)st, &xbuf);
> > +  return r;
> > +}
> > +
> > +weak_alias (__fstatat, fstatat)
> > +
> > +#else /* __ASSUME_STATX && __NR_statx */ #include
> > +<sysdeps/unix/sysv/linux/fstatat.c>
> > +#endif
> 
> I see no point in such optimization, which adds another mips specific file.
> If glibc is still alive near 2106 most likely we would had increases the
> minimum kernel version to include __NR_statx...
> 

linux/fstatat.c has no statx call. So, should we do the similar like fstatat64?

> > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
> > b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
> > new file mode 100644
> > index 0000000000..acd929dfaa
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
> > @@ -0,0 +1,51 @@
> > +/* fxstat using old-style Unix stat system call.
> > +   Copyright (C) 1991-2021 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 <kernel-features.h>
> > +#include <sys/syscall.h>
> > +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
> > +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
> > +<sysdep.h> #include <statx_cp.h>
> > +
> > +/* Get information about the file NAME in BUF.  */ int __fxstat (int
> > +vers, int fd, struct stat *buf) {
> > +  switch (vers)
> > +    {
> > +    case _STAT_VER_KERNEL:
> > +      return INLINE_SYSCALL_CALL (fstat, fd, buf);
> > +
> > +    default:
> > +      {
> > +	struct statx xbuf;
> > +	int r = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH,
> > +		      STATX_BASIC_STATS, &xbuf);
> > +	if (r == 0)
> > +	  __cp_stat64_statx((struct stat64 *)buf, &xbuf);
> > +	return r;
> > +      }
> > +    }
> > +}
> > +
> > +#else /* __ASSUME_STATX && __NR_statx */ #include
> > +<sysdeps/unix/sysv/linux/mips/fxstat.c>
> > +#endif
> 
> As for the mips specific implementation, the __fxstat are compatibilty symbols
> and I don't want us to change their semantic.  If user really care about
> y2106 they should use the newer stat symbols.
> 

While the pre-exists binaries do use __fxstat.
With this patch, I think that we can make them work correctly with just libc upgrade.

With the previous binaries, even they use `stat' in source code, the result binaries do use __xstat.

And the problem of Y2106 is not only about Y2106, and it also has problem for Y1969.
It may make some trouble, if we set the timestamp before 1970.

> > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
> > b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
> > new file mode 100644
> > index 0000000000..a8da108347
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
> > @@ -0,0 +1,43 @@
> > +/* fxstat64 using 64-bit MIPS fstat system call.
> > +   Copyright (C) 1997-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 <kernel-features.h>
> > +#include <sys/syscall.h>
> > +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
> > +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
> > +<sysdep.h> #include <statx_cp.h>
> > +
> > +/* Get information about the file FD in BUF.  */
> > +
> > +int
> > +__fxstat64 (int vers, int fd, struct stat64 *buf) {
> > +  struct statx xbuf;
> > +  int r = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH,
> > +	      STATX_BASIC_STATS, &xbuf);
> > +  if (r == 0)
> > +    __cp_stat64_statx(buf, &xbuf);
> > +  return r;
> > +}
> > +
> > +#else /* __ASSUME_STATX && __NR_statx */ #include
> > +<sysdeps/unix/sysv/linux/mips/mips64/fxstat64.c>
> > +#endif
> > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
> > b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
> > new file mode 100644
> > index 0000000000..935888efe6
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
> > @@ -0,0 +1,63 @@
> > +/* Copyright (C) 2005-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/>.  */
> > +
> > +/* Ho hum, since fxstatat == fxstatat64 we must get rid of the
> > +   prototype or gcc will complain since they don't strictly match.
> > +*/
> > +
> > +#include <kernel-features.h>
> > +#include <sys/syscall.h>
> > +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include <errno.h>
> > +#include <fcntl.h> #include <stddef.h> #include <stdio.h> #include
> > +<string.h> #include <sys/stat.h>
> > +
> > +#include <sysdep.h>
> > +#include <kernel_stat.h>
> > +#include <statx_cp.h>
> > +
> > +
> > +/* Get information about the file NAME relative to FD in ST.  */ int
> > +__fxstatat (int vers, int fd, const char *file, struct stat *st, int
> > +flag) {
> > +  switch (vers)
> > +    {
> > +    case _STAT_VER_KERNEL:
> > +	return INLINE_SYSCALL (newfstatat, 4, fd, file, st, flag);
> > +
> > +    case _STAT_VER_LINUX:
> > +      {
> > +	struct statx xbuf;
> > +	int r = INLINE_SYSCALL (statx, 5, fd, file, flag&AT_SYMLINK_NOFOLLOW,
> > +		      STATX_BASIC_STATS, &xbuf);
> > +	if (r == 0)
> > +	  __cp_stat64_statx((struct stat64 *)st, &xbuf);
> > +	return r;
> > +      }
> > +
> > +    default:
> > +      __set_errno (EINVAL);
> > +      return -1;
> > +    }
> > +}
> > +
> > +#else /* __ASSUME_STATX && __NR_statx */ #include
> > +<sysdeps/unix/sysv/linux/mips/mips64/fxstatat.c>
> > +#endif
> > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
> > b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
> > new file mode 100644
> > index 0000000000..80bd0f1d09
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
> > @@ -0,0 +1,53 @@
> > +/* Copyright (C) 2005-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 <kernel-features.h>
> > +#include <sys/syscall.h>
> > +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include <errno.h>
> > +#include <fcntl.h> #include <stddef.h> #include <stdio.h> #include
> > +<string.h> #include <sys/stat.h> #include <kernel_stat.h>
> > +
> > +#include <sysdep.h>
> > +#include <statx_cp.h>
> > +
> > +/* Get information about the file NAME in BUF.  */
> > +
> > +int
> > +__fxstatat64 (int vers, int fd, const char *file, struct stat64 *st,
> > +int flag) {
> > +  if (__builtin_expect (vers != _STAT_VER_LINUX, 0))
> > +    {
> > +      __set_errno (EINVAL);
> > +      return -1;
> > +    }
> > +
> > +  struct statx xbuf;
> > +  int r = INLINE_SYSCALL (statx, 5, fd, file, flag&AT_SYMLINK_NOFOLLOW,
> > +	      STATX_BASIC_STATS, &xbuf);
> > +  if (r == 0)
> > +    __cp_stat64_statx(st, &xbuf);
> > +  return r;
> > +}
> > +
> > +#else /* __ASSUME_STATX && __NR_statx */ #include
> > +<sysdeps/unix/sysv/linux/mips/mips64/fxstatat64.c>
> > +#endif
> > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
> > b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
> > new file mode 100644
> > index 0000000000..f9c28b753b
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
> > @@ -0,0 +1,51 @@
> > +/* lxstat using old-style Unix stat system call.
> > +   Copyright (C) 1991-2021 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 <kernel-features.h>
> > +#include <sys/syscall.h>
> > +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
> > +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
> > +<sysdep.h> #include <statx_cp.h>
> > +
> > +/* Get information about the file NAME in BUF.  */ int __lxstat (int
> > +vers, const char *name, struct stat *buf) {
> > +  switch (vers)
> > +    {
> > +    case _STAT_VER_KERNEL:
> > +      return INLINE_SYSCALL_CALL (lstat, name, buf);
> > +
> > +    default:
> > +      {
> > +	struct statx xbuf;
> > +	int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name,
> AT_SYMLINK_NOFOLLOW,
> > +			STATX_BASIC_STATS, &xbuf);
> > +	if (r == 0)
> > +	  __cp_stat64_statx((struct stat64 *)buf, &xbuf);
> > +	return r;
> > +      }
> > +    }
> > +}
> > +
> > +#else /* __ASSUME_STATX && __NR_statx */ #include
> > +<sysdeps/unix/sysv/linux/mips/lxstat.c>
> > +#endif
> > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
> > b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
> > new file mode 100644
> > index 0000000000..927c542ca7
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
> > @@ -0,0 +1,43 @@
> > +/* lxstat64 using 64-bit MIPS lstat system call.
> > +   Copyright (C) 1997-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 <kernel-features.h>
> > +#include <sys/syscall.h>
> > +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
> > +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
> > +<sysdep.h> #include <statx_cp.h>
> > +
> > +/* Get information about the file NAME in BUF.  */ int
> > +__lxstat64 (int vers, const char *name, struct stat64 *buf) {
> > +  struct statx xbuf;
> > +  int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name,
> AT_SYMLINK_NOFOLLOW,
> > +		STATX_BASIC_STATS, &xbuf);
> > +  // cast to struct stat from struct stat64 is OK for N64.
> > +  if (r == 0)
> > +    __cp_stat64_statx(buf, &xbuf);
> > +  return r;
> > +}
> > +
> > +#else /* __ASSUME_STATX && __NR_statx */ #include
> > +<sysdeps/unix/sysv/linux/mips/mips64/lxstat64.c>
> > +#endif
> > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
> > b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
> > new file mode 100644
> > index 0000000000..6c735e5365
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
> > @@ -0,0 +1,51 @@
> > +/* xstat using old-style Unix stat system call.
> > +   Copyright (C) 1991-2021 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 <kernel-features.h>
> > +#include <sys/syscall.h>
> > +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
> > +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
> > +<sysdep.h> #include <statx_cp.h>
> > +
> > +/* Get information about the file NAME in BUF.  */ int __xstat (int
> > +vers, const char *name, struct stat *buf) {
> > +  switch (vers)
> > +    {
> > +    case _STAT_VER_KERNEL:
> > +      return INLINE_SYSCALL_CALL (stat, name, buf);
> > +
> > +    default:
> > +      {
> > +	struct statx xbuf;
> > +	int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, 0,
> > +			STATX_BASIC_STATS, &xbuf);
> > +	if (r == 0)
> > +	  __cp_stat64_statx((struct stat64 *)buf, &xbuf);
> > +	return r;
> > +      }
> > +    }
> > +}
> > +
> > +#else /* __ASSUME_STATX && __NR_statx */ #include
> > +<sysdeps/unix/sysv/linux/mips/xstat.c>
> > +#endif
> > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
> > b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
> > new file mode 100644
> > index 0000000000..84db1b7a85
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
> > @@ -0,0 +1,43 @@
> > +/* xstat64 using 64-bit MIPS stat system call.
> > +   Copyright (C) 1991-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 <kernel-features.h>
> > +#include <sys/syscall.h>
> > +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
> > +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
> > +<sysdep.h> #include <statx_cp.h>
> > +
> > +/* Get information about the file NAME in BUF.  */
> > +
> > +int
> > +__xstat64 (int vers, const char *name, struct stat64 *buf) {
> > +  struct statx xbuf;
> > +  int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, 0,
> > +		STATX_BASIC_STATS, &xbuf);
> > +  if (r == 0)
> > +    __cp_stat64_statx(buf, &xbuf);
> > +  return r;
> > +}
> > +
> > +#else /* __ASSUME_STATX && __NR_statx */ #include
> > +<sysdeps/unix/sysv/linux/mips/mips64/xstat64.c>
> > +#endif
> >
Adhemerval Zanella March 17, 2021, 11:27 a.m. UTC | #3
On 17/03/2021 04:25, yunqiang.su@cipunited.com wrote:
> 
> 
>> -----邮件原件-----
>> 发件人: Adhemerval Zanella <adhemerval.zanella@linaro.org>
>> 发送时间: 2021年3月12日 20:35
>> 收件人: YunQiang Su <yunqiang.su@cipunited.com>;
>> libc-alpha@sourceware.org
>> 抄送: aurelien@aurel32.net; jiaxun.yang@flygoat.com; macro@orcam.me.uk
>> 主题: Re: [PATCH] MIPS: fix y2106 problem on N64 with statx
>>
>>
>>
>> On 12/03/2021 00:49, YunQiang Su wrote:
>>> the stat series syscall of N64 use uint32 as its time.
>>> Glibc converts it to int64 then. For example a file with timestamp -1:
>>>    syscall(stat) gets 0xffffffff
>>>    Glibc convert it to 0x00000000ffffffff Then, -1 becomes a time in
>>> y2106.
>>
>> Sigh, another MIPS ABI idissionacracy that I am not aware about...
>>
>>>
>>> In this patch, we use statx syscall to replace stat-series syscall.
>>> statx always return int64 timestamp, and the `struct stat' in userland
>>> of N64 always has 64bit timestamp. We can convert between them without
>>> any problem
>> Some comments below.
>>
>>> ---
>>>  io/tst-fstatat.c                              | 26 +++++++-
>>>  sysdeps/unix/sysv/linux/fstatat64.c           |  8 ++-
>>>  .../unix/sysv/linux/mips/mips64/n64/fstatat.c | 52 +++++++++++++++
>>> .../unix/sysv/linux/mips/mips64/n64/fxstat.c  | 51 +++++++++++++++
>>>  .../sysv/linux/mips/mips64/n64/fxstat64.c     | 43 +++++++++++++
>>>  .../sysv/linux/mips/mips64/n64/fxstatat.c     | 63
>> +++++++++++++++++++
>>>  .../sysv/linux/mips/mips64/n64/fxstatat64.c   | 53 ++++++++++++++++
>>>  .../unix/sysv/linux/mips/mips64/n64/lxstat.c  | 51 +++++++++++++++
>>>  .../sysv/linux/mips/mips64/n64/lxstat64.c     | 43 +++++++++++++
>>>  .../unix/sysv/linux/mips/mips64/n64/xstat.c   | 51 +++++++++++++++
>>>  .../unix/sysv/linux/mips/mips64/n64/xstat64.c | 43 +++++++++++++
>>>  11 files changed, 482 insertions(+), 2 deletions(-)  create mode
>>> 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
>>>  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
>>>  create mode 100644
>> sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
>>>  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
>>>  create mode 100644
>>> sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
>>>  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
>>>  create mode 100644
>> sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
>>>  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
>>>  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
>>>
>>> diff --git a/io/tst-fstatat.c b/io/tst-fstatat.c index
>>> 4766bb2e71..8297b14479 100644
>>> --- a/io/tst-fstatat.c
>>> +++ b/io/tst-fstatat.c
>>> @@ -5,7 +5,7 @@
>>>  #include <string.h>
>>>  #include <unistd.h>
>>>  #include <sys/stat.h>
>>> -
>>> +#include <kernel-features.h>
>>>
>>>  static void prepare (void);
>>>  #define PREPARE(argc, argv) prepare () @@ -134,6 +134,30 @@ do_test
>>> (void)
>>>        puts ("stat results do not match");
>>>        return 1;
>>>      }
>>> +#if defined(__mips64) &&  (_MIPS_SIM == _ABI64) &&
>>> +defined(__ASSUME_STATX)
>>> +  /* fstatat syscall has y2106 problem on MIPS N64
>>> +     Now we use statx to implement *stat* functions
>>> +     So the problem should have gone */
>>> +  struct timespec tm_1[2] = {{-1, 0}, {-1, 0}};
>>> +  if (utimensat(dir_fd, "some-file", tm_1, 0) != 0)
>>> +    {
>>> +      puts ("utimensat fail");
>>> +      return 1;
>>> +    }
>>> +
>>> +  if (fstatat64 (dir_fd, "some-file", &st2, 0) != 0)
>>> +    {
>>> +      puts ("fstatat64 failed");
>>> +      return 1;
>>> +    }
>>> +
>>> +  if (st2.st_mtim.tv_sec != -1
>>> +      || st2.st_atim.tv_sec != -1)
>>> +    {
>>> +      puts ("fstatat64 has y2106 problem?");
>>> +      return 1;
>>> +    }
>>> +#endif
>>>
>>>    if (unlinkat (dir_fd, "some-file", 0) != 0)
>>>      {
>>
>> I am about to push a way to check in if the file has support for y2038 [1], so
>> please use this instead.  Also this tests does not really check any file
>> timestamps so I don't think this is the place add this warning (and making it
>> mips specific it not a good approach, neither by using __ASSUME_STATX
>> which is Linux specific and it should be used on internal tests).
>>
>> Instead please add the y2106 checks on Linux specific tests:
>>
>>   sysdeps/unix/sysv/linux/tst-futimens.c
>>   sysdeps/unix/sysv/linux/tst-utime.c
>>   sysdeps/unix/sysv/linux/tst-utimes.c
>>
>> Since they use fstat to check against the set timestamps.
>>
>> [1]
>> https://patchwork.sourceware.org/project/glibc/patch/20210311123557.348
>> 6677-1-adhemerval.zanella@linaro.org/
>>
> 
> That's a great idea to add the test here.
> 
>>> diff --git a/sysdeps/unix/sysv/linux/fstatat64.c
>>> b/sysdeps/unix/sysv/linux/fstatat64.c
>>> index 490226a8ec..220321be9c 100644
>>> --- a/sysdeps/unix/sysv/linux/fstatat64.c
>>> +++ b/sysdeps/unix/sysv/linux/fstatat64.c
>>> @@ -47,15 +47,21 @@ __fstatat64_time64 (int fd, const char *file, struct
>> __stat64_t64 *buf,
>>>    int r;
>>>
>>>  #if (__WORDSIZE == 32 \
>>> -     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE ==
>> 32))
>>> +     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE ==
>> 32)) \
>>> +    || defined(__mips64)
>>
>> I would prefer to add a define added on kernel_stat.h, even though it seems
>> from a briefly inspecting on kernel sources that it is only mips64 that has this
>> issue.  I think we should avoid the preprocessor archirecture define on Linux
>> generic code.
>>
>> So add a STAT_KERNEL_UNSIGNED_TIME_T with a proper comment on
>> mips.h kernel_stat.h
>>
> 
> Yes. It is much cleaner.
> 
>>>    /* 32-bit kABI with default 64-bit time_t, e.g. arc, riscv32.   Also
>>>       64-bit time_t support is done through statx syscall.  */
>>> +  /* Also use statx syscall for MIPS N64, since newfstatat has y2106
>>> + problem */
>>>    struct statx tmp;
>>
>> Merge it with the previous comment.
>>
>>>    r = INTERNAL_SYSCALL_CALL (statx, fd, file, AT_NO_AUTOMOUNT |
>> flag,
>>>  			     STATX_BASIC_STATS, &tmp);
>>>    if (r == 0)
>>>      {
>>> +#if defined(__mips64) && (_MIPS_SIM == _ABI64)
>>> +      __cp_stat64_statx (buf, &tmp);
>>> +#else
>>>        __cp_stat64_t64_statx (buf, &tmp);
>>> +#endif
>>>        return 0;
>>>      }
>>>    if (-r != ENOSYS)
>>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
>>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
>>> new file mode 100644
>>> index 0000000000..5000cd0715
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
>>> @@ -0,0 +1,52 @@
>>> +/* Copyright (C) 2005-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/>.  */
>>> +
>>> +/* Ho hum, since fxstatat == fxstatat64 we must get rid of the
>>> +   prototype or gcc will complain since they don't strictly match.
>>> +*/
>>> +
>>> +#include <kernel-features.h>
>>> +#include <sys/syscall.h>
>>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include <errno.h>
>>> +#include <fcntl.h> #include <stddef.h> #include <stdio.h> #include
>>> +<string.h> #include <sys/stat.h>
>>> +
>>> +#include <sysdep.h>
>>> +#include <kernel_stat.h>
>>> +#include <statx_cp.h>
>>> +
>>> +
>>> +/* Get information about the file NAME relative to FD in ST.  */ int
>>> +__fstatat (int fd, const char *file, struct stat *st, int flag) {
>>> +  struct statx xbuf;
>>> +  int r = INLINE_SYSCALL (statx, 5, fd, file, flag&AT_SYMLINK_NOFOLLOW,
>>> +	      STATX_BASIC_STATS, &xbuf);
>>> +  if (r == 0)
>>> +    __cp_stat64_statx((struct stat64 *)st, &xbuf);
>>> +  return r;
>>> +}
>>> +
>>> +weak_alias (__fstatat, fstatat)
>>> +
>>> +#else /* __ASSUME_STATX && __NR_statx */ #include
>>> +<sysdeps/unix/sysv/linux/fstatat.c>
>>> +#endif
>>
>> I see no point in such optimization, which adds another mips specific file.
>> If glibc is still alive near 2106 most likely we would had increases the
>> minimum kernel version to include __NR_statx...
>>
> 
> linux/fstatat.c has no statx call. So, should we do the similar like fstatat64?

Even though it is not the default, non LFS interface are legacy ones.
y2038 support, for instance, is only supported with LFS interfaces.

So it is up to you if you want to fix on fstatat.c, it should also
fix the s390 issue with missing nanosecond support.

> 
>>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
>>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
>>> new file mode 100644
>>> index 0000000000..acd929dfaa
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
>>> @@ -0,0 +1,51 @@
>>> +/* fxstat using old-style Unix stat system call.
>>> +   Copyright (C) 1991-2021 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 <kernel-features.h>
>>> +#include <sys/syscall.h>
>>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
>>> +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
>>> +<sysdep.h> #include <statx_cp.h>
>>> +
>>> +/* Get information about the file NAME in BUF.  */ int __fxstat (int
>>> +vers, int fd, struct stat *buf) {
>>> +  switch (vers)
>>> +    {
>>> +    case _STAT_VER_KERNEL:
>>> +      return INLINE_SYSCALL_CALL (fstat, fd, buf);
>>> +
>>> +    default:
>>> +      {
>>> +	struct statx xbuf;
>>> +	int r = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH,
>>> +		      STATX_BASIC_STATS, &xbuf);
>>> +	if (r == 0)
>>> +	  __cp_stat64_statx((struct stat64 *)buf, &xbuf);
>>> +	return r;
>>> +      }
>>> +    }
>>> +}
>>> +
>>> +#else /* __ASSUME_STATX && __NR_statx */ #include
>>> +<sysdeps/unix/sysv/linux/mips/fxstat.c>
>>> +#endif
>>
>> As for the mips specific implementation, the __fxstat are compatibilty symbols
>> and I don't want us to change their semantic.  If user really care about
>> y2106 they should use the newer stat symbols.
>>
> 
> While the pre-exists binaries do use __fxstat.
> With this patch, I think that we can make them work correctly with just libc upgrade.
> 
> With the previous binaries, even they use `stat' in source code, the result binaries do use __xstat.
> 
> And the problem of Y2106 is not only about Y2106, and it also has problem for Y1969.
> It may make some trouble, if we set the timestamp before 1970.

But is this really an issue for MIPS in a sense legacy programs will
be affected in the referred timeframe? If we limit the fix for
newly built binaries it simplifies a lot the code base.

My xstat refactor work was really to avoid the nasty profileration of 
arch-specific implementations and I think we are getting a step back
by adding back this specific fix.

If you really want to fix on legacy compat implementation, I think
it would be better to make in arch neutral way: 1. make xstat, lxstat,
fxstat call fxstatat, 2. add statx on fxstatat/fxstatat64, and 3.
convert back the struct to the _STAT_VER. 

> 
>>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
>>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
>>> new file mode 100644
>>> index 0000000000..a8da108347
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
>>> @@ -0,0 +1,43 @@
>>> +/* fxstat64 using 64-bit MIPS fstat system call.
>>> +   Copyright (C) 1997-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 <kernel-features.h>
>>> +#include <sys/syscall.h>
>>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
>>> +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
>>> +<sysdep.h> #include <statx_cp.h>
>>> +
>>> +/* Get information about the file FD in BUF.  */
>>> +
>>> +int
>>> +__fxstat64 (int vers, int fd, struct stat64 *buf) {
>>> +  struct statx xbuf;
>>> +  int r = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH,
>>> +	      STATX_BASIC_STATS, &xbuf);
>>> +  if (r == 0)
>>> +    __cp_stat64_statx(buf, &xbuf);
>>> +  return r;
>>> +}
>>> +
>>> +#else /* __ASSUME_STATX && __NR_statx */ #include
>>> +<sysdeps/unix/sysv/linux/mips/mips64/fxstat64.c>
>>> +#endif
>>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
>>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
>>> new file mode 100644
>>> index 0000000000..935888efe6
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
>>> @@ -0,0 +1,63 @@
>>> +/* Copyright (C) 2005-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/>.  */
>>> +
>>> +/* Ho hum, since fxstatat == fxstatat64 we must get rid of the
>>> +   prototype or gcc will complain since they don't strictly match.
>>> +*/
>>> +
>>> +#include <kernel-features.h>
>>> +#include <sys/syscall.h>
>>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include <errno.h>
>>> +#include <fcntl.h> #include <stddef.h> #include <stdio.h> #include
>>> +<string.h> #include <sys/stat.h>
>>> +
>>> +#include <sysdep.h>
>>> +#include <kernel_stat.h>
>>> +#include <statx_cp.h>
>>> +
>>> +
>>> +/* Get information about the file NAME relative to FD in ST.  */ int
>>> +__fxstatat (int vers, int fd, const char *file, struct stat *st, int
>>> +flag) {
>>> +  switch (vers)
>>> +    {
>>> +    case _STAT_VER_KERNEL:
>>> +	return INLINE_SYSCALL (newfstatat, 4, fd, file, st, flag);
>>> +
>>> +    case _STAT_VER_LINUX:
>>> +      {
>>> +	struct statx xbuf;
>>> +	int r = INLINE_SYSCALL (statx, 5, fd, file, flag&AT_SYMLINK_NOFOLLOW,
>>> +		      STATX_BASIC_STATS, &xbuf);
>>> +	if (r == 0)
>>> +	  __cp_stat64_statx((struct stat64 *)st, &xbuf);
>>> +	return r;
>>> +      }
>>> +
>>> +    default:
>>> +      __set_errno (EINVAL);
>>> +      return -1;
>>> +    }
>>> +}
>>> +
>>> +#else /* __ASSUME_STATX && __NR_statx */ #include
>>> +<sysdeps/unix/sysv/linux/mips/mips64/fxstatat.c>
>>> +#endif
>>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
>>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
>>> new file mode 100644
>>> index 0000000000..80bd0f1d09
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
>>> @@ -0,0 +1,53 @@
>>> +/* Copyright (C) 2005-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 <kernel-features.h>
>>> +#include <sys/syscall.h>
>>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include <errno.h>
>>> +#include <fcntl.h> #include <stddef.h> #include <stdio.h> #include
>>> +<string.h> #include <sys/stat.h> #include <kernel_stat.h>
>>> +
>>> +#include <sysdep.h>
>>> +#include <statx_cp.h>
>>> +
>>> +/* Get information about the file NAME in BUF.  */
>>> +
>>> +int
>>> +__fxstatat64 (int vers, int fd, const char *file, struct stat64 *st,
>>> +int flag) {
>>> +  if (__builtin_expect (vers != _STAT_VER_LINUX, 0))
>>> +    {
>>> +      __set_errno (EINVAL);
>>> +      return -1;
>>> +    }
>>> +
>>> +  struct statx xbuf;
>>> +  int r = INLINE_SYSCALL (statx, 5, fd, file, flag&AT_SYMLINK_NOFOLLOW,
>>> +	      STATX_BASIC_STATS, &xbuf);
>>> +  if (r == 0)
>>> +    __cp_stat64_statx(st, &xbuf);
>>> +  return r;
>>> +}
>>> +
>>> +#else /* __ASSUME_STATX && __NR_statx */ #include
>>> +<sysdeps/unix/sysv/linux/mips/mips64/fxstatat64.c>
>>> +#endif
>>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
>>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
>>> new file mode 100644
>>> index 0000000000..f9c28b753b
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
>>> @@ -0,0 +1,51 @@
>>> +/* lxstat using old-style Unix stat system call.
>>> +   Copyright (C) 1991-2021 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 <kernel-features.h>
>>> +#include <sys/syscall.h>
>>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
>>> +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
>>> +<sysdep.h> #include <statx_cp.h>
>>> +
>>> +/* Get information about the file NAME in BUF.  */ int __lxstat (int
>>> +vers, const char *name, struct stat *buf) {
>>> +  switch (vers)
>>> +    {
>>> +    case _STAT_VER_KERNEL:
>>> +      return INLINE_SYSCALL_CALL (lstat, name, buf);
>>> +
>>> +    default:
>>> +      {
>>> +	struct statx xbuf;
>>> +	int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name,
>> AT_SYMLINK_NOFOLLOW,
>>> +			STATX_BASIC_STATS, &xbuf);
>>> +	if (r == 0)
>>> +	  __cp_stat64_statx((struct stat64 *)buf, &xbuf);
>>> +	return r;
>>> +      }
>>> +    }
>>> +}
>>> +
>>> +#else /* __ASSUME_STATX && __NR_statx */ #include
>>> +<sysdeps/unix/sysv/linux/mips/lxstat.c>
>>> +#endif
>>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
>>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
>>> new file mode 100644
>>> index 0000000000..927c542ca7
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
>>> @@ -0,0 +1,43 @@
>>> +/* lxstat64 using 64-bit MIPS lstat system call.
>>> +   Copyright (C) 1997-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 <kernel-features.h>
>>> +#include <sys/syscall.h>
>>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
>>> +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
>>> +<sysdep.h> #include <statx_cp.h>
>>> +
>>> +/* Get information about the file NAME in BUF.  */ int
>>> +__lxstat64 (int vers, const char *name, struct stat64 *buf) {
>>> +  struct statx xbuf;
>>> +  int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name,
>> AT_SYMLINK_NOFOLLOW,
>>> +		STATX_BASIC_STATS, &xbuf);
>>> +  // cast to struct stat from struct stat64 is OK for N64.
>>> +  if (r == 0)
>>> +    __cp_stat64_statx(buf, &xbuf);
>>> +  return r;
>>> +}
>>> +
>>> +#else /* __ASSUME_STATX && __NR_statx */ #include
>>> +<sysdeps/unix/sysv/linux/mips/mips64/lxstat64.c>
>>> +#endif
>>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
>>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
>>> new file mode 100644
>>> index 0000000000..6c735e5365
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
>>> @@ -0,0 +1,51 @@
>>> +/* xstat using old-style Unix stat system call.
>>> +   Copyright (C) 1991-2021 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 <kernel-features.h>
>>> +#include <sys/syscall.h>
>>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
>>> +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
>>> +<sysdep.h> #include <statx_cp.h>
>>> +
>>> +/* Get information about the file NAME in BUF.  */ int __xstat (int
>>> +vers, const char *name, struct stat *buf) {
>>> +  switch (vers)
>>> +    {
>>> +    case _STAT_VER_KERNEL:
>>> +      return INLINE_SYSCALL_CALL (stat, name, buf);
>>> +
>>> +    default:
>>> +      {
>>> +	struct statx xbuf;
>>> +	int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, 0,
>>> +			STATX_BASIC_STATS, &xbuf);
>>> +	if (r == 0)
>>> +	  __cp_stat64_statx((struct stat64 *)buf, &xbuf);
>>> +	return r;
>>> +      }
>>> +    }
>>> +}
>>> +
>>> +#else /* __ASSUME_STATX && __NR_statx */ #include
>>> +<sysdeps/unix/sysv/linux/mips/xstat.c>
>>> +#endif
>>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
>>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
>>> new file mode 100644
>>> index 0000000000..84db1b7a85
>>> --- /dev/null
>>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
>>> @@ -0,0 +1,43 @@
>>> +/* xstat64 using 64-bit MIPS stat system call.
>>> +   Copyright (C) 1991-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 <kernel-features.h>
>>> +#include <sys/syscall.h>
>>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
>>> +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
>>> +<sysdep.h> #include <statx_cp.h>
>>> +
>>> +/* Get information about the file NAME in BUF.  */
>>> +
>>> +int
>>> +__xstat64 (int vers, const char *name, struct stat64 *buf) {
>>> +  struct statx xbuf;
>>> +  int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, 0,
>>> +		STATX_BASIC_STATS, &xbuf);
>>> +  if (r == 0)
>>> +    __cp_stat64_statx(buf, &xbuf);
>>> +  return r;
>>> +}
>>> +
>>> +#else /* __ASSUME_STATX && __NR_statx */ #include
>>> +<sysdeps/unix/sysv/linux/mips/mips64/xstat64.c>
>>> +#endif
>>>
>
Maciej W. Rozycki March 17, 2021, 10:28 p.m. UTC | #4
On Fri, 12 Mar 2021, Adhemerval Zanella wrote:

> > the stat series syscall of N64 use uint32 as its time.
> > Glibc converts it to int64 then. For example a file with timestamp -1:
> >    syscall(stat) gets 0xffffffff
> >    Glibc convert it to 0x00000000ffffffff
> > Then, -1 becomes a time in y2106.
> 
> Sigh, another MIPS ABI idissionacracy that I am not aware about...

 Someone may have mimicked IRIX too much I guess.  Or it's just a plain 
oversight.

  Maciej
YunQiang Su March 18, 2021, 6:05 a.m. UTC | #5
> -----邮件原件-----
> 发件人: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> 发送时间: 2021年3月17日 19:27
> 收件人: yunqiang.su@cipunited.com; libc-alpha@sourceware.org
> 抄送: aurelien@aurel32.net; jiaxun.yang@flygoat.com; macro@orcam.me.uk
> 主题: Re: 回复: [PATCH] MIPS: fix y2106 problem on N64 with statx
> 
> 
> 
> On 17/03/2021 04:25, yunqiang.su@cipunited.com wrote:
> >
> >
> >> -----邮件原件-----
> >> 发件人: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> >> 发送时间: 2021年3月12日 20:35
> >> 收件人: YunQiang Su <yunqiang.su@cipunited.com>;
> >> libc-alpha@sourceware.org
> >> 抄送: aurelien@aurel32.net; jiaxun.yang@flygoat.com;
> macro@orcam.me.uk
> >> 主题: Re: [PATCH] MIPS: fix y2106 problem on N64 with statx
> >>
> >>
> >>
> >> On 12/03/2021 00:49, YunQiang Su wrote:
> >>> the stat series syscall of N64 use uint32 as its time.
> >>> Glibc converts it to int64 then. For example a file with timestamp -1:
> >>>    syscall(stat) gets 0xffffffff
> >>>    Glibc convert it to 0x00000000ffffffff Then, -1 becomes a time in
> >>> y2106.
> >>
> >> Sigh, another MIPS ABI idissionacracy that I am not aware about...
> >>
> >>>
> >>> In this patch, we use statx syscall to replace stat-series syscall.
> >>> statx always return int64 timestamp, and the `struct stat' in
> >>> userland of N64 always has 64bit timestamp. We can convert between
> >>> them without any problem
> >> Some comments below.
> >>
> >>> ---
> >>>  io/tst-fstatat.c                              | 26 +++++++-
> >>>  sysdeps/unix/sysv/linux/fstatat64.c           |  8 ++-
> >>>  .../unix/sysv/linux/mips/mips64/n64/fstatat.c | 52 +++++++++++++++
> >>> .../unix/sysv/linux/mips/mips64/n64/fxstat.c  | 51 +++++++++++++++
> >>>  .../sysv/linux/mips/mips64/n64/fxstat64.c     | 43 +++++++++++++
> >>>  .../sysv/linux/mips/mips64/n64/fxstatat.c     | 63
> >> +++++++++++++++++++
> >>>  .../sysv/linux/mips/mips64/n64/fxstatat64.c   | 53
> ++++++++++++++++
> >>>  .../unix/sysv/linux/mips/mips64/n64/lxstat.c  | 51 +++++++++++++++
> >>>  .../sysv/linux/mips/mips64/n64/lxstat64.c     | 43 +++++++++++++
> >>>  .../unix/sysv/linux/mips/mips64/n64/xstat.c   | 51 +++++++++++++++
> >>>  .../unix/sysv/linux/mips/mips64/n64/xstat64.c | 43 +++++++++++++
> >>>  11 files changed, 482 insertions(+), 2 deletions(-)  create mode
> >>> 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
> >>>  create mode 100644
> sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
> >>>  create mode 100644
> >> sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
> >>>  create mode 100644
> >>> sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
> >>>  create mode 100644
> >>> sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
> >>>  create mode 100644
> sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
> >>>  create mode 100644
> >> sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
> >>>  create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
> >>>  create mode 100644
> >>> sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
> >>>
> >>> diff --git a/io/tst-fstatat.c b/io/tst-fstatat.c index
> >>> 4766bb2e71..8297b14479 100644
> >>> --- a/io/tst-fstatat.c
> >>> +++ b/io/tst-fstatat.c
> >>> @@ -5,7 +5,7 @@
> >>>  #include <string.h>
> >>>  #include <unistd.h>
> >>>  #include <sys/stat.h>
> >>> -
> >>> +#include <kernel-features.h>
> >>>
> >>>  static void prepare (void);
> >>>  #define PREPARE(argc, argv) prepare () @@ -134,6 +134,30 @@
> do_test
> >>> (void)
> >>>        puts ("stat results do not match");
> >>>        return 1;
> >>>      }
> >>> +#if defined(__mips64) &&  (_MIPS_SIM == _ABI64) &&
> >>> +defined(__ASSUME_STATX)
> >>> +  /* fstatat syscall has y2106 problem on MIPS N64
> >>> +     Now we use statx to implement *stat* functions
> >>> +     So the problem should have gone */
> >>> +  struct timespec tm_1[2] = {{-1, 0}, {-1, 0}};
> >>> +  if (utimensat(dir_fd, "some-file", tm_1, 0) != 0)
> >>> +    {
> >>> +      puts ("utimensat fail");
> >>> +      return 1;
> >>> +    }
> >>> +
> >>> +  if (fstatat64 (dir_fd, "some-file", &st2, 0) != 0)
> >>> +    {
> >>> +      puts ("fstatat64 failed");
> >>> +      return 1;
> >>> +    }
> >>> +
> >>> +  if (st2.st_mtim.tv_sec != -1
> >>> +      || st2.st_atim.tv_sec != -1)
> >>> +    {
> >>> +      puts ("fstatat64 has y2106 problem?");
> >>> +      return 1;
> >>> +    }
> >>> +#endif
> >>>
> >>>    if (unlinkat (dir_fd, "some-file", 0) != 0)
> >>>      {
> >>
> >> I am about to push a way to check in if the file has support for
> >> y2038 [1], so please use this instead.  Also this tests does not
> >> really check any file timestamps so I don't think this is the place
> >> add this warning (and making it mips specific it not a good approach,
> >> neither by using __ASSUME_STATX which is Linux specific and it should be
> used on internal tests).
> >>
> >> Instead please add the y2106 checks on Linux specific tests:
> >>
> >>   sysdeps/unix/sysv/linux/tst-futimens.c
> >>   sysdeps/unix/sysv/linux/tst-utime.c
> >>   sysdeps/unix/sysv/linux/tst-utimes.c
> >>
> >> Since they use fstat to check against the set timestamps.
> >>
> >> [1]
> >>
> https://patchwork.sourceware.org/project/glibc/patch/20210311123557.3
> >> 48 6677-1-adhemerval.zanella@linaro.org/
> >>
> >
> > That's a great idea to add the test here.
> >
> >>> diff --git a/sysdeps/unix/sysv/linux/fstatat64.c
> >>> b/sysdeps/unix/sysv/linux/fstatat64.c
> >>> index 490226a8ec..220321be9c 100644
> >>> --- a/sysdeps/unix/sysv/linux/fstatat64.c
> >>> +++ b/sysdeps/unix/sysv/linux/fstatat64.c
> >>> @@ -47,15 +47,21 @@ __fstatat64_time64 (int fd, const char *file,
> >>> struct
> >> __stat64_t64 *buf,
> >>>    int r;
> >>>
> >>>  #if (__WORDSIZE == 32 \
> >>> -     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE ==
> >> 32))
> >>> +     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE
> ==
> >> 32)) \
> >>> +    || defined(__mips64)
> >>
> >> I would prefer to add a define added on kernel_stat.h, even though it
> >> seems from a briefly inspecting on kernel sources that it is only
> >> mips64 that has this issue.  I think we should avoid the preprocessor
> >> archirecture define on Linux generic code.
> >>
> >> So add a STAT_KERNEL_UNSIGNED_TIME_T with a proper comment on
> mips.h
> >> kernel_stat.h
> >>
> >
> > Yes. It is much cleaner.
> >
> >>>    /* 32-bit kABI with default 64-bit time_t, e.g. arc, riscv32.   Also
> >>>       64-bit time_t support is done through statx syscall.  */
> >>> +  /* Also use statx syscall for MIPS N64, since newfstatat has
> >>> + y2106 problem */
> >>>    struct statx tmp;
> >>
> >> Merge it with the previous comment.
> >>
> >>>    r = INTERNAL_SYSCALL_CALL (statx, fd, file, AT_NO_AUTOMOUNT |
> >> flag,
> >>>  			     STATX_BASIC_STATS, &tmp);
> >>>    if (r == 0)
> >>>      {
> >>> +#if defined(__mips64) && (_MIPS_SIM == _ABI64)
> >>> +      __cp_stat64_statx (buf, &tmp); #else
> >>>        __cp_stat64_t64_statx (buf, &tmp);
> >>> +#endif
> >>>        return 0;
> >>>      }
> >>>    if (-r != ENOSYS)
> >>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
> >>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
> >>> new file mode 100644
> >>> index 0000000000..5000cd0715
> >>> --- /dev/null
> >>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
> >>> @@ -0,0 +1,52 @@
> >>> +/* Copyright (C) 2005-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/>.  */
> >>> +
> >>> +/* Ho hum, since fxstatat == fxstatat64 we must get rid of the
> >>> +   prototype or gcc will complain since they don't strictly match.
> >>> +*/
> >>> +
> >>> +#include <kernel-features.h>
> >>> +#include <sys/syscall.h>
> >>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
> >>> +<errno.h> #include <fcntl.h> #include <stddef.h> #include <stdio.h>
> >>> +#include <string.h> #include <sys/stat.h>
> >>> +
> >>> +#include <sysdep.h>
> >>> +#include <kernel_stat.h>
> >>> +#include <statx_cp.h>
> >>> +
> >>> +
> >>> +/* Get information about the file NAME relative to FD in ST.  */
> >>> +int __fstatat (int fd, const char *file, struct stat *st, int flag)
> >>> +{
> >>> +  struct statx xbuf;
> >>> +  int r = INLINE_SYSCALL (statx, 5, fd, file,
> flag&AT_SYMLINK_NOFOLLOW,
> >>> +	      STATX_BASIC_STATS, &xbuf);
> >>> +  if (r == 0)
> >>> +    __cp_stat64_statx((struct stat64 *)st, &xbuf);
> >>> +  return r;
> >>> +}
> >>> +
> >>> +weak_alias (__fstatat, fstatat)
> >>> +
> >>> +#else /* __ASSUME_STATX && __NR_statx */ #include
> >>> +<sysdeps/unix/sysv/linux/fstatat.c>
> >>> +#endif
> >>
> >> I see no point in such optimization, which adds another mips specific file.
> >> If glibc is still alive near 2106 most likely we would had increases
> >> the minimum kernel version to include __NR_statx...
> >>
> >
> > linux/fstatat.c has no statx call. So, should we do the similar like fstatat64?
> 
> Even though it is not the default, non LFS interface are legacy ones.
> y2038 support, for instance, is only supported with LFS interfaces.
> 
> So it is up to you if you want to fix on fstatat.c, it should also fix the s390 issue
> with missing nanosecond support.
> 

fstatat is not recommend used by any new write code?
All new write code should use fstatat64?

> >
> >>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
> >>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
> >>> new file mode 100644
> >>> index 0000000000..acd929dfaa
> >>> --- /dev/null
> >>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
> >>> @@ -0,0 +1,51 @@
> >>> +/* fxstat using old-style Unix stat system call.
> >>> +   Copyright (C) 1991-2021 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 <kernel-features.h>
> >>> +#include <sys/syscall.h>
> >>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
> >>> +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
> >>> +<sysdep.h> #include <statx_cp.h>
> >>> +
> >>> +/* Get information about the file NAME in BUF.  */ int __fxstat
> >>> +(int vers, int fd, struct stat *buf) {
> >>> +  switch (vers)
> >>> +    {
> >>> +    case _STAT_VER_KERNEL:
> >>> +      return INLINE_SYSCALL_CALL (fstat, fd, buf);
> >>> +
> >>> +    default:
> >>> +      {
> >>> +	struct statx xbuf;
> >>> +	int r = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH,
> >>> +		      STATX_BASIC_STATS, &xbuf);
> >>> +	if (r == 0)
> >>> +	  __cp_stat64_statx((struct stat64 *)buf, &xbuf);
> >>> +	return r;
> >>> +      }
> >>> +    }
> >>> +}
> >>> +
> >>> +#else /* __ASSUME_STATX && __NR_statx */ #include
> >>> +<sysdeps/unix/sysv/linux/mips/fxstat.c>
> >>> +#endif
> >>
> >> As for the mips specific implementation, the __fxstat are
> >> compatibilty symbols and I don't want us to change their semantic.
> >> If user really care about
> >> y2106 they should use the newer stat symbols.
> >>
> >
> > While the pre-exists binaries do use __fxstat.
> > With this patch, I think that we can make them work correctly with just libc
> upgrade.
> >
> > With the previous binaries, even they use `stat' in source code, the result
> binaries do use __xstat.
> >
> > And the problem of Y2106 is not only about Y2106, and it also has problem
> for Y1969.
> > It may make some trouble, if we set the timestamp before 1970.
> 
> But is this really an issue for MIPS in a sense legacy programs will be affected
> in the referred timeframe? If we limit the fix for newly built binaries it
> simplifies a lot the code base.
> 
> My xstat refactor work was really to avoid the nasty profileration of
> arch-specific implementations and I think we are getting a step back by
> adding back this specific fix.
> 
> If you really want to fix on legacy compat implementation, I think it would be
> better to make in arch neutral way: 1. make xstat, lxstat, fxstat call fxstatat, 2.
> add statx on fxstatat/fxstatat64, and 3.
> convert back the struct to the _STAT_VER.
> 

I will split this patch, then.

> >
> >>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
> >>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
> >>> new file mode 100644
> >>> index 0000000000..a8da108347
> >>> --- /dev/null
> >>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
> >>> @@ -0,0 +1,43 @@
> >>> +/* fxstat64 using 64-bit MIPS fstat system call.
> >>> +   Copyright (C) 1997-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 <kernel-features.h>
> >>> +#include <sys/syscall.h>
> >>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
> >>> +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
> >>> +<sysdep.h> #include <statx_cp.h>
> >>> +
> >>> +/* Get information about the file FD in BUF.  */
> >>> +
> >>> +int
> >>> +__fxstat64 (int vers, int fd, struct stat64 *buf) {
> >>> +  struct statx xbuf;
> >>> +  int r = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH,
> >>> +	      STATX_BASIC_STATS, &xbuf);
> >>> +  if (r == 0)
> >>> +    __cp_stat64_statx(buf, &xbuf);
> >>> +  return r;
> >>> +}
> >>> +
> >>> +#else /* __ASSUME_STATX && __NR_statx */ #include
> >>> +<sysdeps/unix/sysv/linux/mips/mips64/fxstat64.c>
> >>> +#endif
> >>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
> >>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
> >>> new file mode 100644
> >>> index 0000000000..935888efe6
> >>> --- /dev/null
> >>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
> >>> @@ -0,0 +1,63 @@
> >>> +/* Copyright (C) 2005-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/>.  */
> >>> +
> >>> +/* Ho hum, since fxstatat == fxstatat64 we must get rid of the
> >>> +   prototype or gcc will complain since they don't strictly match.
> >>> +*/
> >>> +
> >>> +#include <kernel-features.h>
> >>> +#include <sys/syscall.h>
> >>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
> >>> +<errno.h> #include <fcntl.h> #include <stddef.h> #include <stdio.h>
> >>> +#include <string.h> #include <sys/stat.h>
> >>> +
> >>> +#include <sysdep.h>
> >>> +#include <kernel_stat.h>
> >>> +#include <statx_cp.h>
> >>> +
> >>> +
> >>> +/* Get information about the file NAME relative to FD in ST.  */
> >>> +int __fxstatat (int vers, int fd, const char *file, struct stat
> >>> +*st, int
> >>> +flag) {
> >>> +  switch (vers)
> >>> +    {
> >>> +    case _STAT_VER_KERNEL:
> >>> +	return INLINE_SYSCALL (newfstatat, 4, fd, file, st, flag);
> >>> +
> >>> +    case _STAT_VER_LINUX:
> >>> +      {
> >>> +	struct statx xbuf;
> >>> +	int r = INLINE_SYSCALL (statx, 5, fd, file,
> flag&AT_SYMLINK_NOFOLLOW,
> >>> +		      STATX_BASIC_STATS, &xbuf);
> >>> +	if (r == 0)
> >>> +	  __cp_stat64_statx((struct stat64 *)st, &xbuf);
> >>> +	return r;
> >>> +      }
> >>> +
> >>> +    default:
> >>> +      __set_errno (EINVAL);
> >>> +      return -1;
> >>> +    }
> >>> +}
> >>> +
> >>> +#else /* __ASSUME_STATX && __NR_statx */ #include
> >>> +<sysdeps/unix/sysv/linux/mips/mips64/fxstatat.c>
> >>> +#endif
> >>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
> >>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
> >>> new file mode 100644
> >>> index 0000000000..80bd0f1d09
> >>> --- /dev/null
> >>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
> >>> @@ -0,0 +1,53 @@
> >>> +/* Copyright (C) 2005-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 <kernel-features.h>
> >>> +#include <sys/syscall.h>
> >>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
> >>> +<errno.h> #include <fcntl.h> #include <stddef.h> #include <stdio.h>
> >>> +#include <string.h> #include <sys/stat.h> #include <kernel_stat.h>
> >>> +
> >>> +#include <sysdep.h>
> >>> +#include <statx_cp.h>
> >>> +
> >>> +/* Get information about the file NAME in BUF.  */
> >>> +
> >>> +int
> >>> +__fxstatat64 (int vers, int fd, const char *file, struct stat64
> >>> +*st, int flag) {
> >>> +  if (__builtin_expect (vers != _STAT_VER_LINUX, 0))
> >>> +    {
> >>> +      __set_errno (EINVAL);
> >>> +      return -1;
> >>> +    }
> >>> +
> >>> +  struct statx xbuf;
> >>> +  int r = INLINE_SYSCALL (statx, 5, fd, file,
> flag&AT_SYMLINK_NOFOLLOW,
> >>> +	      STATX_BASIC_STATS, &xbuf);
> >>> +  if (r == 0)
> >>> +    __cp_stat64_statx(st, &xbuf);
> >>> +  return r;
> >>> +}
> >>> +
> >>> +#else /* __ASSUME_STATX && __NR_statx */ #include
> >>> +<sysdeps/unix/sysv/linux/mips/mips64/fxstatat64.c>
> >>> +#endif
> >>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
> >>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
> >>> new file mode 100644
> >>> index 0000000000..f9c28b753b
> >>> --- /dev/null
> >>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
> >>> @@ -0,0 +1,51 @@
> >>> +/* lxstat using old-style Unix stat system call.
> >>> +   Copyright (C) 1991-2021 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 <kernel-features.h>
> >>> +#include <sys/syscall.h>
> >>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
> >>> +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
> >>> +<sysdep.h> #include <statx_cp.h>
> >>> +
> >>> +/* Get information about the file NAME in BUF.  */ int __lxstat
> >>> +(int vers, const char *name, struct stat *buf) {
> >>> +  switch (vers)
> >>> +    {
> >>> +    case _STAT_VER_KERNEL:
> >>> +      return INLINE_SYSCALL_CALL (lstat, name, buf);
> >>> +
> >>> +    default:
> >>> +      {
> >>> +	struct statx xbuf;
> >>> +	int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name,
> >> AT_SYMLINK_NOFOLLOW,
> >>> +			STATX_BASIC_STATS, &xbuf);
> >>> +	if (r == 0)
> >>> +	  __cp_stat64_statx((struct stat64 *)buf, &xbuf);
> >>> +	return r;
> >>> +      }
> >>> +    }
> >>> +}
> >>> +
> >>> +#else /* __ASSUME_STATX && __NR_statx */ #include
> >>> +<sysdeps/unix/sysv/linux/mips/lxstat.c>
> >>> +#endif
> >>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
> >>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
> >>> new file mode 100644
> >>> index 0000000000..927c542ca7
> >>> --- /dev/null
> >>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
> >>> @@ -0,0 +1,43 @@
> >>> +/* lxstat64 using 64-bit MIPS lstat system call.
> >>> +   Copyright (C) 1997-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 <kernel-features.h>
> >>> +#include <sys/syscall.h>
> >>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
> >>> +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
> >>> +<sysdep.h> #include <statx_cp.h>
> >>> +
> >>> +/* Get information about the file NAME in BUF.  */ int
> >>> +__lxstat64 (int vers, const char *name, struct stat64 *buf) {
> >>> +  struct statx xbuf;
> >>> +  int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name,
> >> AT_SYMLINK_NOFOLLOW,
> >>> +		STATX_BASIC_STATS, &xbuf);
> >>> +  // cast to struct stat from struct stat64 is OK for N64.
> >>> +  if (r == 0)
> >>> +    __cp_stat64_statx(buf, &xbuf);
> >>> +  return r;
> >>> +}
> >>> +
> >>> +#else /* __ASSUME_STATX && __NR_statx */ #include
> >>> +<sysdeps/unix/sysv/linux/mips/mips64/lxstat64.c>
> >>> +#endif
> >>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
> >>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
> >>> new file mode 100644
> >>> index 0000000000..6c735e5365
> >>> --- /dev/null
> >>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
> >>> @@ -0,0 +1,51 @@
> >>> +/* xstat using old-style Unix stat system call.
> >>> +   Copyright (C) 1991-2021 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 <kernel-features.h>
> >>> +#include <sys/syscall.h>
> >>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
> >>> +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
> >>> +<sysdep.h> #include <statx_cp.h>
> >>> +
> >>> +/* Get information about the file NAME in BUF.  */ int __xstat (int
> >>> +vers, const char *name, struct stat *buf) {
> >>> +  switch (vers)
> >>> +    {
> >>> +    case _STAT_VER_KERNEL:
> >>> +      return INLINE_SYSCALL_CALL (stat, name, buf);
> >>> +
> >>> +    default:
> >>> +      {
> >>> +	struct statx xbuf;
> >>> +	int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, 0,
> >>> +			STATX_BASIC_STATS, &xbuf);
> >>> +	if (r == 0)
> >>> +	  __cp_stat64_statx((struct stat64 *)buf, &xbuf);
> >>> +	return r;
> >>> +      }
> >>> +    }
> >>> +}
> >>> +
> >>> +#else /* __ASSUME_STATX && __NR_statx */ #include
> >>> +<sysdeps/unix/sysv/linux/mips/xstat.c>
> >>> +#endif
> >>> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
> >>> b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
> >>> new file mode 100644
> >>> index 0000000000..84db1b7a85
> >>> --- /dev/null
> >>> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
> >>> @@ -0,0 +1,43 @@
> >>> +/* xstat64 using 64-bit MIPS stat system call.
> >>> +   Copyright (C) 1991-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 <kernel-features.h>
> >>> +#include <sys/syscall.h>
> >>> +#if defined(__ASSUME_STATX) && defined(__NR_statx) #include
> >>> +<sys/stat.h> #include <fcntl.h> #include <kernel_stat.h> #include
> >>> +<sysdep.h> #include <statx_cp.h>
> >>> +
> >>> +/* Get information about the file NAME in BUF.  */
> >>> +
> >>> +int
> >>> +__xstat64 (int vers, const char *name, struct stat64 *buf) {
> >>> +  struct statx xbuf;
> >>> +  int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, 0,
> >>> +		STATX_BASIC_STATS, &xbuf);
> >>> +  if (r == 0)
> >>> +    __cp_stat64_statx(buf, &xbuf);
> >>> +  return r;
> >>> +}
> >>> +
> >>> +#else /* __ASSUME_STATX && __NR_statx */ #include
> >>> +<sysdeps/unix/sysv/linux/mips/mips64/xstat64.c>
> >>> +#endif
> >>>
> >
Adhemerval Zanella March 18, 2021, 12:17 p.m. UTC | #6
On 18/03/2021 03:05, yunqiang.su@cipunited.com wrote:
> 
> 
>> -----邮件原件-----
>> 发件人: Adhemerval Zanella <adhemerval.zanella@linaro.org>
>> 发送时间: 2021年3月17日 19:27
>> 收件人: yunqiang.su@cipunited.com; libc-alpha@sourceware.org
>> 抄送: aurelien@aurel32.net; jiaxun.yang@flygoat.com; macro@orcam.me.uk
>> 主题: Re: 回复: [PATCH] MIPS: fix y2106 problem on N64 with statx
>>
>> Even though it is not the default, non LFS interface are legacy ones.
>> y2038 support, for instance, is only supported with LFS interfaces.
>>
>> So it is up to you if you want to fix on fstatat.c, it should also fix the s390 issue
>> with missing nanosecond support.
>>
> 
> fstatat is not recommend used by any new write code?
> All new write code should use fstatat64?

It is an implementation detail in fact, glibc fstatat64 is the
interface with LFS support.  On ABIs with default LFS support it does
matter whether you use fstatat or fstatat64 (fstatat is fact an alias
to fstatat64).

On ABIs with LFS support (most of legacy 32-bits and some of 64-bit)
fstatat is used as default and fstatat64 is used as an asm alias if
_FILE_OFFSET_BITS=64 is defined or provided in the namespace if
_LARGEFILE64_SOURCE is defined.

I think we should now make LFS as default [1], at least for legacy
32-bit ABIs even though they are still namespace issues [2] [3].

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=13047
[2] https://sourceware.org/bugzilla/show_bug.cgi?id=14106
[3] https://sourceware.org/bugzilla/show_bug.cgi?id=15766
YunQiang Su March 19, 2021, 1 a.m. UTC | #7
> >>
> >> Even though it is not the default, non LFS interface are legacy ones.
> >> y2038 support, for instance, is only supported with LFS interfaces.
> >>
> >> So it is up to you if you want to fix on fstatat.c, it should also
> >> fix the s390 issue with missing nanosecond support.
> >>
> >
> > fstatat is not recommend used by any new write code?
> > All new write code should use fstatat64?
> 
> It is an implementation detail in fact, glibc fstatat64 is the interface with LFS
> support.  On ABIs with default LFS support it does matter whether you use
> fstatat or fstatat64 (fstatat is fact an alias to fstatat64).
> 
> On ABIs with LFS support (most of legacy 32-bits and some of 64-bit) fstatat is
> used as default and fstatat64 is used as an asm alias if
> _FILE_OFFSET_BITS=64 is defined or provided in the namespace if
> _LARGEFILE64_SOURCE is defined.

Here, what I care about it only MIPS N64 (aka pure 64).
The bad news is that neither _FILE_OFFSET_BITS=64 nor _LARGEFILE64_SOURCE is defined by default.
So, I guess that we have to fix fstatat at the same time, in fact it is quite simple: just call __fstatat64 is OK.

> 
> I think we should now make LFS as default [1], at least for legacy 32-bit ABIs
> even though they are still namespace issues [2] [3].

Another bad news for s390-32, its statx has no nanosecond value neither.

> 
> [1] https://sourceware.org/bugzilla/show_bug.cgi?id=13047
> [2] https://sourceware.org/bugzilla/show_bug.cgi?id=14106
> [3] https://sourceware.org/bugzilla/show_bug.cgi?id=15766
diff mbox series

Patch

diff --git a/io/tst-fstatat.c b/io/tst-fstatat.c
index 4766bb2e71..8297b14479 100644
--- a/io/tst-fstatat.c
+++ b/io/tst-fstatat.c
@@ -5,7 +5,7 @@ 
 #include <string.h>
 #include <unistd.h>
 #include <sys/stat.h>
-
+#include <kernel-features.h>
 
 static void prepare (void);
 #define PREPARE(argc, argv) prepare ()
@@ -134,6 +134,30 @@  do_test (void)
       puts ("stat results do not match");
       return 1;
     }
+#if defined(__mips64) &&  (_MIPS_SIM == _ABI64) && defined(__ASSUME_STATX)
+  /* fstatat syscall has y2106 problem on MIPS N64
+     Now we use statx to implement *stat* functions
+     So the problem should have gone */
+  struct timespec tm_1[2] = {{-1, 0}, {-1, 0}};
+  if (utimensat(dir_fd, "some-file", tm_1, 0) != 0)
+    {
+      puts ("utimensat fail");
+      return 1;
+    }
+
+  if (fstatat64 (dir_fd, "some-file", &st2, 0) != 0)
+    {
+      puts ("fstatat64 failed");
+      return 1;
+    }
+
+  if (st2.st_mtim.tv_sec != -1
+      || st2.st_atim.tv_sec != -1)
+    {
+      puts ("fstatat64 has y2106 problem?");
+      return 1;
+    }
+#endif
 
   if (unlinkat (dir_fd, "some-file", 0) != 0)
     {
diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
index 490226a8ec..220321be9c 100644
--- a/sysdeps/unix/sysv/linux/fstatat64.c
+++ b/sysdeps/unix/sysv/linux/fstatat64.c
@@ -47,15 +47,21 @@  __fstatat64_time64 (int fd, const char *file, struct __stat64_t64 *buf,
   int r;
 
 #if (__WORDSIZE == 32 \
-     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
+     && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
+    || defined(__mips64)
   /* 32-bit kABI with default 64-bit time_t, e.g. arc, riscv32.   Also
      64-bit time_t support is done through statx syscall.  */
+  /* Also use statx syscall for MIPS N64, since newfstatat has y2106 problem */
   struct statx tmp;
   r = INTERNAL_SYSCALL_CALL (statx, fd, file, AT_NO_AUTOMOUNT | flag,
 			     STATX_BASIC_STATS, &tmp);
   if (r == 0)
     {
+#if defined(__mips64) && (_MIPS_SIM == _ABI64)
+      __cp_stat64_statx (buf, &tmp);
+#else
       __cp_stat64_t64_statx (buf, &tmp);
+#endif
       return 0;
     }
   if (-r != ENOSYS)
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
new file mode 100644
index 0000000000..5000cd0715
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fstatat.c
@@ -0,0 +1,52 @@ 
+/* Copyright (C) 2005-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/>.  */
+
+/* Ho hum, since fxstatat == fxstatat64 we must get rid of the
+   prototype or gcc will complain since they don't strictly match.  */
+
+#include <kernel-features.h>
+#include <sys/syscall.h>
+#if defined(__ASSUME_STATX) && defined(__NR_statx)
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <sysdep.h>
+#include <kernel_stat.h>
+#include <statx_cp.h>
+
+
+/* Get information about the file NAME relative to FD in ST.  */
+int
+__fstatat (int fd, const char *file, struct stat *st, int flag)
+{
+  struct statx xbuf;
+  int r = INLINE_SYSCALL (statx, 5, fd, file, flag&AT_SYMLINK_NOFOLLOW,
+	      STATX_BASIC_STATS, &xbuf);
+  if (r == 0)
+    __cp_stat64_statx((struct stat64 *)st, &xbuf);
+  return r;
+}
+
+weak_alias (__fstatat, fstatat)
+
+#else /* __ASSUME_STATX && __NR_statx */
+#include <sysdeps/unix/sysv/linux/fstatat.c>
+#endif
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
new file mode 100644
index 0000000000..acd929dfaa
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat.c
@@ -0,0 +1,51 @@ 
+/* fxstat using old-style Unix stat system call.
+   Copyright (C) 1991-2021 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 <kernel-features.h>
+#include <sys/syscall.h>
+#if defined(__ASSUME_STATX) && defined(__NR_statx)
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <kernel_stat.h>
+#include <sysdep.h>
+#include <statx_cp.h>
+
+/* Get information about the file NAME in BUF.  */
+int
+__fxstat (int vers, int fd, struct stat *buf)
+{
+  switch (vers)
+    {
+    case _STAT_VER_KERNEL:
+      return INLINE_SYSCALL_CALL (fstat, fd, buf);
+
+    default:
+      {
+	struct statx xbuf;
+	int r = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH,
+		      STATX_BASIC_STATS, &xbuf);
+	if (r == 0)
+	  __cp_stat64_statx((struct stat64 *)buf, &xbuf);
+	return r;
+      }
+    }
+}
+
+#else /* __ASSUME_STATX && __NR_statx */
+#include <sysdeps/unix/sysv/linux/mips/fxstat.c>
+#endif
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
new file mode 100644
index 0000000000..a8da108347
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstat64.c
@@ -0,0 +1,43 @@ 
+/* fxstat64 using 64-bit MIPS fstat system call.
+   Copyright (C) 1997-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 <kernel-features.h>
+#include <sys/syscall.h>
+#if defined(__ASSUME_STATX) && defined(__NR_statx)
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <kernel_stat.h>
+#include <sysdep.h>
+#include <statx_cp.h>
+
+/* Get information about the file FD in BUF.  */
+
+int
+__fxstat64 (int vers, int fd, struct stat64 *buf)
+{
+  struct statx xbuf;
+  int r = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH,
+	      STATX_BASIC_STATS, &xbuf);
+  if (r == 0)
+    __cp_stat64_statx(buf, &xbuf);
+  return r;
+}
+
+#else /* __ASSUME_STATX && __NR_statx */
+#include <sysdeps/unix/sysv/linux/mips/mips64/fxstat64.c>
+#endif
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
new file mode 100644
index 0000000000..935888efe6
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat.c
@@ -0,0 +1,63 @@ 
+/* Copyright (C) 2005-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/>.  */
+
+/* Ho hum, since fxstatat == fxstatat64 we must get rid of the
+   prototype or gcc will complain since they don't strictly match.  */
+
+#include <kernel-features.h>
+#include <sys/syscall.h>
+#if defined(__ASSUME_STATX) && defined(__NR_statx)
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <sysdep.h>
+#include <kernel_stat.h>
+#include <statx_cp.h>
+
+
+/* Get information about the file NAME relative to FD in ST.  */
+int
+__fxstatat (int vers, int fd, const char *file, struct stat *st, int flag)
+{
+  switch (vers)
+    {
+    case _STAT_VER_KERNEL:
+	return INLINE_SYSCALL (newfstatat, 4, fd, file, st, flag);
+
+    case _STAT_VER_LINUX:
+      {
+	struct statx xbuf;
+	int r = INLINE_SYSCALL (statx, 5, fd, file, flag&AT_SYMLINK_NOFOLLOW,
+		      STATX_BASIC_STATS, &xbuf);
+	if (r == 0)
+	  __cp_stat64_statx((struct stat64 *)st, &xbuf);
+	return r;
+      }
+
+    default:
+      __set_errno (EINVAL);
+      return -1;
+    }
+}
+
+#else /* __ASSUME_STATX && __NR_statx */
+#include <sysdeps/unix/sysv/linux/mips/mips64/fxstatat.c>
+#endif
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
new file mode 100644
index 0000000000..80bd0f1d09
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/fxstatat64.c
@@ -0,0 +1,53 @@ 
+/* Copyright (C) 2005-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 <kernel-features.h>
+#include <sys/syscall.h>
+#if defined(__ASSUME_STATX) && defined(__NR_statx)
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <kernel_stat.h>
+
+#include <sysdep.h>
+#include <statx_cp.h>
+
+/* Get information about the file NAME in BUF.  */
+
+int
+__fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag)
+{
+  if (__builtin_expect (vers != _STAT_VER_LINUX, 0))
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  struct statx xbuf;
+  int r = INLINE_SYSCALL (statx, 5, fd, file, flag&AT_SYMLINK_NOFOLLOW,
+	      STATX_BASIC_STATS, &xbuf);
+  if (r == 0)
+    __cp_stat64_statx(st, &xbuf);
+  return r;
+}
+
+#else /* __ASSUME_STATX && __NR_statx */
+#include <sysdeps/unix/sysv/linux/mips/mips64/fxstatat64.c>
+#endif
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
new file mode 100644
index 0000000000..f9c28b753b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat.c
@@ -0,0 +1,51 @@ 
+/* lxstat using old-style Unix stat system call.
+   Copyright (C) 1991-2021 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 <kernel-features.h>
+#include <sys/syscall.h>
+#if defined(__ASSUME_STATX) && defined(__NR_statx)
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <kernel_stat.h>
+#include <sysdep.h>
+#include <statx_cp.h>
+
+/* Get information about the file NAME in BUF.  */
+int
+__lxstat (int vers, const char *name, struct stat *buf)
+{
+  switch (vers)
+    {
+    case _STAT_VER_KERNEL:
+      return INLINE_SYSCALL_CALL (lstat, name, buf);
+
+    default:
+      {
+	struct statx xbuf;
+	int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, AT_SYMLINK_NOFOLLOW,
+			STATX_BASIC_STATS, &xbuf);
+	if (r == 0)
+	  __cp_stat64_statx((struct stat64 *)buf, &xbuf);
+	return r;
+      }
+    }
+}
+
+#else /* __ASSUME_STATX && __NR_statx */
+#include <sysdeps/unix/sysv/linux/mips/lxstat.c>
+#endif
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
new file mode 100644
index 0000000000..927c542ca7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/lxstat64.c
@@ -0,0 +1,43 @@ 
+/* lxstat64 using 64-bit MIPS lstat system call.
+   Copyright (C) 1997-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 <kernel-features.h>
+#include <sys/syscall.h>
+#if defined(__ASSUME_STATX) && defined(__NR_statx)
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <kernel_stat.h>
+#include <sysdep.h>
+#include <statx_cp.h>
+
+/* Get information about the file NAME in BUF.  */
+int
+__lxstat64 (int vers, const char *name, struct stat64 *buf)
+{
+  struct statx xbuf;
+  int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, AT_SYMLINK_NOFOLLOW,
+		STATX_BASIC_STATS, &xbuf);
+  // cast to struct stat from struct stat64 is OK for N64.
+  if (r == 0)
+    __cp_stat64_statx(buf, &xbuf);
+  return r;
+}
+
+#else /* __ASSUME_STATX && __NR_statx */
+#include <sysdeps/unix/sysv/linux/mips/mips64/lxstat64.c>
+#endif
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
new file mode 100644
index 0000000000..6c735e5365
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat.c
@@ -0,0 +1,51 @@ 
+/* xstat using old-style Unix stat system call.
+   Copyright (C) 1991-2021 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 <kernel-features.h>
+#include <sys/syscall.h>
+#if defined(__ASSUME_STATX) && defined(__NR_statx)
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <kernel_stat.h>
+#include <sysdep.h>
+#include <statx_cp.h>
+
+/* Get information about the file NAME in BUF.  */
+int
+__xstat (int vers, const char *name, struct stat *buf)
+{
+  switch (vers)
+    {
+    case _STAT_VER_KERNEL:
+      return INLINE_SYSCALL_CALL (stat, name, buf);
+
+    default:
+      {
+	struct statx xbuf;
+	int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, 0,
+			STATX_BASIC_STATS, &xbuf);
+	if (r == 0)
+	  __cp_stat64_statx((struct stat64 *)buf, &xbuf);
+	return r;
+      }
+    }
+}
+
+#else /* __ASSUME_STATX && __NR_statx */
+#include <sysdeps/unix/sysv/linux/mips/xstat.c>
+#endif
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
new file mode 100644
index 0000000000..84db1b7a85
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/xstat64.c
@@ -0,0 +1,43 @@ 
+/* xstat64 using 64-bit MIPS stat system call.
+   Copyright (C) 1991-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 <kernel-features.h>
+#include <sys/syscall.h>
+#if defined(__ASSUME_STATX) && defined(__NR_statx)
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <kernel_stat.h>
+#include <sysdep.h>
+#include <statx_cp.h>
+
+/* Get information about the file NAME in BUF.  */
+
+int
+__xstat64 (int vers, const char *name, struct stat64 *buf)
+{
+  struct statx xbuf;
+  int r = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, 0,
+		STATX_BASIC_STATS, &xbuf);
+  if (r == 0)
+    __cp_stat64_statx(buf, &xbuf);
+  return r;
+}
+
+#else /* __ASSUME_STATX && __NR_statx */
+#include <sysdeps/unix/sysv/linux/mips/mips64/xstat64.c>
+#endif