Message ID | cover.1542591094.git.han_mao@c-sky.com |
---|---|
Headers | show |
Series | port C-SKY to glibc | expand |
On Mon, 19 Nov 2018, Mao Han wrote: > I've replace ctri.S crtn.S with init-array in this patch. > Thanks Palmer for giving some background information about this change. > But I still got some trouble with this. GCC seems can not detect whether > glibc use init-array or not, and default to not use init-array. > Option --enable-initfini-array is needed while configuring gcc, otherwise > some init function won't be called. The correct thing to do there is to fix the GCC configure test so you don't need --enable-initfini-array in build-many-glibcs.py. As far as I can tell, in the current version of the gcc_AC_INITFINI_ARRAY test, the only part that's an execution test is the ia64 case. That is, for every other target, the 'if test "x${build}" = "x${target}" && test "x${build}" = "x${host}"' condition is bogus as the rest of the tests would work just as well for cross compilation. (In the ia64 case, the fourth argument to AC_RUN_IFELSE - the action if cross compiling - is already there. So simply removing the requirement for build = host = target should allow things to work for cross compiling as well as for native except on ia64, and someone using ia64 could always fix that case later to have better cross compilation defaults based on the target OS.) > Another issue is Linux kernel have remove stat64 family from default > syscall set, and C-SKY dont' define __ARCH_WANT_STAT64. The generic > version seems can't work without stat64. So I added fxstat, fxstatat, > lxstat, xstat implemented with statx for C-SKY. I am supposing this is the preferred default for all future architectures added to the Linux kernel - they won't have the stat64 syscalls because the relevant functions are supposed to be implemented in userspace using statx instead. If so, the implementations in terms of statx do not belong in a csky sysdeps directory. Rather, all the sysdeps/unix/sysv/linux/generic/wordsize-32/ implementations should gain appropriate conditionals, so that if __NR_<whatever-old-syscall> is defined they follow the existing logic, and if it's not defined they follow the logic to use statx instead. (If we get new 64-bit architectures in the kernel and glibc in the future, further implementations in sysdeps/unix/sysv/linux/ and sysdeps/unix/sysv/linux/generic/ will also need such conditionals. However, it would be hard to test such changes at present, and I think the wordsize-32 files cover all that you need for this architecture.) Note that statx_cp.c would similarly be a generic file with an appropriate non-architecture-specific Makefile causing it to be built, and with its contents conditioned out in the case where the old syscalls exist. Note also that there should be a corresponding header - it's a bad idea to duplicate an extern declaration of __cp_stat_statx (which should be declared as hidden) in lots of separate .c files. > - remove support for big endian I'd expect an explicit error somewhere (either header #error of in the preconfigure script) for an attempt to build for big endian.
On Mon, Nov 19, 2018 at 04:45:09PM +0000, Joseph Myers wrote: > The correct thing to do there is to fix the GCC configure test so you > don't need --enable-initfini-array in build-many-glibcs.py. > > As far as I can tell, in the current version of the gcc_AC_INITFINI_ARRAY > test, the only part that's an execution test is the ia64 case. That is, > for every other target, the 'if test "x${build}" = "x${target}" && test > "x${build}" = "x${host}"' condition is bogus as the rest of the tests > would work just as well for cross compilation. (In the ia64 case, the > fourth argument to AC_RUN_IFELSE - the action if cross compiling - is > already there. So simply removing the requirement for build = host = > target should allow things to work for cross compiling as well as for > native except on ia64, and someone using ia64 could always fix that case > later to have better cross compilation defaults based on the target OS.) > Thanks for suggestion. We will try if it works for C-SKY cross compilation. > > Another issue is Linux kernel have remove stat64 family from default > > syscall set, and C-SKY dont' define __ARCH_WANT_STAT64. The generic > > version seems can't work without stat64. So I added fxstat, fxstatat, > > lxstat, xstat implemented with statx for C-SKY. > > I am supposing this is the preferred default for all future architectures > added to the Linux kernel - they won't have the stat64 syscalls because > the relevant functions are supposed to be implemented in userspace using > statx instead. > > If so, the implementations in terms of statx do not belong in a csky > sysdeps directory. Rather, all the > sysdeps/unix/sysv/linux/generic/wordsize-32/ implementations should gain > appropriate conditionals, so that if __NR_<whatever-old-syscall> is > defined they follow the existing logic, and if it's not defined they > follow the logic to use statx instead. > I'v modified patch 14/14 to a generic version with __NR3264_fstatat conditionals (in the attachment). It is tested in the same environment as patch V5 and got same result, but have't test fstat64 path yet. > > > - remove support for big endian > > I'd expect an explicit error somewhere (either header #error of in the > preconfigure script) for an attempt to build for big endian. > I forget to remove big endian part while making patch v5, there was a #error in bits/endian.h in patch v4. Thanks for reminding. From 67d158a0f631744ae99666ab1cd86d44457e59c1 Mon Sep 17 00:00:00 2001 Message-Id: <67d158a0f631744ae99666ab1cd86d44457e59c1.1542765182.git.han_mao@c-sky.com> From: Mao Han <han_mao@c-sky.com> Date: Wed, 21 Nov 2018 09:14:26 +0800 Subject: [PATCH 1/1] Add statx conditionals for wordsize-32 *xstat.c Linux kernel have remove stat64 family from default syscall set, new implementations with statx is needed when __ARCH_WANT_STAT64 is not define. This patch add conditionals for relevant functions, using statx system call to get information and then copy to the return buf, ref to include/linux/fs.h from linux kernel. * sysdeps/unix/sysv/linux/Makefile: Add for statx_cp.c. * sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat64.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat64.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c: Likewise. * sysdeps/unix/sysv/linux/statx_cp.c: New file. * sysdeps/unix/sysv/linux/statx_cp.h: Likewise. --- sysdeps/unix/sysv/linux/Makefile | 3 +- .../unix/sysv/linux/generic/wordsize-32/fxstat.c | 11 ++++ .../unix/sysv/linux/generic/wordsize-32/fxstat64.c | 47 ++++++++++++- .../unix/sysv/linux/generic/wordsize-32/fxstatat.c | 11 ++++ .../sysv/linux/generic/wordsize-32/fxstatat64.c | 42 +++++++++++- .../unix/sysv/linux/generic/wordsize-32/lxstat.c | 11 ++++ .../unix/sysv/linux/generic/wordsize-32/lxstat64.c | 19 +++++- .../unix/sysv/linux/generic/wordsize-32/xstat.c | 10 +++ .../unix/sysv/linux/generic/wordsize-32/xstat64.c | 14 +++- sysdeps/unix/sysv/linux/statx_cp.c | 77 ++++++++++++++++++++++ sysdeps/unix/sysv/linux/statx_cp.h | 23 +++++++ 11 files changed, 262 insertions(+), 6 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/statx_cp.c create mode 100644 sysdeps/unix/sysv/linux/statx_cp.h diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 72b6b64..7f817e0 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -177,7 +177,8 @@ sysdep_routines += xstatconv internal_statvfs internal_statvfs64 \ close_nocancel fcntl_nocancel nanosleep_nocancel \ open_nocancel open64_nocancel \ openat_nocancel openat64_nocancel \ - pause_nocancel read_nocancel waitpid_nocancel write_nocancel + pause_nocancel read_nocancel waitpid_nocancel \ + write_nocancel statx_cp sysdep_headers += bits/fcntl-linux.h diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c index b5c766d..bb3eec2 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c @@ -18,6 +18,7 @@ #include <errno.h> #include <stddef.h> +#include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <kernel_stat.h> @@ -27,6 +28,7 @@ #if !XSTAT_IS_XSTAT64 #include "overflow.h" +#include "statx_cp.h" /* Get information about the file FD in BUF. */ int @@ -34,8 +36,17 @@ __fxstat (int vers, int fd, struct stat *buf) { if (vers == _STAT_VER_KERNEL) { +# ifdef __NR3264_fstatat int rc = INLINE_SYSCALL (fstat64, 2, fd, buf); return rc ?: stat_overflow (buf); +# else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat_statx (buf, &tmp); + return rc; +# endif } errno = EINVAL; diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat64.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat64.c index c558388..e94e652 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat64.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat64.c @@ -25,7 +25,52 @@ #define __fxstat __fxstat_disable #define _fxstat _fxstat_disable -#include <sysdeps/unix/sysv/linux/fxstat64.c> +#include <errno.h> +#include <stddef.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <kernel_stat.h> + +#include <sysdep.h> +#include <sys/syscall.h> + +#include <kernel-features.h> + +#include "statx_cp.h" + +/* Get information about the file FD in BUF. */ + +int +___fxstat64 (int vers, int fd, struct stat64 *buf) +{ + int result; +#ifdef __NR3264_fstatat + result = INLINE_SYSCALL (fstat64, 2, fd, buf); +#else + struct statx tmp; + result = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH, STATX_BASIC_STATS, + &tmp); + if (result == 0) + __cp_stat64_statx (buf, &tmp); +#endif +#if defined _HAVE_STAT64___ST_INO && !__ASSUME_ST_INO_64_BIT + if (__builtin_expect (!result, 1) && buf->__st_ino != (__ino_t) buf->st_ino) + buf->st_ino = buf->__st_ino; +#endif + return result; +} + +#include <shlib-compat.h> + +#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) +versioned_symbol (libc, ___fxstat64, __fxstat64, GLIBC_2_2); +strong_alias (___fxstat64, __old__fxstat64) +compat_symbol (libc, __old__fxstat64, __fxstat64, GLIBC_2_1); +hidden_ver (___fxstat64, __fxstat64) +#else +strong_alias (___fxstat64, __fxstat64) +hidden_def (__fxstat64) +#endif #undef __fxstat #undef _fxstat diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c index 0bda8f7..3c031c5 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c @@ -28,6 +28,7 @@ #if !XSTAT_IS_XSTAT64 #include "overflow.h" +#include "statx_cp.h" /* Get information about the file NAME in BUF. */ int @@ -35,8 +36,18 @@ __fxstatat (int vers, int fd, const char *file, struct stat *buf, int flag) { if (vers == _STAT_VER_KERNEL) { +# ifdef __NR3264_fstatat int rc = INLINE_SYSCALL (fstatat64, 4, fd, file, buf, flag); return rc ?: stat_overflow (buf); +# else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, fd, file, + AT_NO_AUTOMOUNT | flag, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat_statx (buf, &tmp); + return rc; +# endif } errno = EINVAL; diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat64.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat64.c index 602bf4b..16ad3ad 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat64.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat64.c @@ -28,7 +28,47 @@ #undef _STAT_VER_LINUX #define _STAT_VER_LINUX _STAT_VER_KERNEL -#include <sysdeps/unix/sysv/linux/fxstatat64.c> +#include <errno.h> +#include <fcntl.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#include <kernel_stat.h> + +#include <sysdep.h> +#include <sys/syscall.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 (__glibc_unlikely (vers != _STAT_VER_LINUX)) + return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); + + int result; + INTERNAL_SYSCALL_DECL (err); + +#ifdef __NR3264_fstatat + result = INTERNAL_SYSCALL (fstatat64, err, 4, fd, file, st, flag); +#else + struct statx tmp; + + result = INTERNAL_SYSCALL (statx, err, 5, fd, file, + AT_NO_AUTOMOUNT | flag, + STATX_BASIC_STATS, &tmp); + if (result == 0) + __cp_stat64_statx (st, &tmp); +#endif + if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1)) + return 0; + else + return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (result, + err)); +} +libc_hidden_def (__fxstatat64) #undef __fxstatat #if XSTAT_IS_XSTAT64 diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c index c278a4d..f4eac25 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c @@ -27,6 +27,7 @@ #if !XSTAT_IS_XSTAT64 #include "overflow.h" +#include "statx_cp.h" /* Get information about the file NAME in BUF. */ int @@ -34,9 +35,19 @@ __lxstat (int vers, const char *name, struct stat *buf) { if (vers == _STAT_VER_KERNEL) { +#ifdef __NR3264_fstatat int rc = INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, AT_SYMLINK_NOFOLLOW); return rc ?: stat_overflow (buf); +#else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat_statx (buf, &tmp); + return rc; +#endif } errno = EINVAL; return -1; diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c index 761dd16..0d76d24 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c @@ -32,13 +32,28 @@ #include <sysdep.h> #include <sys/syscall.h> +#include "statx_cp.h" + /* Get information about the file NAME in BUF. */ int __lxstat64 (int vers, const char *name, struct stat64 *buf) { if (vers == _STAT_VER_KERNEL) - return INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, - AT_SYMLINK_NOFOLLOW); + { +#ifdef __NR3264_fstatat + return INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, + AT_SYMLINK_NOFOLLOW); +#else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat64_statx (buf, &tmp); + return rc; +#endif + } + errno = EINVAL; return -1; } diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c index 1fd57ff..292a292 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c @@ -27,6 +27,7 @@ #if !XSTAT_IS_XSTAT64 #include "overflow.h" +#include "statx_cp.h" /* Get information about the file NAME in BUF. */ int @@ -34,8 +35,17 @@ __xstat (int vers, const char *name, struct stat *buf) { if (vers == _STAT_VER_KERNEL) { +# ifdef __NR3264_fstatat int rc = INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, 0); return rc ?: stat_overflow (buf); +# else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, AT_NO_AUTOMOUNT, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat_statx (buf, &tmp); + return rc; +# endif } errno = EINVAL; diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c index ae70495..bd10402 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c @@ -32,13 +32,25 @@ #include <sysdep.h> #include <sys/syscall.h> +#include "statx_cp.h" + /* Get information about the file NAME in BUF. */ int __xstat64 (int vers, const char *name, struct stat64 *buf) { if (vers == _STAT_VER_KERNEL) + { +#ifdef __NR3264_fstatat return INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, 0); - +#else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, AT_NO_AUTOMOUNT, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat64_statx (buf, &tmp); + return rc; +#endif + } errno = EINVAL; return -1; } diff --git a/sysdeps/unix/sysv/linux/statx_cp.c b/sysdeps/unix/sysv/linux/statx_cp.c new file mode 100644 index 0000000..f10bd74 --- /dev/null +++ b/sysdeps/unix/sysv/linux/statx_cp.c @@ -0,0 +1,77 @@ +/* Struct statx to stat/stat64 conversion for Linux. + Copyright (C) 2018 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 + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <stddef.h> +#include <string.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <kernel_stat.h> + +#include <sysdep.h> +#include <sys/syscall.h> + +#if !defined(__NR3264_fstatat) && __WORDSIZE == 32 +void +__cp_stat_statx (struct stat *to, struct statx *from) +{ + memset(to, 0, sizeof(struct stat)); + to->st_dev = (from->stx_dev_minor & 0xff) | (from->stx_dev_major << 8) | + ((from->stx_dev_minor & ~0xff) << 12); + to->st_rdev = (from->stx_rdev_minor & 0xff) | (from->stx_rdev_major << 8) | + ((from->stx_rdev_minor & ~0xff) << 12); + to->st_ino = from->stx_ino; + to->st_mode = from->stx_mode; + to->st_nlink = from->stx_nlink; + to->st_uid = from->stx_uid; + to->st_gid = from->stx_gid; + to->st_atime = from->stx_atime.tv_sec; + to->st_atim.tv_nsec = from->stx_atime.tv_nsec; + to->st_mtime = from->stx_mtime.tv_sec; + to->st_mtim.tv_nsec = from->stx_mtime.tv_nsec; + to->st_ctime = from->stx_ctime.tv_sec; + to->st_ctim.tv_nsec = from->stx_ctime.tv_nsec; + to->st_size = from->stx_size; + to->st_blocks = from->stx_blocks; + to->st_blksize = from->stx_blksize; +} + +void +__cp_stat64_statx (struct stat64 *to, struct statx *from) +{ + memset(to, 0, sizeof(struct stat64)); + to->st_dev = (from->stx_dev_minor & 0xff) | (from->stx_dev_major << 8) | + ((from->stx_dev_minor & ~0xff) << 12); + to->st_rdev = (from->stx_rdev_minor & 0xff) | (from->stx_rdev_major << 8) | + ((from->stx_rdev_minor & ~0xff) << 12); + to->st_ino = from->stx_ino; + to->st_mode = from->stx_mode; + to->st_nlink = from->stx_nlink; + to->st_uid = from->stx_uid; + to->st_gid = from->stx_gid; + to->st_atime = from->stx_atime.tv_sec; + to->st_atim.tv_nsec = from->stx_atime.tv_nsec; + to->st_mtime = from->stx_mtime.tv_sec; + to->st_mtim.tv_nsec = from->stx_mtime.tv_nsec; + to->st_ctime = from->stx_ctime.tv_sec; + to->st_ctim.tv_nsec = from->stx_ctime.tv_nsec; + to->st_size = from->stx_size; + to->st_blocks = from->stx_blocks; + to->st_blksize = from->stx_blksize; +} +#endif diff --git a/sysdeps/unix/sysv/linux/statx_cp.h b/sysdeps/unix/sysv/linux/statx_cp.h new file mode 100644 index 0000000..7e411a7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/statx_cp.h @@ -0,0 +1,23 @@ +/* Struct statx to stat/stat64 conversion for Linux. + Copyright (C) 2018 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 + <http://www.gnu.org/licenses/>. */ + +extern void __cp_stat_statx (struct stat *to, struct statx *from) + attribute_hidden; + +extern void __cp_stat64_statx (struct stat64 *to, struct statx *from) + attribute_hidden;
On Wed, 21 Nov 2018, Mao Han wrote: > I'v modified patch 14/14 to a generic version with __NR3264_fstatat > conditionals (in the attachment). It is tested in the same environment > as patch V5 and got same result, but have't test fstat64 path yet. Thanks, this is the sort of thing I'm looking for, but I'm concerned about the use of __NR3264_fstatat. As I understand, that's an internal implementation detail of the asm-generic unistd.h; it shouldn't be considered something stable that will reliably be there in future kernel versions. Rather, the stable interface from asm/unistd.h is the __NR_<syscall> macros for each <syscall> provided by the kernel. So I think the #ifdef conditionals need to be on the actual syscalls used in each case (e.g. you'd condition on __NR_fstat64 when using fstat64 in the existing INLINE_SYSCALL use). In statx_cp.c you'll need to find some stat syscall to condition on that's present on all existing architectures, as the aim is that no existing glibc architecture should get any code compiled from that file (which you could check using build-many-glibcs.py). Also, it's a bad idea to duplicate the contents of sysdeps/unix/sysv/linux/fxstat64.c in sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat64.c - rather, keep the existing #include, and modify sysdeps/unix/sysv/linux/fxstat64.c appropriately to handle the statx case (which definitely requires using __NR_fstat64 in the #ifdef, since this file is used in cases not using the asm-generic syscall list at all). You're using AT_NO_AUTOMOUNT in these statx calls - does that match what the old stat syscalls do on other architectures? (I think the aim there should be to match the old stat syscalls, so if those don't automount for stat of an automount point, then using AT_NO_AUTOMOUNT is correct.) The indentation in the changes to sysdeps/unix/sysv/linux/Makefile seems to be off. In statx_cp.c you're breaking lines after operators, but they should be broken before operators (and have parentheses used in such cases to ensure the continuation line is properly indented automatically, see the GNU Coding Standards).
On Wed, Nov 21, 2018 at 6:01 PM Joseph Myers <joseph@codesourcery.com> wrote: > > On Wed, 21 Nov 2018, Mao Han wrote: > > > I'v modified patch 14/14 to a generic version with __NR3264_fstatat > > conditionals (in the attachment). It is tested in the same environment > > as patch V5 and got same result, but have't test fstat64 path yet. > > Thanks, this is the sort of thing I'm looking for, but I'm concerned about > the use of __NR3264_fstatat. As I understand, that's an internal > implementation detail of the asm-generic unistd.h; it shouldn't be > considered something stable that will reliably be there in future kernel > versions. Rather, the stable interface from asm/unistd.h is the > __NR_<syscall> macros for each <syscall> provided by the kernel. So I > think the #ifdef conditionals need to be on the actual syscalls used in > each case (e.g. you'd condition on __NR_fstat64 when using fstat64 in the > existing INLINE_SYSCALL use). In statx_cp.c you'll need to find some stat > syscall to condition on that's present on all existing architectures, as > the aim is that no existing glibc architecture should get any code > compiled from that file (which you could check using > build-many-glibcs.py). Sorry, that was my mistake. __NR3264_fstatat and the related macros will be gone in 4.20, I just haven't forwarded the patch to hide them for csky and other statx() based architectures. Arnd
On Wed, Nov 21, 2018 at 05:01:32PM +0000, Joseph Myers wrote: > On Wed, 21 Nov 2018, Mao Han wrote: > > > I'v modified patch 14/14 to a generic version with __NR3264_fstatat > > conditionals (in the attachment). It is tested in the same environment > > as patch V5 and got same result, but have't test fstat64 path yet. > > Thanks, this is the sort of thing I'm looking for, but I'm concerned about > the use of __NR3264_fstatat. As I understand, that's an internal > implementation detail of the asm-generic unistd.h; it shouldn't be > considered something stable that will reliably be there in future kernel > versions. Rather, the stable interface from asm/unistd.h is the > __NR_<syscall> macros for each <syscall> provided by the kernel. So I > think the #ifdef conditionals need to be on the actual syscalls used in > each case (e.g. you'd condition on __NR_fstat64 when using fstat64 in the > existing INLINE_SYSCALL use). In statx_cp.c you'll need to find some stat > syscall to condition on that's present on all existing architectures, as > the aim is that no existing glibc architecture should get any code > compiled from that file (which you could check using > build-many-glibcs.py). Yes. __NR_<syscall> macros should be used here. I'v change __NR3264_fstat* to __NR_fstat*. Current unistd.h alway have __NR_fstatat64 defined to __NR3264_fstatat for 32-bit platform, so I used __NR3264_fstatat to make conditionals work. As Arnd said that __NR3264_fstatat and the related macro will be gone in 4.20 and the patch is not forwarded yet, C-SKY will get some compile error with current kernel header, I added some conditionals in unistd.h for test: +#if defined(__ARCH_WANT_NEW_STAT) || defined(__ARCH_WANT_STAT64) #define __NR_fstatat64 __NR3264_fstatat #define __NR_fstat64 __NR3264_fstat +#endif Current statx_cp.c will check __NR_fstat64, __NR_fstatat64, __WORDSIZE == 32 to see if it is a 32 bit platforms without fstat64; __NR_fstat and __NR_newfstatat check is for mips64-*-n32 and x86_64-*-x32 they always use 64 bit system call but got __WORDSIZE == 32. I'v add an #error in statx_cp.c while using build-many-glibcs.py to do the build test. Seems no other arch compiled code inside statx_cp.c > Also, it's a bad idea to duplicate the contents of > sysdeps/unix/sysv/linux/fxstat64.c in > sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat64.c - rather, keep the > existing #include, and modify sysdeps/unix/sysv/linux/fxstat64.c > appropriately to handle the statx case (which definitely requires using > __NR_fstat64 in the #ifdef, since this file is used in cases not using the > asm-generic syscall list at all). > OK. I've modified sysdeps/unix/sysv/linux/fxstat64.c directly. I was quite hesitate to change that file as it will affect more arch. > You're using AT_NO_AUTOMOUNT in these statx calls - does that match what > the old stat syscalls do on other architectures? (I think the aim there > should be to match the old stat syscalls, so if those don't automount for > stat of an automount point, then using AT_NO_AUTOMOUNT is correct.) AT_NO_AUTOMOUNT is from ./include/linux/fs.h in the kernel. fstatat64 will call vfs_fstatat and fstat64 will call vfs_stat; they both got AT_NO_AUTOMOUNT inside in call. static inline int vfs_stat(const char __user *filename, struct kstat *stat) { return vfs_statx(AT_FDCWD, filename, AT_NO_AUTOMOUNT, stat, STATX_BASIC_STATS); } static inline int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat, int flags) { return vfs_statx(dfd, filename, flags | AT_NO_AUTOMOUNT, stat, STATX_BASIC_STATS); } Best Regards, Mao Han From d1a3b0fc2cd91f7a969468fd28c7eef27a2359c6 Mon Sep 17 00:00:00 2001 Message-Id: <d1a3b0fc2cd91f7a969468fd28c7eef27a2359c6.1542960800.git.han_mao@c-sky.com> From: Mao Han <han_mao@c-sky.com> Date: Fri, 23 Nov 2018 15:46:20 +0800 Subject: [PATCH V2 1/1] Add statx conditionals for wordsize-32 *xstat.c Linux kernel have remove stat64 family from default syscall set, new implementations with statx is needed when __ARCH_WANT_STAT64 is not define. This patch add conditionals for relevant functions, using statx system call to get information and then copy to the return buf, ref to include/linux/fs.h from linux kernel. * sysdeps/unix/sysv/linux/Makefile: Add statx_cp.c. * sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c: Add conditionals for kernel without stat64. * sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat64.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat64.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c: Likewise. * sysdeps/unix/sysv/linux/statx_cp.c: New file. * sysdeps/unix/sysv/linux/statx_cp.h: Likewise. --- sysdeps/unix/sysv/linux/Makefile | 3 +- sysdeps/unix/sysv/linux/fxstat64.c | 13 +++- sysdeps/unix/sysv/linux/fxstatat64.c | 11 +++ .../unix/sysv/linux/generic/wordsize-32/fxstat.c | 11 +++ .../unix/sysv/linux/generic/wordsize-32/fxstatat.c | 11 +++ .../unix/sysv/linux/generic/wordsize-32/lxstat.c | 11 +++ .../unix/sysv/linux/generic/wordsize-32/lxstat64.c | 19 +++++- .../unix/sysv/linux/generic/wordsize-32/xstat.c | 10 +++ .../unix/sysv/linux/generic/wordsize-32/xstat64.c | 14 +++- sysdeps/unix/sysv/linux/statx_cp.c | 78 ++++++++++++++++++++++ sysdeps/unix/sysv/linux/statx_cp.h | 23 +++++++ 11 files changed, 199 insertions(+), 5 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/statx_cp.c create mode 100644 sysdeps/unix/sysv/linux/statx_cp.h diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 72b6b64..2943a10 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -177,7 +177,8 @@ sysdep_routines += xstatconv internal_statvfs internal_statvfs64 \ close_nocancel fcntl_nocancel nanosleep_nocancel \ open_nocancel open64_nocancel \ openat_nocancel openat64_nocancel \ - pause_nocancel read_nocancel waitpid_nocancel write_nocancel + pause_nocancel read_nocancel waitpid_nocancel \ + write_nocancel statx_cp sysdep_headers += bits/fcntl-linux.h diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c index 0d05389..e2e51dc 100644 --- a/sysdeps/unix/sysv/linux/fxstat64.c +++ b/sysdeps/unix/sysv/linux/fxstat64.c @@ -1,4 +1,4 @@ -/* fxstat64 using Linux fstat64 system call. +/* fxstat64 using Linux fstat64/statx system call. Copyright (C) 1997-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -18,6 +18,7 @@ #include <errno.h> #include <stddef.h> +#include <fcntl.h> #include <sys/stat.h> #include <kernel_stat.h> @@ -26,13 +27,23 @@ #include <kernel-features.h> +#include "statx_cp.h" + /* Get information about the file FD in BUF. */ int ___fxstat64 (int vers, int fd, struct stat64 *buf) { int result; +#ifdef __NR_fstat64 result = INLINE_SYSCALL (fstat64, 2, fd, buf); +#else + struct statx tmp; + result = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH, STATX_BASIC_STATS, + &tmp); + if (result == 0) + __cp_stat64_statx (buf, &tmp); +#endif #if defined _HAVE_STAT64___ST_INO && !__ASSUME_ST_INO_64_BIT if (__builtin_expect (!result, 1) && buf->__st_ino != (__ino_t) buf->st_ino) buf->st_ino = buf->__st_ino; diff --git a/sysdeps/unix/sysv/linux/fxstatat64.c b/sysdeps/unix/sysv/linux/fxstatat64.c index baa9a60..95123ed 100644 --- a/sysdeps/unix/sysv/linux/fxstatat64.c +++ b/sysdeps/unix/sysv/linux/fxstatat64.c @@ -26,6 +26,8 @@ #include <sysdep.h> #include <sys/syscall.h> +#include "statx_cp.h" + /* Get information about the file NAME in BUF. */ int @@ -37,7 +39,16 @@ __fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag) int result; INTERNAL_SYSCALL_DECL (err); +#ifdef __NR_fstatat64 result = INTERNAL_SYSCALL (fstatat64, err, 4, fd, file, st, flag); +#else + struct statx tmp; + + result = INTERNAL_SYSCALL (statx, err, 5, fd, file, AT_NO_AUTOMOUNT | flag, + STATX_BASIC_STATS, &tmp); + if (result == 0) + __cp_stat64_statx (st, &tmp); +#endif if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1)) return 0; else diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c index b5c766d..0c0ff10 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c @@ -18,6 +18,7 @@ #include <errno.h> #include <stddef.h> +#include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <kernel_stat.h> @@ -27,6 +28,7 @@ #if !XSTAT_IS_XSTAT64 #include "overflow.h" +#include "statx_cp.h" /* Get information about the file FD in BUF. */ int @@ -34,8 +36,17 @@ __fxstat (int vers, int fd, struct stat *buf) { if (vers == _STAT_VER_KERNEL) { +# ifdef __NR_fstat64 int rc = INLINE_SYSCALL (fstat64, 2, fd, buf); return rc ?: stat_overflow (buf); +# else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat_statx (buf, &tmp); + return rc; +# endif } errno = EINVAL; diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c index 0bda8f7..58e3a90 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c @@ -28,6 +28,7 @@ #if !XSTAT_IS_XSTAT64 #include "overflow.h" +#include "statx_cp.h" /* Get information about the file NAME in BUF. */ int @@ -35,8 +36,18 @@ __fxstatat (int vers, int fd, const char *file, struct stat *buf, int flag) { if (vers == _STAT_VER_KERNEL) { +# ifdef __NR_fstatat64 int rc = INLINE_SYSCALL (fstatat64, 4, fd, file, buf, flag); return rc ?: stat_overflow (buf); +# else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, fd, file, + AT_NO_AUTOMOUNT | flag, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat_statx (buf, &tmp); + return rc; +# endif } errno = EINVAL; diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c index c278a4d..b680782 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c @@ -27,6 +27,7 @@ #if !XSTAT_IS_XSTAT64 #include "overflow.h" +#include "statx_cp.h" /* Get information about the file NAME in BUF. */ int @@ -34,9 +35,19 @@ __lxstat (int vers, const char *name, struct stat *buf) { if (vers == _STAT_VER_KERNEL) { +#ifdef __NR_fstatat64 int rc = INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, AT_SYMLINK_NOFOLLOW); return rc ?: stat_overflow (buf); +#else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat_statx (buf, &tmp); + return rc; +#endif } errno = EINVAL; return -1; diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c index 761dd16..c41c759 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c @@ -32,13 +32,28 @@ #include <sysdep.h> #include <sys/syscall.h> +#include "statx_cp.h" + /* Get information about the file NAME in BUF. */ int __lxstat64 (int vers, const char *name, struct stat64 *buf) { if (vers == _STAT_VER_KERNEL) - return INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, - AT_SYMLINK_NOFOLLOW); + { +#ifdef __NR_fstatat64 + return INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, + AT_SYMLINK_NOFOLLOW); +#else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat64_statx (buf, &tmp); + return rc; +#endif + } + errno = EINVAL; return -1; } diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c index 1fd57ff..b67f4bb 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c @@ -27,6 +27,7 @@ #if !XSTAT_IS_XSTAT64 #include "overflow.h" +#include "statx_cp.h" /* Get information about the file NAME in BUF. */ int @@ -34,8 +35,17 @@ __xstat (int vers, const char *name, struct stat *buf) { if (vers == _STAT_VER_KERNEL) { +# ifdef __NR_fstatat64 int rc = INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, 0); return rc ?: stat_overflow (buf); +# else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, AT_NO_AUTOMOUNT, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat_statx (buf, &tmp); + return rc; +# endif } errno = EINVAL; diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c index ae70495..209675e 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c @@ -32,13 +32,25 @@ #include <sysdep.h> #include <sys/syscall.h> +#include "statx_cp.h" + /* Get information about the file NAME in BUF. */ int __xstat64 (int vers, const char *name, struct stat64 *buf) { if (vers == _STAT_VER_KERNEL) + { +#ifdef __NR_fstatat64 return INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, 0); - +#else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, AT_NO_AUTOMOUNT, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat64_statx (buf, &tmp); + return rc; +#endif + } errno = EINVAL; return -1; } diff --git a/sysdeps/unix/sysv/linux/statx_cp.c b/sysdeps/unix/sysv/linux/statx_cp.c new file mode 100644 index 0000000..f31f5da4 --- /dev/null +++ b/sysdeps/unix/sysv/linux/statx_cp.c @@ -0,0 +1,78 @@ +/* Struct statx to stat/stat64 conversion for Linux. + Copyright (C) 2018 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 + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <stddef.h> +#include <string.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <kernel_stat.h> + +#include <sysdep.h> +#include <sys/syscall.h> + +#if !defined(__NR_fstat64) && !defined(__NR_fstatat64) && __WORDSIZE == 32 \ + && !defined(__NR_fstat) && !defined(__NR_newfstatat) +void +__cp_stat_statx (struct stat *to, struct statx *from) +{ + memset(to, 0, sizeof(struct stat)); + to->st_dev = ((from->stx_dev_minor & 0xff) | (from->stx_dev_major << 8) + | ((from->stx_dev_minor & ~0xff) << 12)); + to->st_rdev = ((from->stx_rdev_minor & 0xff) | (from->stx_rdev_major << 8) + | ((from->stx_rdev_minor & ~0xff) << 12)); + to->st_ino = from->stx_ino; + to->st_mode = from->stx_mode; + to->st_nlink = from->stx_nlink; + to->st_uid = from->stx_uid; + to->st_gid = from->stx_gid; + to->st_atime = from->stx_atime.tv_sec; + to->st_atim.tv_nsec = from->stx_atime.tv_nsec; + to->st_mtime = from->stx_mtime.tv_sec; + to->st_mtim.tv_nsec = from->stx_mtime.tv_nsec; + to->st_ctime = from->stx_ctime.tv_sec; + to->st_ctim.tv_nsec = from->stx_ctime.tv_nsec; + to->st_size = from->stx_size; + to->st_blocks = from->stx_blocks; + to->st_blksize = from->stx_blksize; +} + +void +__cp_stat64_statx (struct stat64 *to, struct statx *from) +{ + memset(to, 0, sizeof(struct stat64)); + to->st_dev = ((from->stx_dev_minor & 0xff) | (from->stx_dev_major << 8) + | ((from->stx_dev_minor & ~0xff) << 12)); + to->st_rdev = ((from->stx_rdev_minor & 0xff) | (from->stx_rdev_major << 8) + | ((from->stx_rdev_minor & ~0xff) << 12)); + to->st_ino = from->stx_ino; + to->st_mode = from->stx_mode; + to->st_nlink = from->stx_nlink; + to->st_uid = from->stx_uid; + to->st_gid = from->stx_gid; + to->st_atime = from->stx_atime.tv_sec; + to->st_atim.tv_nsec = from->stx_atime.tv_nsec; + to->st_mtime = from->stx_mtime.tv_sec; + to->st_mtim.tv_nsec = from->stx_mtime.tv_nsec; + to->st_ctime = from->stx_ctime.tv_sec; + to->st_ctim.tv_nsec = from->stx_ctime.tv_nsec; + to->st_size = from->stx_size; + to->st_blocks = from->stx_blocks; + to->st_blksize = from->stx_blksize; +} +#endif diff --git a/sysdeps/unix/sysv/linux/statx_cp.h b/sysdeps/unix/sysv/linux/statx_cp.h new file mode 100644 index 0000000..7e411a7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/statx_cp.h @@ -0,0 +1,23 @@ +/* Struct statx to stat/stat64 conversion for Linux. + Copyright (C) 2018 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 + <http://www.gnu.org/licenses/>. */ + +extern void __cp_stat_statx (struct stat *to, struct statx *from) + attribute_hidden; + +extern void __cp_stat64_statx (struct stat64 *to, struct statx *from) + attribute_hidden;
On Fri, 23 Nov 2018, Mao Han wrote: > Current statx_cp.c will check __NR_fstat64, __NR_fstatat64, __WORDSIZE > == 32 to see if it is a 32 bit platforms without fstat64; __NR_fstat and > __NR_newfstatat check is for mips64-*-n32 and x86_64-*-x32 they always > use 64 bit system call but got __WORDSIZE == 32. That might give the right conditions for current glibc platforms, but I don't think it's logically correct - putting conditions on __NR_fstat and __NR_newfstatat, when none of the files using statx also use those syscalls, is hardly a clean approach. Since the way in which those platforms avoid using the files in question is through having their own sysdeps override files that either contain just comments or reimplement the functions in question, my suggestion would be to have statx_cp.c files in sysdeps/unix/sysv/linux/wordsize-64 and sysdeps/unix/sysv/linux/mips/mips64, containing just a comment. Then the conditional in the main statx_cp.c file would be #if !defined(__NR_fstat64) || !defined(__NR_fstatat64) (note this is || not &&, because if either macro is undefined, the relevant source file will use statx). Note that the ChangeLog entry needs updating to reflect the actual set of files modified (it still refers to wordsize-32 for two files being modified outside of the wordsize-32 directory). > +#include "statx_cp.h" I think these includes should be of <statx_cp.h> not "statx_cp.h" - in general, #include <> should be preferred to avoid any problems overriding a file in another sysdeps directory if necessary. You're missing an include of statx_cp.h from statx_cp.c. It's important to include the header from the file defining the corresponding functions, so that the compiler checks the prototypes in the two places are consistent. > +__cp_stat_statx (struct stat *to, struct statx *from) > +{ > + memset(to, 0, sizeof(struct stat)); Missing space before '(', twice on this line. > + memset(to, 0, sizeof(struct stat64)); Likewise. I also note that when the generic/wordsize-32 files use the existing syscalls, they use stat_overflow in the case of success to ensure that if any of the fields overflow the 32-bit versions in struct stat, an error is properly returned with errno set to EOVERFLOW. This patch seems to be missing anything like that in the case where statx is used - indeed, __cp_stat_statx returns void, so preventing it from indicating an error to the caller. It's probably a bad idea to duplicate the logic for such overflow checks - rather, the existing stat_overflow code should be used. Maybe eliminate __cp_stat_statx, make the callers cast to (struct stat64 *) and call __cp_stat64_statx and then use stat_overflow in the callers? (As all the cases needing this check are in generic/wordsize-32, we know that the stat and stat64 layouts are the same, just differing in whether or not high parts are counted as padding. Because statx_cp.c is in a separate translation unit and glibc uses C with ABI boundaries, doing the cast in a caller like that is safe, whereas defining __cp_stat_statx to do such a cast, call and then check with stat_overflow, in the same translation unit as the __cp_stat64_statx definition, could run into aliasing issues.)
On Mon, Nov 19, 2018 at 04:45:09PM +0000, Joseph Myers wrote: > As far as I can tell, in the current version of the gcc_AC_INITFINI_ARRAY > test, the only part that's an execution test is the ia64 case. That is, > for every other target, the 'if test "x${build}" = "x${target}" && test > "x${build}" = "x${host}"' condition is bogus as the rest of the tests > would work just as well for cross compilation. (In the ia64 case, the > fourth argument to AC_RUN_IFELSE - the action if cross compiling - is > already there. So simply removing the requirement for build = host = > target should allow things to work for cross compiling as well as for > native except on ia64, and someone using ia64 could always fix that case > later to have better cross compilation defaults based on the target OS.) > We'v tried to remove this condition, but seems doesn't meet our expectation. The ia64 case seems only get a test need to run on the target, return -1 when init_array is not support. I didn't found any AC_RUN_IFELSE in current gcc 9.0 gcc/configure. The *) case seems can return gcc_cv_initfini_array=yes on C-SKY target, but it only check whether tools can generate init_array section, not libc use init_array or not. On Fri, Nov 23, 2018 at 05:11:35PM +0000, Joseph Myers wrote: > Since the way in which those platforms avoid using the files in question > is through having their own sysdeps override files that either contain > just comments or reimplement the functions in question, my suggestion > would be to have statx_cp.c files in sysdeps/unix/sysv/linux/wordsize-64 > and sysdeps/unix/sysv/linux/mips/mips64, containing just a comment. Then > the conditional in the main statx_cp.c file would be Thanks for suggestion. I'v tried to add statx_cp.c under sysdeps/unix/sysv/linux/mips/mips64, and something got wrong while glibc is configured for mips: PASS: compilers-mips64-linux-gnu-soft glibc mips64-linux-gnu-n64-soft copy *** Error in `/home/vmh/disk2/buildmany/install/compilers/mips64-linux-gnu-soft/lib/gcc/mips64-glibc-linux-gnu/9.0.0/../../../../mips64-glibc-linux-gnu/bin/ld': free(): invalid next size (fast): 0x000000000250c100 *** ======= Backtrace: ========= /lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f45a2d417e5] /lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7f45a2d4a37a] /lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f45a2d4e53c] /home/vmh/disk2/buildmany/install/compilers/mips64-linux-gnu-soft/lib/gcc/mips64-glibc-linux-gnu/9.0.0/../../../../mips64-glibc-linux-gnu/bin/ld[0x4440c0] /home/vmh/disk2/buildmany/install/compilers/mips64-linux-gnu-soft/lib/gcc/mips64-glibc-linux-gnu/9.0.0/../../../../mips64-glibc-linux-gnu/bin/ld[0x4926bf] /home/vmh/disk2/buildmany/install/compilers/mips64-linux-gnu-soft/lib/gcc/mips64-glibc-linux-gnu/9.0.0/../../../../mips64-glibc-linux-gnu/bin/ld[0x467c22] ... PASS: compilers-mips64-linux-gnu-nan2008-soft glibc mips64-linux-gnu-n64-nan2008-soft configure The final result is PASS. I haven't found the rootcause yet. > It's probably a bad idea to duplicate the logic for such overflow checks - > rather, the existing stat_overflow code should be used. Maybe eliminate > __cp_stat_statx, make the callers cast to (struct stat64 *) and call > __cp_stat64_statx and then use stat_overflow in the callers? (As all the > cases needing this check are in generic/wordsize-32, we know that the stat > and stat64 layouts are the same, just differing in whether or not high > parts are counted as padding. Because statx_cp.c is in a separate > translation unit and glibc uses C with ABI boundaries, doing the cast in a > caller like that is safe, whereas defining __cp_stat_statx to do such a > cast, call and then check with stat_overflow, in the same translation unit > as the __cp_stat64_statx definition, could run into aliasing issues.) I used __cp_stat_statx in the last patch, the high part will cut off when assign a 64bit variable to a 32bit one. The padding seems will never become non-zero, so I didn't use stat_overflow in last patch. In order to return whether st_ino, st_size, st_blocks are overflowed, the high part should be keeped or some check is needed on statx result? So make the callers cast to (struct stat64 *) and call __cp_stat64_statx will make the funcion behavior exactly same as the old one? Best Regards, Mao Han From 9bb30a741a5665296997235ed89ced51a23e9048 Mon Sep 17 00:00:00 2001 Message-Id: <9bb30a741a5665296997235ed89ced51a23e9048.1543216869.git.han_mao@c-sky.com> From: Mao Han <han_mao@c-sky.com> Date: Mon, 26 Nov 2018 11:13:32 +0800 Subject: [PATCH v3 1/1] Add statx conditionals for wordsize-32 *xstat.c Linux kernel have remove stat64 family from default syscall set, new implementations with statx is needed when __ARCH_WANT_STAT64 is not define. This patch add conditionals for relevant functions, using statx system call to get information and then copy to the return buf, ref to include/linux/fs.h from linux kernel. * sysdeps/unix/sysv/linux/Makefile: Add statx_cp.c. * sysdeps/unix/sysv/linux/fxstat64.c: Add conditionals for kernel without stat64 system call support. * sysdeps/unix/sysv/linux/fxstatat64.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c: Likewise. * sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c: Likewise. * sysdeps/unix/sysv/linux/mips/mips64/statx_cp.c: New file. * sysdeps/unix/sysv/linux/statx_cp.c: Likewise. * sysdeps/unix/sysv/linux/statx_cp.h: Likewise. * sysdeps/unix/sysv/linux/wordsize-64/statx_cp.c: Likewise. --- sysdeps/unix/sysv/linux/Makefile | 3 +- sysdeps/unix/sysv/linux/fxstat64.c | 12 +++++- sysdeps/unix/sysv/linux/fxstatat64.c | 11 +++++ .../unix/sysv/linux/generic/wordsize-32/fxstat.c | 11 +++++ .../unix/sysv/linux/generic/wordsize-32/fxstatat.c | 11 +++++ .../unix/sysv/linux/generic/wordsize-32/lxstat.c | 11 +++++ .../unix/sysv/linux/generic/wordsize-32/lxstat64.c | 19 ++++++++- .../unix/sysv/linux/generic/wordsize-32/xstat.c | 10 +++++ .../unix/sysv/linux/generic/wordsize-32/xstat64.c | 14 ++++++- sysdeps/unix/sysv/linux/mips/mips64/statx_cp.c | 3 ++ sysdeps/unix/sysv/linux/statx_cp.c | 49 ++++++++++++++++++++++ sysdeps/unix/sysv/linux/statx_cp.h | 23 ++++++++++ sysdeps/unix/sysv/linux/wordsize-64/statx_cp.c | 3 ++ 13 files changed, 175 insertions(+), 5 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/mips/mips64/statx_cp.c create mode 100644 sysdeps/unix/sysv/linux/statx_cp.c create mode 100644 sysdeps/unix/sysv/linux/statx_cp.h create mode 100644 sysdeps/unix/sysv/linux/wordsize-64/statx_cp.c diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 72b6b64..2943a10 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -177,7 +177,8 @@ sysdep_routines += xstatconv internal_statvfs internal_statvfs64 \ close_nocancel fcntl_nocancel nanosleep_nocancel \ open_nocancel open64_nocancel \ openat_nocancel openat64_nocancel \ - pause_nocancel read_nocancel waitpid_nocancel write_nocancel + pause_nocancel read_nocancel waitpid_nocancel \ + write_nocancel statx_cp sysdep_headers += bits/fcntl-linux.h diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c index 0d05389..b0c5271 100644 --- a/sysdeps/unix/sysv/linux/fxstat64.c +++ b/sysdeps/unix/sysv/linux/fxstat64.c @@ -1,4 +1,4 @@ -/* fxstat64 using Linux fstat64 system call. +/* fxstat64 using Linux fstat64/statx system call. Copyright (C) 1997-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -18,6 +18,7 @@ #include <errno.h> #include <stddef.h> +#include <fcntl.h> #include <sys/stat.h> #include <kernel_stat.h> @@ -25,6 +26,7 @@ #include <sys/syscall.h> #include <kernel-features.h> +#include <statx_cp.h> /* Get information about the file FD in BUF. */ @@ -32,7 +34,15 @@ int ___fxstat64 (int vers, int fd, struct stat64 *buf) { int result; +#ifdef __NR_fstat64 result = INLINE_SYSCALL (fstat64, 2, fd, buf); +#else + struct statx tmp; + result = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH, STATX_BASIC_STATS, + &tmp); + if (result == 0) + __cp_stat64_statx (buf, &tmp); +#endif #if defined _HAVE_STAT64___ST_INO && !__ASSUME_ST_INO_64_BIT if (__builtin_expect (!result, 1) && buf->__st_ino != (__ino_t) buf->st_ino) buf->st_ino = buf->__st_ino; diff --git a/sysdeps/unix/sysv/linux/fxstatat64.c b/sysdeps/unix/sysv/linux/fxstatat64.c index baa9a60..767d55c 100644 --- a/sysdeps/unix/sysv/linux/fxstatat64.c +++ b/sysdeps/unix/sysv/linux/fxstatat64.c @@ -26,6 +26,8 @@ #include <sysdep.h> #include <sys/syscall.h> +#include <statx_cp.h> + /* Get information about the file NAME in BUF. */ int @@ -37,7 +39,16 @@ __fxstatat64 (int vers, int fd, const char *file, struct stat64 *st, int flag) int result; INTERNAL_SYSCALL_DECL (err); +#ifdef __NR_fstatat64 result = INTERNAL_SYSCALL (fstatat64, err, 4, fd, file, st, flag); +#else + struct statx tmp; + + result = INTERNAL_SYSCALL (statx, err, 5, fd, file, AT_NO_AUTOMOUNT | flag, + STATX_BASIC_STATS, &tmp); + if (result == 0) + __cp_stat64_statx (st, &tmp); +#endif if (!__builtin_expect (INTERNAL_SYSCALL_ERROR_P (result, err), 1)) return 0; else diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c index b5c766d..654c5e0 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstat.c @@ -18,6 +18,7 @@ #include <errno.h> #include <stddef.h> +#include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <kernel_stat.h> @@ -27,6 +28,7 @@ #if !XSTAT_IS_XSTAT64 #include "overflow.h" +#include <statx_cp.h> /* Get information about the file FD in BUF. */ int @@ -34,8 +36,17 @@ __fxstat (int vers, int fd, struct stat *buf) { if (vers == _STAT_VER_KERNEL) { +# ifdef __NR_fstat64 int rc = INLINE_SYSCALL (fstat64, 2, fd, buf); return rc ?: stat_overflow (buf); +# else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, fd, "", AT_EMPTY_PATH, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat64_statx ((struct stat64 *)buf, &tmp); + return rc ?: stat_overflow (buf); +# endif } errno = EINVAL; diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c index 0bda8f7..1b385cc 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/fxstatat.c @@ -28,6 +28,7 @@ #if !XSTAT_IS_XSTAT64 #include "overflow.h" +#include <statx_cp.h> /* Get information about the file NAME in BUF. */ int @@ -35,8 +36,18 @@ __fxstatat (int vers, int fd, const char *file, struct stat *buf, int flag) { if (vers == _STAT_VER_KERNEL) { +# ifdef __NR_fstatat64 int rc = INLINE_SYSCALL (fstatat64, 4, fd, file, buf, flag); return rc ?: stat_overflow (buf); +# else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, fd, file, + AT_NO_AUTOMOUNT | flag, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat64_statx ((struct stat64 *)buf, &tmp); + return rc ?: stat_overflow (buf); +# endif } errno = EINVAL; diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c index c278a4d..d6c8824 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat.c @@ -27,6 +27,7 @@ #if !XSTAT_IS_XSTAT64 #include "overflow.h" +#include <statx_cp.h> /* Get information about the file NAME in BUF. */ int @@ -34,9 +35,19 @@ __lxstat (int vers, const char *name, struct stat *buf) { if (vers == _STAT_VER_KERNEL) { +#ifdef __NR_fstatat64 int rc = INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, AT_SYMLINK_NOFOLLOW); return rc ?: stat_overflow (buf); +#else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat64_statx ((struct stat64 *)buf, &tmp); + return rc ?: stat_overflow (buf); +#endif } errno = EINVAL; return -1; diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c index 761dd16..86b7a98 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/lxstat64.c @@ -32,13 +32,28 @@ #include <sysdep.h> #include <sys/syscall.h> +#include <statx_cp.h> + /* Get information about the file NAME in BUF. */ int __lxstat64 (int vers, const char *name, struct stat64 *buf) { if (vers == _STAT_VER_KERNEL) - return INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, - AT_SYMLINK_NOFOLLOW); + { +#ifdef __NR_fstatat64 + return INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, + AT_SYMLINK_NOFOLLOW); +#else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat64_statx (buf, &tmp); + return rc; +#endif + } + errno = EINVAL; return -1; } diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c index 1fd57ff..753f91e 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat.c @@ -27,6 +27,7 @@ #if !XSTAT_IS_XSTAT64 #include "overflow.h" +#include <statx_cp.h> /* Get information about the file NAME in BUF. */ int @@ -34,8 +35,17 @@ __xstat (int vers, const char *name, struct stat *buf) { if (vers == _STAT_VER_KERNEL) { +# ifdef __NR_fstatat64 int rc = INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, 0); return rc ?: stat_overflow (buf); +# else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, AT_NO_AUTOMOUNT, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat64_statx ((struct stat64 *)buf, &tmp); + return rc ?: stat_overflow (buf); +# endif } errno = EINVAL; diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c index ae70495..8b38926 100644 --- a/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c +++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/xstat64.c @@ -32,13 +32,25 @@ #include <sysdep.h> #include <sys/syscall.h> +#include <statx_cp.h> + /* Get information about the file NAME in BUF. */ int __xstat64 (int vers, const char *name, struct stat64 *buf) { if (vers == _STAT_VER_KERNEL) + { +#ifdef __NR_fstatat64 return INLINE_SYSCALL (fstatat64, 4, AT_FDCWD, name, buf, 0); - +#else + struct statx tmp; + int rc = INLINE_SYSCALL (statx, 5, AT_FDCWD, name, AT_NO_AUTOMOUNT, + STATX_BASIC_STATS, &tmp); + if (rc == 0) + __cp_stat64_statx (buf, &tmp); + return rc; +#endif + } errno = EINVAL; return -1; } diff --git a/sysdeps/unix/sysv/linux/mips/mips64/statx_cp.c b/sysdeps/unix/sysv/linux/mips/mips64/statx_cp.c new file mode 100644 index 0000000..260cda9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/mips/mips64/statx_cp.c @@ -0,0 +1,3 @@ +/* Override the generic statx_cp.c which is only needed for new 32-bit arch + without stat64 family support. + */ diff --git a/sysdeps/unix/sysv/linux/statx_cp.c b/sysdeps/unix/sysv/linux/statx_cp.c new file mode 100644 index 0000000..04a13fa --- /dev/null +++ b/sysdeps/unix/sysv/linux/statx_cp.c @@ -0,0 +1,49 @@ +/* Struct statx to stat/stat64 conversion for Linux. + Copyright (C) 2018 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 + <http://www.gnu.org/licenses/>. */ + +#include <stddef.h> +#include <string.h> +#include <sys/stat.h> + +#include <statx_cp.h> + +#if !defined(__NR_fstat64) || !defined(__NR_fstatat64) +void +__cp_stat64_statx (struct stat64 *to, struct statx *from) +{ + memset (to, 0, sizeof (struct stat64)); + to->st_dev = ((from->stx_dev_minor & 0xff) | (from->stx_dev_major << 8) + | ((from->stx_dev_minor & ~0xff) << 12)); + to->st_rdev = ((from->stx_rdev_minor & 0xff) | (from->stx_rdev_major << 8) + | ((from->stx_rdev_minor & ~0xff) << 12)); + to->st_ino = from->stx_ino; + to->st_mode = from->stx_mode; + to->st_nlink = from->stx_nlink; + to->st_uid = from->stx_uid; + to->st_gid = from->stx_gid; + to->st_atime = from->stx_atime.tv_sec; + to->st_atim.tv_nsec = from->stx_atime.tv_nsec; + to->st_mtime = from->stx_mtime.tv_sec; + to->st_mtim.tv_nsec = from->stx_mtime.tv_nsec; + to->st_ctime = from->stx_ctime.tv_sec; + to->st_ctim.tv_nsec = from->stx_ctime.tv_nsec; + to->st_size = from->stx_size; + to->st_blocks = from->stx_blocks; + to->st_blksize = from->stx_blksize; +} +#endif diff --git a/sysdeps/unix/sysv/linux/statx_cp.h b/sysdeps/unix/sysv/linux/statx_cp.h new file mode 100644 index 0000000..7e411a7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/statx_cp.h @@ -0,0 +1,23 @@ +/* Struct statx to stat/stat64 conversion for Linux. + Copyright (C) 2018 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 + <http://www.gnu.org/licenses/>. */ + +extern void __cp_stat_statx (struct stat *to, struct statx *from) + attribute_hidden; + +extern void __cp_stat64_statx (struct stat64 *to, struct statx *from) + attribute_hidden; diff --git a/sysdeps/unix/sysv/linux/wordsize-64/statx_cp.c b/sysdeps/unix/sysv/linux/wordsize-64/statx_cp.c new file mode 100644 index 0000000..260cda9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/wordsize-64/statx_cp.c @@ -0,0 +1,3 @@ +/* Override the generic statx_cp.c which is only needed for new 32-bit arch + without stat64 family support. + */
On Mon, 26 Nov 2018, Mao Han wrote: > We'v tried to remove this condition, but seems doesn't meet our expectation. > The ia64 case seems only get a test need to run on the target, return -1 when > init_array is not support. I didn't found any AC_RUN_IFELSE in current gcc 9.0 > gcc/configure. The *) case seems can return gcc_cv_initfini_array=yes > on C-SKY target, but it only check whether tools can generate init_array > section, not libc use init_array or not. Yes, that's right. init_array is a standard feature of ELF and has been for a very long time. So it's entirely correct that GCC should default to using it unless it knows there's a problem with support for that feature on some platform, and the present restriction to native builds is wrong. It's true that removing the restriction to native builds might help show up places where libc is missing init_array support. If it does, we can then consider whether some more selective disabling on those platforms would be appropriate - but enabling by default for ELF platforms, independent of whether native, is still the right thing to do. > PASS: compilers-mips64-linux-gnu-soft glibc mips64-linux-gnu-n64-soft copy > *** Error in `/home/vmh/disk2/buildmany/install/compilers/mips64-linux-gnu-soft/lib/gcc/mips64-glibc-linux-gnu/9.0.0/../../../../mips64-glibc-linux-gnu/bin/ld': free(): invalid next size (fast): 0x000000000250c100 *** > ======= Backtrace: ========= > /lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f45a2d417e5] > /lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7f45a2d4a37a] > /lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f45a2d4e53c] > /home/vmh/disk2/buildmany/install/compilers/mips64-linux-gnu-soft/lib/gcc/mips64-glibc-linux-gnu/9.0.0/../../../../mips64-glibc-linux-gnu/bin/ld[0x4440c0] > /home/vmh/disk2/buildmany/install/compilers/mips64-linux-gnu-soft/lib/gcc/mips64-glibc-linux-gnu/9.0.0/../../../../mips64-glibc-linux-gnu/bin/ld[0x4926bf] > /home/vmh/disk2/buildmany/install/compilers/mips64-linux-gnu-soft/lib/gcc/mips64-glibc-linux-gnu/9.0.0/../../../../mips64-glibc-linux-gnu/bin/ld[0x467c22] > ... > PASS: compilers-mips64-linux-gnu-nan2008-soft glibc mips64-linux-gnu-n64-nan2008-soft configure > > The final result is PASS. I haven't found the rootcause yet. That's a known (i.e. observed for years) linker bug, though I've no idea where the underlying cause is in binutils. > I used __cp_stat_statx in the last patch, the high part will cut off when > assign a 64bit variable to a 32bit one. The padding seems will never become > non-zero, so I didn't use stat_overflow in last patch. In order to return > whether st_ino, st_size, st_blocks are overflowed, the high part should > be keeped or some check is needed on statx result? So make the callers > cast to (struct stat64 *) and call __cp_stat64_statx will make the funcion > behavior exactly same as the old one? Yes, that's my suggestion. Silent truncation is not acceptable; if truncation occurs, it is required to produce an EOVERFLOW error, and it seems best to arrange things so that the existing overflow check code can be used for that.