On Sun, Nov 3, 2013 at 11:18 PM, Chung-Lin Tang wrote: > 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. Yes I ran into this same issue when I was working on ILP32 for AARCH64. Attached is the patch which I used. Thanks, Andrew Pinski > > 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;