linux: Consolidate fstatfs implementations

The __NR_fstatfs64 syscall is supported on all architectures but
aarch64, mips64, riscv64, and x86_64.  And newer ABIs also uses
the new fstatfs64 interface (where the struct size is used as
first argument).

So the default implementation now uses:

  1. __NR_fstatfs64 for non-LFS call and handle overflow directly
     There is no need to handle __NR_fstatfs since all architectures
     that only support are LFS only.

  2. __NR_fstatfs if defined or __NR_fstatfs64 otherwise for LFS
     call.

Alpha is the only outlier, it is a 64-bit architecture which
provides non-LFS interface and only provides __NR_fstatfs64 on
newer kernels (5.1+).

Checked on x86_64-linux-gnu.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
This commit is contained in:
Adhemerval Zanella 2021-02-05 20:13:58 +00:00
parent e7702cb56e
commit 1bfbaf7130
10 changed files with 129 additions and 77 deletions

View File

@ -6,12 +6,11 @@
/* Now define the internal interfaces. */ /* Now define the internal interfaces. */
extern int __statfs (const char *__file, struct statfs *__buf); extern int __statfs (const char *__file, struct statfs *__buf);
libc_hidden_proto (__statfs) libc_hidden_proto (__statfs)
extern int __fstatfs (int __fildes, struct statfs *__buf) extern int __fstatfs (int __fildes, struct statfs *__buf);
attribute_hidden; libc_hidden_proto (__fstatfs)
extern int __statfs64 (const char *__file, struct statfs64 *__buf) extern int __statfs64 (const char *__file, struct statfs64 *__buf)
attribute_hidden; attribute_hidden;
extern int __fstatfs64 (int __fildes, struct statfs64 *__buf) extern int __fstatfs64 (int __fildes, struct statfs64 *__buf);
attribute_hidden;
# endif /* !_ISOMAC */ # endif /* !_ISOMAC */
#endif #endif

View File

@ -1,6 +1,6 @@
/* Copyright (C) 2011-2021 Free Software Foundation, Inc. /* Get filesystem statistics. Linux/alpha.
Copyright (C) 2011-2021 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -18,18 +18,13 @@
#include <sys/statfs.h> #include <sys/statfs.h>
#include <kernel_stat.h> #include <kernel_stat.h>
#include <stddef.h>
#include <sysdep.h> #include <sysdep.h>
#if !STATFS_IS_STATFS64
#include "overflow.h"
/* Return information about the filesystem on which FD resides. */ /* Return information about the filesystem on which FD resides. */
int int
__fstatfs (int fd, struct statfs *buf) __fstatfs (int fd, struct statfs *buf)
{ {
int rc = INLINE_SYSCALL (fstatfs64, 3, fd, sizeof (*buf), buf); return INLINE_SYSCALL_CALL (fstatfs, fd, buf);
return rc ?: statfs_overflow (buf);
} }
libc_hidden_def (__fstatfs)
weak_alias (__fstatfs, fstatfs) weak_alias (__fstatfs, fstatfs)
#endif

View File

@ -1 +1,51 @@
#include <sysdeps/unix/sysv/linux/fstatfs64.c> /* Get filesystem statistics. Linux/alpha.
Copyright (C) 1996-2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <sys/statfs.h>
#include <sysdep.h>
#include <kernel_stat.h>
/* Return information about the filesystem on which FILE resides. */
int
__fstatfs64 (int fd, struct statfs64 *buf)
{
int r = INLINE_SYSCALL_CALL (fstatfs64, fd, sizeof (*buf), buf);
#if __ASSUME_STATFS64 == 0
if (r == -1 && errno == ENOSYS)
{
struct statfs buf32;
if (__fstatfs (fd, &buf32) < 0)
return -1;
buf->f_type = buf32.f_type;
buf->f_bsize = buf32.f_bsize;
buf->f_blocks = buf32.f_blocks;
buf->f_bfree = buf32.f_bfree;
buf->f_bavail = buf32.f_bavail;
buf->f_files = buf32.f_files;
buf->f_ffree = buf32.f_ffree;
buf->f_fsid = buf32.f_fsid;
buf->f_namelen = buf32.f_namelen;
buf->f_frsize = buf32.f_frsize;
buf->f_flags = buf32.f_flags;
memcpy (buf->f_spare, buf32.f_spare, sizeof (buf32.f_spare));
}
#endif
return r;
}
weak_alias (__fstatfs64, fstatfs64)

View File

@ -29,5 +29,4 @@ utimes - utimes i:sp __utimes utimes@@GLIBC_2.1
getrusage - getrusage i:ip __getrusage getrusage@@GLIBC_2.1 getrusage - getrusage i:ip __getrusage getrusage@@GLIBC_2.1
# avoid 64-bit aliases on 32-bit statfs syscalls # avoid 64-bit aliases on 32-bit statfs syscalls
fstatfs - fstatfs i:ip __fstatfs fstatfs
statfs - statfs i:sp __statfs statfs statfs - statfs i:sp __statfs statfs

View File

@ -0,0 +1,62 @@
/* Get filesystem statistics. Linux version.
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#include <sys/statfs.h>
#include <time.h>
#include <sysdep.h>
#include <kernel_stat.h>
#if !STATFS_IS_STATFS64
/* Return information about the filesystem on which FILE resides. */
int
__fstatfs (int fd, struct statfs *buf)
{
struct statfs64 buf64;
int rc = INLINE_SYSCALL_CALL (fstatfs64, fd, sizeof (buf64), &buf64);
if (rc != 0)
return rc;
buf->f_type = buf64.f_type;
buf->f_bsize = buf64.f_bsize;
buf->f_blocks = buf64.f_blocks;
buf->f_bfree = buf64.f_bfree;
buf->f_bavail = buf64.f_bavail;
buf->f_files = buf64.f_files;
buf->f_ffree = buf64.f_ffree;
buf->f_fsid = buf64.f_fsid;
buf->f_namelen = buf64.f_namelen;
buf->f_frsize = buf64.f_frsize;
buf->f_flags = buf64.f_flags;
memcpy (buf->f_spare, buf64.f_spare, sizeof (buf64.f_spare));
if ((fsblkcnt_t) buf64.f_blocks != buf64.f_blocks
|| (fsblkcnt_t) buf64.f_bfree != buf64.f_bfree
|| (fsblkcnt_t) buf64.f_bavail != buf64.f_bavail
|| (fsblkcnt_t) buf64.f_files != buf64.f_files
|| (fsblkcnt_t) buf64.f_ffree != buf64.f_ffree)
{
__set_errno (EOVERFLOW);
return -1;
}
return 0;
}
libc_hidden_def (__fstatfs)
weak_alias (__fstatfs, fstatfs)
#endif

View File

@ -16,77 +16,28 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */ <https://www.gnu.org/licenses/>. */
#include <errno.h> #define __fstatfs __fstatfs_disable
#include <string.h> #define fstatfs fstatfs_disable
#include <stddef.h> #include <sys/statfs.h>
#include <sysdep.h> #include <sysdep.h>
#include <kernel_stat.h> #include <kernel_stat.h>
#undef __fstatfs
/* Hide the prototypes for __fstatfs and fstatfs so that GCC will not #undef fstatfs
complain about the different function signatures if they are aliased
to __fstat64. If STATFS_IS_STATFS64 is not zero then the statfs and
statfs64 structures have an identical layout but different type names. */
#if STATFS_IS_STATFS64
# define __fstatfs __fstatfs_disable
# define fstatfs fstatfs_disable
#endif
#include <sys/statfs.h>
#include <kernel-features.h>
/* Defined in statfs64.c. */
extern int __no_statfs64 attribute_hidden;
/* Return information about the filesystem on which FD resides. */ /* Return information about the filesystem on which FD resides. */
int int
__fstatfs64 (int fd, struct statfs64 *buf) __fstatfs64 (int fd, struct statfs64 *buf)
{ {
#ifdef __NR_fstatfs64 #ifdef __NR_fstatfs64
# if __ASSUME_STATFS64 == 0 return INLINE_SYSCALL_CALL (fstatfs64, fd, sizeof (*buf), buf);
if (! __no_statfs64) #else
# endif return INLINE_SYSCALL_CALL (fstatfs, fd, buf);
{
int result = INLINE_SYSCALL (fstatfs64, 3, fd, sizeof (*buf), buf);
# if __ASSUME_STATFS64 == 0
if (result == 0 || errno != ENOSYS)
# endif
return result;
# if __ASSUME_STATFS64 == 0
__no_statfs64 = 1;
# endif
}
#endif
#if __ASSUME_STATFS64 == 0
struct statfs buf32;
if (__fstatfs (fd, &buf32) < 0)
return -1;
buf->f_type = buf32.f_type;
buf->f_bsize = buf32.f_bsize;
buf->f_blocks = buf32.f_blocks;
buf->f_bfree = buf32.f_bfree;
buf->f_bavail = buf32.f_bavail;
buf->f_files = buf32.f_files;
buf->f_ffree = buf32.f_ffree;
buf->f_fsid = buf32.f_fsid;
buf->f_namelen = buf32.f_namelen;
buf->f_frsize = buf32.f_frsize;
memcpy (buf->f_spare, buf32.f_spare, sizeof (buf32.f_spare));
return 0;
#endif #endif
} }
weak_alias (__fstatfs64, fstatfs64) weak_alias (__fstatfs64, fstatfs64)
#undef __fstatfs
#undef fstatfs
#if STATFS_IS_STATFS64 #if STATFS_IS_STATFS64
weak_alias (__fstatfs64, __fstatfs) weak_alias (__fstatfs64, __fstatfs)
weak_alias (__fstatfs64, fstatfs) weak_alias (__fstatfs64, fstatfs)
libc_hidden_ver (__fstatfs64, __fstatfs)
#endif #endif

View File

@ -1 +0,0 @@
/* Empty. */

View File

@ -4,7 +4,6 @@ prlimit EXTRA prlimit64 i:iipp prlimit prlimit64
fanotify_mark EXTRA fanotify_mark i:iiiis fanotify_mark fanotify_mark EXTRA fanotify_mark i:iiiis fanotify_mark
fstatfs - fstatfs i:ip __fstatfs fstatfs fstatfs64 __fstatfs64
statfs - statfs i:sp __statfs statfs statfs64 __statfs64 statfs - statfs i:sp __statfs statfs statfs64 __statfs64
sendfile - sendfile i:iipi sendfile sendfile64 sendfile - sendfile i:iipi sendfile sendfile64

View File

@ -1 +0,0 @@
/* fstatfs64 is the same as fstatfs. */

View File

@ -1,6 +1,5 @@
# File name Caller Syscall name # args Strong name Weak names # File name Caller Syscall name # args Strong name Weak names
fstatfs - fstatfs i:ip __fstatfs fstatfs fstatfs64 __fstatfs64
statfs - statfs i:sp __statfs statfs statfs64 statfs - statfs i:sp __statfs statfs statfs64
sendfile - sendfile i:iipi sendfile sendfile64 sendfile - sendfile i:iipi sendfile sendfile64
prlimit EXTRA prlimit64 i:iipp prlimit prlimit64 prlimit EXTRA prlimit64 i:iipp prlimit prlimit64