[PATCH] LoongArch: Add fstat64 and fstatat64.

Xi Ruoyao xry111@xry111.site
Wed Sep 11 11:00:06 GMT 2024


On Wed, 2024-09-11 at 17:40 +0800, caiyinyu wrote:

/* snip */

> diff --git a/sysdeps/unix/sysv/linux/loongarch/arch-syscall.h b/sysdeps/unix/sysv/linux/loongarch/arch-syscall.h
> index 8bb82448a7..7e732256fd 100644
> --- a/sysdeps/unix/sysv/linux/loongarch/arch-syscall.h
> +++ b/sysdeps/unix/sysv/linux/loongarch/arch-syscall.h

No, we are not allowed to edit this file manually.  We must wait for the
global maintainer to regenerate this file (and all arch-syscall.h files)
after Linux 6.11 release.

And we should avoid the runtime probe if --enable-kernel-6.10.6 or
later.

And we shouldn't use fstat64 or fstatat64 on LA32 (because they'll
suffer y2038 issue on 32-bit architecture).  IMO it's better to add the
check now so we don't need to remember to change this again when we add
LA32 support.

(See below for my suggestion to handle --enable-kernel and 32-bit but
there may be better ways.)

/* snip */


> diff --git a/sysdeps/unix/sysv/linux/loongarch/fstat64.c b/sysdeps/unix/sysv/linux/loongarch/fstat64.c
> new file mode 100644
> index 0000000000..b1a9e9c6a4
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/loongarch/fstat64.c
> @@ -0,0 +1,64 @@
> +/* Get file status.  LoongArch version.

/* snip */

> +   <https://www.gnu.org/licenses/>.  */
> +

Here add

#if __LINUX_KERNEL_VERSION >= 0x060a06 || !defined(__loongarch_lp64)
#include "../fstat64.c"
#else

and add #endif at the end of the file.  This should be enough to avoid
the runtime probe of --enable-kernel=6.10.6 or later, and avoid using
fstat64/fstatat64 for 32-bit.

> +#define __fstat __redirect___fstat
> +#define fstat   __redirect_fstat
> +#include <sys/stat.h>
> +#undef __fstat
> +#undef fstat
> +
> +#include "fstatat64_time64_statx.h"
> +
> +int __fstat_syscall_supported attribute_hidden = 1;

static int __fstat_syscall_supported = 1;

because it's only used in this translation unit.  Or you may want to
remove __newfstatat_syscall_supported and reuse this in fstatat64.c.

> +int
> +__fstat64 (int fd, struct __stat64_t64 *buf)
> +{
> +  int r;
> +  extern int __fstat_syscall_supported attribute_hidden;

Remove this.  The definition is in the same TU, so no need of this.

> +  int supported = atomic_load_relaxed (&__fstat_syscall_supported);
> +  if (__glibc_likely (supported))

I'd remove __glibc_likely here.  We don't have a priori knowledge of
what kernel version we are running on (unless --enable-kernel=6.10.6 or
later but then we should be just using ../fstat64.c).

> +  {
> +    r = INTERNAL_SYSCALL_CALL (fstat, fd, buf);
> +    if (r == 0)
> +      return r;
> +    else if (r != -ENOSYS)
> +      return INLINE_SYSCALL_ERROR_RETURN_VALUE (-r);
> +
> +    atomic_store_relaxed (&__fstat_syscall_supported, 0);
> +  }
> +
> +  if (fd < 0)
> +  {
> +    __set_errno (EBADF);
> +    return -1;
> +  }
> +
> +  r = fstatat64_time64_statx (fd, "", buf, AT_EMPTY_PATH);
> +  return INTERNAL_SYSCALL_ERROR_P (r)
> +    ? INLINE_SYSCALL_ERROR_RETURN_VALUE (-r)
> +    : 0;
> +}
> +
> +hidden_def (__fstat64)
> +weak_alias (__fstat64, fstat64)
> +
> +#if XSTAT_IS_XSTAT64

On LoongArch XSTAT_IS_XSTAT64 is always 1, so we can remove this #if.

> +strong_alias (__fstat64, __fstat)
> +weak_alias (__fstat64, fstat)
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/loongarch/fstatat64.c b/sysdeps/unix/sysv/linux/loongarch/fstatat64.c
> new file mode 100644
> index 0000000000..64f5b3b8f6
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/loongarch/fstatat64.c
> @@ -0,0 +1,59 @@
> +/* Get file status.  LoongArch version.

/* snip */

> +   <https://www.gnu.org/licenses/>.  */

Likewise, add

#if __LINUX_KERNEL_VERSION >= 0x060a06 || !defined(__loongarch_lp64)
#include "../fstatat64.c"
#else

here.

> +#define __fstatat __redirect___fstatat
> +#define fstatat   __redirect_fstatat
> +#include <sys/stat.h>
> +#undef __fstatat
> +#undef fstatat
> +
> +#include "fstatat64_time64_statx.h"
> +
> +int __newfstatat_syscall_supported attribute_hidden = 1;

Likewise, use static (or remove it if you want to reuse
__fstat_syscall_supported instead).

> +
> +int
> +__fstatat64 (int fd, const char *file, struct __stat64_t64 *buf,
> +		    int flag)
> +{
> +  int r;
> +  extern int __newfstatat_syscall_supported attribute_hidden;

Likewise, remove this.  Or change to __fstat_syscall_supported if you
want to reuse it.

/* snip */

> +#if XSTAT_IS_XSTAT64

Likewise, remove this #if.

> +strong_alias (__fstatat64, __fstatat)
> +weak_alias (__fstatat64, fstatat)
> +strong_alias (__fstatat64, __GI___fstatat);
> +#endif


> diff --git a/sysdeps/unix/sysv/linux/loongarch/fstatat64_time64_statx.h b/sysdeps/unix/sysv/linux/loongarch/fstatat64_time64_statx.h
> new file mode 100644
> index 0000000000..97920a820f
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/loongarch/fstatat64_time64_statx.h

Hmm this is duplicating a large hunk of code from
sysdeps/unix/sysv/linux/fstatat64.c.  Maybe rename to
sysdeps/unix/sysv/linux/fstatat64_time64_statx.h and include it in both
linux/fstatat64.c and linux/loongarch/fstatat64.c?

> @@ -0,0 +1,54 @@
> +/* Get file status.  LoongArch version.
> +   Copyright (C) 2024 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 <fcntl.h>
> +#include <sys/sysmacros.h>
> +#include <internal-stat.h>
> +
> +static inline int
> +fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
> +			int flag)
> +{
> +  struct statx tmp;
> +  int r = INTERNAL_SYSCALL_CALL (statx, fd, file, AT_NO_AUTOMOUNT | flag,
> +				 STATX_BASIC_STATS, &tmp);
> +  if (r != 0)
> +    return r;
> +
> +  *buf = (struct __stat64_t64)
> +  {
> +    .st_dev = __gnu_dev_makedev (tmp.stx_dev_major, tmp.stx_dev_minor),
> +    .st_rdev = __gnu_dev_makedev (tmp.stx_rdev_major, tmp.stx_rdev_minor),
> +    .st_ino = tmp.stx_ino,
> +    .st_mode = tmp.stx_mode,
> +    .st_nlink = tmp.stx_nlink,
> +    .st_uid = tmp.stx_uid,
> +    .st_gid = tmp.stx_gid,
> +    .st_atime = tmp.stx_atime.tv_sec,
> +    .st_atim.tv_nsec = tmp.stx_atime.tv_nsec,
> +    .st_mtime = tmp.stx_mtime.tv_sec,
> +    .st_mtim.tv_nsec = tmp.stx_mtime.tv_nsec,
> +    .st_ctime = tmp.stx_ctime.tv_sec,
> +    .st_ctim.tv_nsec = tmp.stx_ctime.tv_nsec,
> +    .st_size = tmp.stx_size,
> +    .st_blocks = tmp.stx_blocks,
> +    .st_blksize = tmp.stx_blksize,
> +  };
> +
> +  return r;
> +}

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University


More information about the Libc-alpha mailing list