This is the mail archive of the
libc-ports@sources.redhat.com
mailing list for the libc-ports project.
struct statfs/statfs64 in linux-generic
- From: Chung-Lin Tang <cltang at codesourcery dot com>
- To: "libc-ports at sourceware dot org" <libc-ports at sourceware dot org>
- Cc: Chris Metcalf <cmetcalf at tilera dot com>
- Date: Mon, 4 Nov 2013 15:18:07 +0800
- Subject: struct statfs/statfs64 in linux-generic
- Authentication-results: sourceware.org; auth=none
Hi,
I'm currently working on the glibc port for Altera Nios II, and per the
kernel upstreaming requirements, we're making it a user of linux-generic
in glibc.
I've come across an issue about struct statfs/statfs64, where I've
listed the struct definitions in both glibc and the kernel below.
In linux-generic, both struct statfs/statfs64 has some fields as 64-bit
words, padded properly if need on 32-bit targets. Effectively, they have
to be same-format, to pass to the statfs64 syscall uniformly.
__SWORD_TYPE appears to be int/long on 32/64-bit targets. This means
that for 32-bit targets, struct statfs[64] will be made of 32-bit words,
with a few 64-bit fields embedded in the middle.
In the kernel however, the fields of importance in struct statfs is made
up of entirely '__statfs_word', defined to be 64-bit or 32-bit depending
on target (putting aside signedness for now).
Notice how that, while this does work for 64-bit targets, 32-bit targets
cannot properly define a compatible struct statfs[64], at least not with
simple typedefs.
Chris, as you seem the original developer/maintainer of linux-generic
and the tile ports (as I observed from the mail archives), I'm curious
if you saw any similar problems with tilegx -m32? The only users of
linux-generic appears to be only aarch64 and tile, and nios2 will be
another 32-bit user.
The exact FAIL I saw was posix/tst-getconf, which I traced to a failed
statfs64 call in pathconf(), due to a failed sizeof(struct statfs64)
check inside the kernel syscall code.
Thanks,
Chung-Lin
In glibc, ports/sysdeps/unix/sysv/linux/generic/bits/statfs.h:
struct statfs
{
__SWORD_TYPE f_type;
__SWORD_TYPE f_bsize;
__field64(__fsblkcnt_t, __fsblkcnt64_t, f_blocks);
__field64(__fsblkcnt_t, __fsblkcnt64_t, f_bfree);
__field64(__fsblkcnt_t, __fsblkcnt64_t, f_bavail);
__field64(__fsfilcnt_t, __fsfilcnt64_t, f_files);
__field64(__fsfilcnt_t, __fsfilcnt64_t, f_ffree);
__fsid_t f_fsid;
__SWORD_TYPE f_namelen;
__SWORD_TYPE f_frsize;
__SWORD_TYPE f_flags;
__SWORD_TYPE f_spare[4];
} __attribute__((__aligned__(8)));
#ifdef __USE_LARGEFILE64
struct statfs64
{
__SWORD_TYPE f_type;
__SWORD_TYPE f_bsize;
__fsblkcnt64_t f_blocks;
__fsblkcnt64_t f_bfree;
__fsblkcnt64_t f_bavail;
__fsfilcnt64_t f_files;
__fsfilcnt64_t f_ffree;
__fsid_t f_fsid;
__SWORD_TYPE f_namelen;
__SWORD_TYPE f_frsize;
__SWORD_TYPE f_flags;
__SWORD_TYPE f_spare[4];
} __attribute__((__aligned__(8)));
#endif
In Linux kernel, include/uapi/asm-generic/statfs.h:
#ifndef __statfs_word
#if __BITS_PER_LONG == 64
#define __statfs_word long
#else
#define __statfs_word __u32
#endif
#endif
struct statfs {
__statfs_word f_type;
__statfs_word f_bsize;
__statfs_word f_blocks;
__statfs_word f_bfree;
__statfs_word f_bavail;
__statfs_word f_files;
__statfs_word f_ffree;
__kernel_fsid_t f_fsid;
__statfs_word f_namelen;
__statfs_word f_frsize;
__statfs_word f_flags;
__statfs_word f_spare[4];
};
#ifndef ARCH_PACK_STATFS64
#define ARCH_PACK_STATFS64
#endif
struct statfs64 {
__statfs_word f_type;
__statfs_word f_bsize;
__u64 f_blocks;
__u64 f_bfree;
__u64 f_bavail;
__u64 f_files;
__u64 f_ffree;
__kernel_fsid_t f_fsid;
__statfs_word f_namelen;
__statfs_word f_frsize;
__statfs_word f_flags;
__statfs_word f_spare[4];
} ARCH_PACK_STATFS64;