Skip to content

tests/zfs-tests/cmd/statx.c: avoid statx() conflicts#18345

Open
jolivain wants to merge 1 commit intoopenzfs:masterfrom
jolivain:avoid_statx_conflicts
Open

tests/zfs-tests/cmd/statx.c: avoid statx() conflicts#18345
jolivain wants to merge 1 commit intoopenzfs:masterfrom
jolivain:avoid_statx_conflicts

Conversation

@jolivain
Copy link

With some libc, such as uclibc >= 1.0.57, the libc defines the statx() function, while also internally including <sys/stat.h> (from <fcntl.h> for example), the compilation results to an error due to conflicting types, with the message:

tests/zfs-tests/cmd/statx.c:58:1: error: conflicting types for 'statx'; have 'int(int,  const char *, int,  unsigned int,  void *)'
   58 | statx(int, const char *, int, unsigned int, void *)
      | ^~~~~
In file included from /TestZfsUclibc/host/aarch64-buildroot-linux-uclibc/sysroot/usr/include/sys/stat.h:381,
                 from ./lib/libspl/include/os/linux/sys/stat.h:30,
                 from /TestZfsUclibc/host/aarch64-buildroot-linux-uclibc/sysroot/usr/include/fcntl.h:37,
                 from tests/zfs-tests/cmd/statx.c:29:
/TestZfsUclibc/host/aarch64-buildroot-linux-uclibc/sysroot/usr/include/bits/statx.h:88:5: note: previous declaration of 'statx' with type 'int(int,  const char * restrict,  int,  unsigned int,  struct statx * restrict)'
   88 | int statx (int __dirfd, const char *__restrict __path, int __flags,
      |     ^~~~~

This is because the zfs statx test inconditionally defines a statx() function with a slightly different prototype [1], compared to Glibc [2] and uClibc [3].

The error does not happen with Glibc because its <fcntl.h> header does not include <sys/stat.h> and the zfs-tests/cmd/statx.c does not include <sys/stat.h> either. So the conflict does not happen.

This commit fixes the issue by only defining the statx() prototype only if the libc was detected not to have a working statx() wrapper, and explicitly include the <sys/stat.h> otherwise.

Note: the issue was found in Linux Buildroot [4], while updating uclibc-ng to version 1.0.57. See: [5] [6]. The issue was also reported in [7].

[1] https://github.com/openzfs/zfs/blob/zfs-2.4.1/tests/zfs-tests/cmd/statx.c#L58
[2] https://sourceware.org/git/?p=glibc.git;a=blob;f=io/bits/statx-generic.h;h=9bb9701dc67eccad968b338aeb15d87378fe65cd;hb=ea37298b65bd67f94c3c2640e91ec5865a5019ad#l66
[3] https://github.com/wbx-github/uclibc-ng/blob/v1.0.57/libc/sysdeps/linux/common/bits/statx.h#L88
[4] https://buildroot.org/
[5] https://lore.kernel.org/buildroot/054ee3804bf26bee3dadf8425e0f723c@free.fr/
[6] https://gitlab.com/jolivain/buildroot/-/jobs/13308829775#L237
[7] #18316

Types of changes

  • Bug fix (non-breaking change which fixes an issue)

Checklist:

With some libc, such as uclibc >= 1.0.57, the libc defines the statx()
function, while also internally including <sys/stat.h> (from <fcntl.h>
for example), the compilation results to an error due to conflicting
types, with the message:

    tests/zfs-tests/cmd/statx.c:58:1: error: conflicting types for 'statx'; have 'int(int,  const char *, int,  unsigned int,  void *)'
       58 | statx(int, const char *, int, unsigned int, void *)
          | ^~~~~
    In file included from /TestZfsUclibc/host/aarch64-buildroot-linux-uclibc/sysroot/usr/include/sys/stat.h:381,
                     from ./lib/libspl/include/os/linux/sys/stat.h:30,
                     from /TestZfsUclibc/host/aarch64-buildroot-linux-uclibc/sysroot/usr/include/fcntl.h:37,
                     from tests/zfs-tests/cmd/statx.c:29:
    /TestZfsUclibc/host/aarch64-buildroot-linux-uclibc/sysroot/usr/include/bits/statx.h:88:5: note: previous declaration of 'statx' with type 'int(int,  const char * restrict,  int,  unsigned int,  struct statx * restrict)'
       88 | int statx (int __dirfd, const char *__restrict __path, int __flags,
          |     ^~~~~

This is because the zfs statx test inconditionally defines a statx()
function with a slightly different prototype [1], compared to Glibc [2]
and uClibc [3].

The error does not happen with Glibc because its <fcntl.h> header does
not include <sys/stat.h> and the zfs-tests/cmd/statx.c does not include
<sys/stat.h> either. So the conflict does not happen.

This commit fixes the issue by only defining the statx() prototype only
if the libc was detected not to have a working statx() wrapper, and
explicitly include the <sys/stat.h> otherwise.

Note: the issue was found in Linux Buildroot [4], while updating
uclibc-ng to version 1.0.57. See: [5] [6]. The issue was also
reported in [7].

[1] https://github.com/openzfs/zfs/blob/zfs-2.4.1/tests/zfs-tests/cmd/statx.c#L58
[2] https://sourceware.org/git/?p=glibc.git;a=blob;f=io/bits/statx-generic.h;h=9bb9701dc67eccad968b338aeb15d87378fe65cd;hb=ea37298b65bd67f94c3c2640e91ec5865a5019ad#l66
[3] https://github.com/wbx-github/uclibc-ng/blob/v1.0.57/libc/sysdeps/linux/common/bits/statx.h#L88
[4] https://buildroot.org/
[5] https://lore.kernel.org/buildroot/054ee3804bf26bee3dadf8425e0f723c@free.fr/
[6] https://gitlab.com/jolivain/buildroot/-/jobs/13308829775#L237
[7] openzfs#18316

Signed-off-by: Julien Olivain <ju.o@free.fr>
static inline int
_statx(int fd, const char *path, int flags, unsigned int mask, void *stx)
{
if (statx)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding the HAVE_STATX guards here as well seems like the cleanest way to resolve the compiler warning.

  tests/zfs-tests/cmd/statx.c: In function '_statx':
  tests/zfs-tests/cmd/statx.c:69:6: error: the address of 'statx' will always evaluate as 'true' [-Werror=address]
    if (statx)
        ^~~~~
  cc1: all warnings being treated as errors

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants