Message ID | 20240822-statx-null-path-v2-1-ff74eddf1a21@gmail.com |
---|---|
State | New |
Headers | show |
Series | [v2] linux: Add linux statx(fd, NULL, AT_EMPTY_PATH) support | expand |
Hi, all I've received a notification from patchwork stating this patch caused a regression for the test tst-valgrind-smoke [1]. I'm able to reproduce this in my working environment, using qemu userspace emulation. The output of valgrind is: > ==469== Syscall param statx(filename) points to unaddressable byte(s) > ==469== at 0x11A536: __libc_do_syscall (libc-do-syscall.S:47) > ==469== by 0x11BAF1: __statx_empty_path (internal-stat.h:47) > ==469== by 0x11BAF1: fstatat64_time64_statx (fstatat64.c:53) > ==469== by 0x11BAF1: __fstatat64_time64 (fstatat64.c:154) > ==469== by 0x10C4EF: _dl_get_file_id (dl-fileid.h:37) > ==469== by 0x10C4EF: _dl_map_object_from_fd (dl-load.c:955) > ==469== by 0x10D0E3: _dl_map_object (dl-load.c:2190) > ==469== by 0x116E39: map_doit (rtld.c:644) > ==469== by 0x108DDF: _dl_catch_exception (dl-catch.c:241) > ==469== by 0x108EAB: _dl_catch_error (dl-catch.c:260) > ==469== by 0x116DE7: do_preload (rtld.c:818) > ==469== by 0x117ACD: handle_preload_list (rtld.c:894) > ==469== by 0x119B0B: dl_main (rtld.c:1849) > ==469== by 0x1167B3: _dl_sysdep_start (dl-sysdep.c:141) > ==469== by 0x117817: _dl_start_final (rtld.c:494) > ==469== by 0x117817: _dl_start (rtld.c:581) > ==469== Address 0x0 is not stack'd, malloc'd or (recently) free'd > ==469== It is because valgrind has not been updated to adapt for the newly introduced statx(fd, NULL, AT_EMPTY_PATH). The related code of valgrind is at [2]. [1]: https://ci.linaro.org/job/tcwg_glibc_check--master-arm-precommit/2361/artifact/artifacts/artifacts.precommit/notify/mail-body.txt [2]: https://sourceware.org/git/?p=valgrind.git;a=blob;f=coregrind/m_syswrap/syswrap-linux.c;h=9f3c51c17948378e501f2200be8b141aa13016b6;hb=HEAD#l4211 Cheers, Miao Wang
* Miao Wang: > I've received a notification from patchwork stating this patch caused a > regression for the test tst-valgrind-smoke [1]. > > > I'm able to reproduce this in my working environment, using qemu userspace > emulation. The output of valgrind is: > >> ==469== Syscall param statx(filename) points to unaddressable byte(s) >> ==469== at 0x11A536: __libc_do_syscall (libc-do-syscall.S:47) >> ==469== by 0x11BAF1: __statx_empty_path (internal-stat.h:47) >> ==469== by 0x11BAF1: fstatat64_time64_statx (fstatat64.c:53) >> ==469== by 0x11BAF1: __fstatat64_time64 (fstatat64.c:154) >> ==469== by 0x10C4EF: _dl_get_file_id (dl-fileid.h:37) >> ==469== by 0x10C4EF: _dl_map_object_from_fd (dl-load.c:955) >> ==469== by 0x10D0E3: _dl_map_object (dl-load.c:2190) >> ==469== by 0x116E39: map_doit (rtld.c:644) >> ==469== by 0x108DDF: _dl_catch_exception (dl-catch.c:241) >> ==469== by 0x108EAB: _dl_catch_error (dl-catch.c:260) >> ==469== by 0x116DE7: do_preload (rtld.c:818) >> ==469== by 0x117ACD: handle_preload_list (rtld.c:894) >> ==469== by 0x119B0B: dl_main (rtld.c:1849) >> ==469== by 0x1167B3: _dl_sysdep_start (dl-sysdep.c:141) >> ==469== by 0x117817: _dl_start_final (rtld.c:494) >> ==469== by 0x117817: _dl_start (rtld.c:581) >> ==469== Address 0x0 is not stack'd, malloc'd or (recently) free'd >> ==469== > > It is because valgrind has not been updated to adapt for the newly > introduced statx(fd, NULL, AT_EMPTY_PATH). The related code of valgrind > is at [2]. > > > > [1]: https://ci.linaro.org/job/tcwg_glibc_check--master-arm-precommit/2361/artifact/artifacts/artifacts.precommit/notify/mail-body.txt > [2]: https://sourceware.org/git/?p=valgrind.git;a=blob;f=coregrind/m_syswrap/syswrap-linux.c;h=9f3c51c17948378e501f2200be8b141aa13016b6;hb=HEAD#l4211 Would you please raise this as a valgrind issue? <https://bugs.kde.org/enter_bug.cgi?product=valgrind> I think valgrind really needs to be fixed (upstream) before distributions can upgrade to a glibc version with this change. The valgrind test should NOT be disabled, as a reminder that the valgrind fix needs to be backported as well. I don't know how easy it is to fix this. Currently valgrind has this: // Work around Rust's dubious use of statx, as described here: // https://github.com/rust-lang/rust/blob/ // ccd238309f9dce92a05a23c2959e2819668c69a4/ // src/libstd/sys/unix/fs.rs#L128-L142 // in which it passes NULL for both filename and buf, and then looks at the // return value, so as to determine whether or not this syscall is supported. Bool both_filename_and_buf_are_null = ARG2 == 0 && ARG5 == 0; if (!both_filename_and_buf_are_null) { PRE_MEM_RASCIIZ( "statx(filename)", ARG2 ); PRE_MEM_WRITE( "statx(buf)", ARG5, sizeof(struct vki_statx) ); } But I think we need some sort of valgrind patch before we can merge this change into glibc (or at least we'd have to revert it for Fedora rawhide). Thanks, Florian
>> >> It is because valgrind has not been updated to adapt for the newly >> introduced statx(fd, NULL, AT_EMPTY_PATH). The related code of valgrind >> is at [2]. >> >> > > Would you please raise this as a valgrind issue? > I've sent out a patch for valgrind, but it seems that the patch fails to reach the mailing list on source forge. Attached is my original patch. I wonder if someone can send it for me. Cheers, Miao Wang > > Thanks, > Florian > From: Miao Wang <shankerwangmiao@gmail.com> statx(fd, NULL, AT_EMPTY_PATH) is supported since Linux 6.11 and this patch addes the support to valgrind, so that it won't complain when NULL is used as |filename| and |flags| includes AT_EMPTY_PATH. Ref: commit 0ef625bba6fb ("vfs: support statx(..., NULL, AT_EMPTY_PATH, ...)") Signed-off-by: Miao Wang <shankerwangmiao@gmail.com> --- coregrind/m_syswrap/syswrap-linux.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 9f3c51c17..453385599 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -4209,8 +4209,12 @@ PRE(sys_statx) // in which it passes NULL for both filename and buf, and then looks at the // return value, so as to determine whether or not this syscall is supported. Bool both_filename_and_buf_are_null = ARG2 == 0 && ARG5 == 0; + Bool statx_null_path = (ARG2 == 0) && (ARG3 & VKI_AT_EMPTY_PATH); if (!both_filename_and_buf_are_null) { - PRE_MEM_RASCIIZ( "statx(filename)", ARG2 ); + // Since Linux 6.11, the kernel allows passing a NULL filename when + // the AT_EMPTY_PATH flag is set. + if (!statx_null_path) + PRE_MEM_RASCIIZ( "statx(filename)", ARG2 ); PRE_MEM_WRITE( "statx(buf)", ARG5, sizeof(struct vki_statx) ); } } --- base-commit: 61e44a4aef8775b925a7a91f403ebd7f4f6670a4 change-id: 20240824-statx-null-path-8eec6e0da3bc Best regards,
* Miao Wang: >>> >>> It is because valgrind has not been updated to adapt for the newly >>> introduced statx(fd, NULL, AT_EMPTY_PATH). The related code of valgrind >>> is at [2]. >>> >>> >> >> Would you please raise this as a valgrind issue? >> > > I've sent out a patch for valgrind, but it seems that the patch fails > to reach the mailing list on source forge. Attached is my original patch. > I wonder if someone can send it for me. You could attach it to a bug in the valgrind bug tracker: <https://bugs.kde.org/enter_bug.cgi?product=valgrind> Thanks, Florian
> 2024年8月26日 21:53,Florian Weimer <fweimer@redhat.com> 写道: > > * Miao Wang: > >>>> >>>> It is because valgrind has not been updated to adapt for the newly >>>> introduced statx(fd, NULL, AT_EMPTY_PATH). The related code of valgrind >>>> is at [2]. >>>> >>>> >>> >>> Would you please raise this as a valgrind issue? >>> >> >> I've sent out a patch for valgrind, but it seems that the patch fails >> to reach the mailing list on source forge. Attached is my original patch. >> I wonder if someone can send it for me. > > You could attach it to a bug in the valgrind bug tracker: > > <https://bugs.kde.org/enter_bug.cgi?product=valgrind> Bug created at https://bugs.kde.org/show_bug.cgi?id=492214 Cheers, Miao Wang > > Thanks, > Florian
On 21/08/24 13:14, Miao Wang via B4 Relay wrote: > From: Miao Wang <shankerwangmiao@gmail.com> > > Linux supports passing NULL instead of an empty string as the second > parameter when AT_EMPTY_PATH is set in the flags, starting from 6.11, > which brings a performance gain since it is much more efficient to > detect a NULL parameter than to detect an empty string in the kernel. > We utilize this feature if statx is used for fstat, when glibc is > compiled to target kernel versions afterwards, and dynamically probe > the kernel support of it, when targeting previous versions. > > Signed-off-by: Miao Wang <shankerwangmiao@gmail.com> > --- > Kernel 6.11 adds support for passing NULL to statx(fd, NULL, > AT_EMPTY_PATH), which improves the performance. This series utilize this > feature when statx is used to implement fstat, on some 32-bit platforms > and on loongarch with targeting kernel version below 6.10.6. > --- > Changes in v2: > - Separate this patch out from the series. > - Put the added __statx_empty_path() into internal-stat.h. > - Minor fixes according as suggested by Ruoyao. > - Link to v1: https://sourceware.org/pipermail/libc-alpha/2024-August/159333.html > --- > sysdeps/unix/sysv/linux/fstatat64.c | 8 ++++++-- > sysdeps/unix/sysv/linux/fxstat64.c | 3 +-- > sysdeps/unix/sysv/linux/internal-stat.h | 31 +++++++++++++++++++++++++++++++ > sysdeps/unix/sysv/linux/kernel-features.h | 5 +++++ > 4 files changed, 43 insertions(+), 4 deletions(-) > > diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c > index da496177c9..b67a5f4469 100644 > --- a/sysdeps/unix/sysv/linux/fstatat64.c > +++ b/sysdeps/unix/sysv/linux/fstatat64.c > @@ -47,8 +47,12 @@ fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf, > /* 32-bit kABI with default 64-bit time_t, e.g. arc, riscv32. Also > 64-bit time_t support is done through statx syscall. */ > struct statx tmp; > - int r = INTERNAL_SYSCALL_CALL (statx, fd, file, AT_NO_AUTOMOUNT | flag, > - STATX_BASIC_STATS, &tmp); > + flag |= AT_NO_AUTOMOUNT; > + int r; > + if ((flag & AT_EMPTY_PATH) && (file == NULL || *file == '\0')) > + r = __statx_empty_path (fd, flag, &tmp); > + else > + r = INTERNAL_SYSCALL_CALL (statx, fd, file, flag, STATX_BASIC_STATS, &tmp); > if (r != 0) > return r; It fails to build on arc-linux-gnuhf, with a missing '__statx_empty_path'. Add: diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c index 2ece683992..1578d55eb4 100644 --- a/sysdeps/unix/sysv/linux/fxstat64.c +++ b/sysdeps/unix/sysv/linux/fxstat64.c @@ -20,7 +20,7 @@ #include <sys/stat.h> #undef __fxstat #include <fcntl.h> -#include <kernel_stat.h> +#include <internal-stat.h> #include <sysdep.h> #include <xstatconv.h> #include <statx_cp.h> To fix it. > > diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c > index 230374cb22..2ece683992 100644 > --- a/sysdeps/unix/sysv/linux/fxstat64.c > +++ b/sysdeps/unix/sysv/linux/fxstat64.c > @@ -53,8 +53,7 @@ ___fxstat64 (int vers, int fd, struct stat64 *buf) > # else > /* New 32-bit kABIs with only 64-bit time_t support, e.g. arc, riscv32. */ > struct statx tmp; > - int r = INLINE_SYSCALL_CALL (statx, fd, "", AT_EMPTY_PATH, > - STATX_BASIC_STATS, &tmp); > + int r = __statx_empty_path (fd, 0, &tmp); > if (r == 0) > __cp_stat64_statx (buf, &tmp); > return r; > diff --git a/sysdeps/unix/sysv/linux/internal-stat.h b/sysdeps/unix/sysv/linux/internal-stat.h > index 9334059765..ee30cb1bd6 100644 > --- a/sysdeps/unix/sysv/linux/internal-stat.h > +++ b/sysdeps/unix/sysv/linux/internal-stat.h > @@ -29,3 +29,34 @@ > #else > # define FSTATAT_USE_STATX 0 > #endif > + > +#if FSTATAT_USE_STATX || XSTAT_IS_XSTAT64 > + > +static inline int > +__statx_empty_path (int fd, int flag, struct statx *buf) > +{ > + flag |= AT_EMPTY_PATH; > +#ifdef __ASSUME_STATX_NULL_PATH > + return INTERNAL_SYSCALL_CALL (statx, fd, NULL, flag, STATX_BASIC_STATS, buf); > +#else > + static int statx_null_path_supported = -1; > + int r; > + int supported = atomic_load_relaxed (&statx_null_path_supported); > + if (supported != 0) > + { > + r = INTERNAL_SYSCALL_CALL (statx, fd, NULL, flag, STATX_BASIC_STATS, buf); > + if (__glibc_likely (supported == 1)) > + return r; > + if (r != -EFAULT) > + { > + if (r == 0) > + atomic_store_relaxed (&statx_null_path_supported, 1); > + return r; > + } > + atomic_store_relaxed (&statx_null_path_supported, 0); > + } > + return INTERNAL_SYSCALL_CALL (statx, fd, "", flag, STATX_BASIC_STATS, buf); I don't think you need a tri-state here, you can assume that it is supported and set to unsupported once the syscall fails with EFAULT (similar to how we handle other fallbacks, like mips64 gendents64). Also, you are replacing a INLINE_SYSCALL_CALL, which sets errno. so you should follow the same semantic: flag |= AT_EMPTY_PATH; int r; #ifdef __ASSUME_STATX_NULL_PATH r = INTERNAL_SYSCALL_CALL (statx, fd, NULL, flag, STATX_BASIC_STATS, buf); #else static int statx_null_path_supported = 1; if (atomic_load_relaxed (&statx_null_path_supported)) { int r = INTERNAL_SYSCALL_CALL (statx, fd, NULL, flag, STATX_BASIC_STATS, buf); if (r == 0 || r != -EFAULT) goto out; atomic_store_relaxed (&statx_null_path_supported, 0); } r = INTERNAL_SYSCALL_CALL (statx, fd, "", flag, STATX_BASIC_STATS, buf); out: #endif return INTERNAL_SYSCALL_ERROR_P (r) ? INLINE_SYSCALL_ERROR_RETURN_VALUE (-r) : 0; > +#endif > +} > + > +#endif > diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h > index a25cf07e9f..78aaf43a82 100644 > --- a/sysdeps/unix/sysv/linux/kernel-features.h > +++ b/sysdeps/unix/sysv/linux/kernel-features.h > @@ -257,4 +257,9 @@ > # define __ASSUME_FCHMODAT2 0 > #endif > > +/* statx(fd, NULL, AT_EMPTY_PATH) was introduced in Linux 6.11. */ > +#if __LINUX_KERNEL_VERSION >= 0x060b00 > +# define __ASSUME_STATX_NULL_PATH 1 > +#endif > + > #endif /* kernel-features.h */ > > --- > base-commit: 2eee835eca960c9d4119279804214b7a1ed5d156 > change-id: 20240821-statx-null-path-531c0775bba4 > > Best regards,
> 2024年8月28日 02:18,Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> 写道: > > It fails to build on arc-linux-gnuhf, with a missing '__statx_empty_path'. Add: > > diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c > index 2ece683992..1578d55eb4 100644 > --- a/sysdeps/unix/sysv/linux/fxstat64.c > +++ b/sysdeps/unix/sysv/linux/fxstat64.c > @@ -20,7 +20,7 @@ > #include <sys/stat.h> > #undef __fxstat > #include <fcntl.h> > -#include <kernel_stat.h> > +#include <internal-stat.h> > #include <sysdep.h> > #include <xstatconv.h> > #include <statx_cp.h> > > To fix it. Many thanks for pointing it out, will be fixed in v3. > >> >> diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c >> index 230374cb22..2ece683992 100644 >> --- a/sysdeps/unix/sysv/linux/fxstat64.c >> +++ b/sysdeps/unix/sysv/linux/fxstat64.c >> @@ -53,8 +53,7 @@ ___fxstat64 (int vers, int fd, struct stat64 *buf) >> # else >> /* New 32-bit kABIs with only 64-bit time_t support, e.g. arc, riscv32. */ >> struct statx tmp; >> - int r = INLINE_SYSCALL_CALL (statx, fd, "", AT_EMPTY_PATH, >> - STATX_BASIC_STATS, &tmp); >> + int r = __statx_empty_path (fd, 0, &tmp); >> if (r == 0) >> __cp_stat64_statx (buf, &tmp); >> return r; >> diff --git a/sysdeps/unix/sysv/linux/internal-stat.h b/sysdeps/unix/sysv/linux/internal-stat.h >> index 9334059765..ee30cb1bd6 100644 >> --- a/sysdeps/unix/sysv/linux/internal-stat.h >> +++ b/sysdeps/unix/sysv/linux/internal-stat.h >> @@ -29,3 +29,34 @@ >> #else >> # define FSTATAT_USE_STATX 0 >> #endif >> + >> +#if FSTATAT_USE_STATX || XSTAT_IS_XSTAT64 >> + >> +static inline int >> +__statx_empty_path (int fd, int flag, struct statx *buf) >> +{ >> + flag |= AT_EMPTY_PATH; >> +#ifdef __ASSUME_STATX_NULL_PATH >> + return INTERNAL_SYSCALL_CALL (statx, fd, NULL, flag, STATX_BASIC_STATS, buf); >> +#else >> + static int statx_null_path_supported = -1; >> + int r; >> + int supported = atomic_load_relaxed (&statx_null_path_supported); >> + if (supported != 0) >> + { >> + r = INTERNAL_SYSCALL_CALL (statx, fd, NULL, flag, STATX_BASIC_STATS, buf); >> + if (__glibc_likely (supported == 1)) >> + return r; >> + if (r != -EFAULT) >> + { >> + if (r == 0) >> + atomic_store_relaxed (&statx_null_path_supported, 1); >> + return r; >> + } >> + atomic_store_relaxed (&statx_null_path_supported, 0); >> + } >> + return INTERNAL_SYSCALL_CALL (statx, fd, "", flag, STATX_BASIC_STATS, buf); > > I don't think you need a tri-state here, you can assume that it is supported > and set to unsupported once the syscall fails with EFAULT (similar to how we > handle other fallbacks, like mips64 gendents64). Tri-state here is needed to prevent generating data barrier instructions after whether it is supported is finally decided. Will improve this in v3. > > Also, you are replacing a INLINE_SYSCALL_CALL, which sets errno. so you should > follow the same semantic: > > > flag |= AT_EMPTY_PATH; > int r; > #ifdef __ASSUME_STATX_NULL_PATH > r = INTERNAL_SYSCALL_CALL (statx, fd, NULL, flag, STATX_BASIC_STATS, buf); > #else > static int statx_null_path_supported = 1; > if (atomic_load_relaxed (&statx_null_path_supported)) > { > int r = INTERNAL_SYSCALL_CALL (statx, fd, NULL, flag, STATX_BASIC_STATS, buf); > if (r == 0 || r != -EFAULT) > goto out; > atomic_store_relaxed (&statx_null_path_supported, 0); > } > r = INTERNAL_SYSCALL_CALL (statx, fd, "", flag, STATX_BASIC_STATS, buf); > out: > #endif > return INTERNAL_SYSCALL_ERROR_P (r) > ? INLINE_SYSCALL_ERROR_RETURN_VALUE (-r) > : 0; > This will be fixed in fxstat64.c in v3, since the replaced statement is INTERNAL_SYSCALL_CALL in fstatat64.c Cheers, Miao Wang
diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c index da496177c9..b67a5f4469 100644 --- a/sysdeps/unix/sysv/linux/fstatat64.c +++ b/sysdeps/unix/sysv/linux/fstatat64.c @@ -47,8 +47,12 @@ fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf, /* 32-bit kABI with default 64-bit time_t, e.g. arc, riscv32. Also 64-bit time_t support is done through statx syscall. */ struct statx tmp; - int r = INTERNAL_SYSCALL_CALL (statx, fd, file, AT_NO_AUTOMOUNT | flag, - STATX_BASIC_STATS, &tmp); + flag |= AT_NO_AUTOMOUNT; + int r; + if ((flag & AT_EMPTY_PATH) && (file == NULL || *file == '\0')) + r = __statx_empty_path (fd, flag, &tmp); + else + r = INTERNAL_SYSCALL_CALL (statx, fd, file, flag, STATX_BASIC_STATS, &tmp); if (r != 0) return r; diff --git a/sysdeps/unix/sysv/linux/fxstat64.c b/sysdeps/unix/sysv/linux/fxstat64.c index 230374cb22..2ece683992 100644 --- a/sysdeps/unix/sysv/linux/fxstat64.c +++ b/sysdeps/unix/sysv/linux/fxstat64.c @@ -53,8 +53,7 @@ ___fxstat64 (int vers, int fd, struct stat64 *buf) # else /* New 32-bit kABIs with only 64-bit time_t support, e.g. arc, riscv32. */ struct statx tmp; - int r = INLINE_SYSCALL_CALL (statx, fd, "", AT_EMPTY_PATH, - STATX_BASIC_STATS, &tmp); + int r = __statx_empty_path (fd, 0, &tmp); if (r == 0) __cp_stat64_statx (buf, &tmp); return r; diff --git a/sysdeps/unix/sysv/linux/internal-stat.h b/sysdeps/unix/sysv/linux/internal-stat.h index 9334059765..ee30cb1bd6 100644 --- a/sysdeps/unix/sysv/linux/internal-stat.h +++ b/sysdeps/unix/sysv/linux/internal-stat.h @@ -29,3 +29,34 @@ #else # define FSTATAT_USE_STATX 0 #endif + +#if FSTATAT_USE_STATX || XSTAT_IS_XSTAT64 + +static inline int +__statx_empty_path (int fd, int flag, struct statx *buf) +{ + flag |= AT_EMPTY_PATH; +#ifdef __ASSUME_STATX_NULL_PATH + return INTERNAL_SYSCALL_CALL (statx, fd, NULL, flag, STATX_BASIC_STATS, buf); +#else + static int statx_null_path_supported = -1; + int r; + int supported = atomic_load_relaxed (&statx_null_path_supported); + if (supported != 0) + { + r = INTERNAL_SYSCALL_CALL (statx, fd, NULL, flag, STATX_BASIC_STATS, buf); + if (__glibc_likely (supported == 1)) + return r; + if (r != -EFAULT) + { + if (r == 0) + atomic_store_relaxed (&statx_null_path_supported, 1); + return r; + } + atomic_store_relaxed (&statx_null_path_supported, 0); + } + return INTERNAL_SYSCALL_CALL (statx, fd, "", flag, STATX_BASIC_STATS, buf); +#endif +} + +#endif diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h index a25cf07e9f..78aaf43a82 100644 --- a/sysdeps/unix/sysv/linux/kernel-features.h +++ b/sysdeps/unix/sysv/linux/kernel-features.h @@ -257,4 +257,9 @@ # define __ASSUME_FCHMODAT2 0 #endif +/* statx(fd, NULL, AT_EMPTY_PATH) was introduced in Linux 6.11. */ +#if __LINUX_KERNEL_VERSION >= 0x060b00 +# define __ASSUME_STATX_NULL_PATH 1 +#endif + #endif /* kernel-features.h */