我的服务器上安装了Red Hat Enterprise Linux Server 6.6(2.6.32-504.el6.x86_64),并且具有以下分区层次结构。
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 7.9G 1.7G 5.9G 22% /
tmpfs 5.4G 8.0K 5.4G 1% /dev/shm
/dev/sda8 53G 1.4G 49G 3% /mysql/data
/dev/sda6 7.9G 4.5G 3.1G 60% /usr/BWhttpd
/dev/sda4 32G 989M 29G 4% /var
/dev/sdb1 25T 37M 25T 1% /media1
/dev/sdc1 25T 37M 25T 1% /media2
/dev/sdd1 25T 37M 25T 1% /media3
/dev/sde1 22T 21T 1.1T 95% /media4
我在每个
上发出statvfs
来电
/ mediax
分区,但系统调用失败,错误为Value too large for defined data type
。
我能够找到系统调用返回错误EOVERFLOW
,但不确定struct statvfs
的哪个成员导致此错误。
是否必须对/ mediax分区的大小做任何事情。
注意:分区是xfs文件系统类型。
答案 0 :(得分:3)
如man 2 statfs
手册页中所述:
原始Linux statfs()和fstatfs()系统调用的设计并未考虑到极大的文件大小。随后,Linux 2.6添加了使用新结构statfs64的新statfs64()和fstatfs64()系统调用。新结构包含与原始statfs结构相同的字段,但增加了各种字段的大小,以适应大文件大小。 glibc statfs()和fstatfs()包装函数透明地处理内核差异。
在您的情况下,出于某种原因,您使用的是非64位版本的系统调用。
Linux内核使用四种不同的系统调用(以及可选的兼容版本)实现fstat*fs*()
和stat*fs*()
库调用:fstatfs()
,fstatfs64()
,statfs()
和statfs64()
。所有四个都在内核源代码的fs/statfs.c
中定义,并使用内核内部函数vfs_statfs()
将必要的信息收集到struct kstatfs
结构中。
statfs()
和fstatfs()
都使用内核函数do_statfs_native()
(在fs/statfs.c
中)将字段从struct kstatfs
复制到用户空间{{ 1}}缓冲区。问题是,许多内核结构字段大于用户空间缓冲区中的字段。 struct statfs
验证值是否合适,否则将返回do_statfs_native()
。
这是我能找到的唯一可能导致四个系统调用中的任何一个返回-EOVERFLOW
的情况。
对于-EOVERFLOW
和statfs64()
,内核函数fstatfs64()
用于将字段从内核do_statfs64()
复制到用户空间struct kstatfs
缓冲区。用户空间缓冲区字段至少与内核结构字段一样大,因此不存在溢出的风险。 (该函数永远不会返回struct statfs64
。)
修复是为了确保您使用64位版本的-EOVERFLOW
以及相应的系统调用。
为确保glibc使用正确的版本(能够正确描述非常大的文件系统的版本),请确保
struct statfs
在任何#define _FILE_OFFSET_BITS 64
之前;或者,将#include
添加到编译器标志中。
所有这一切都确保glibc知道你在Linux 2.6或更高版本的内核(3.x,4.x等)上运行,并且它肯定应该尝试使用结构的版本适当大小的字段。
或者,您可以定义-D_FILE_OFFSET_BITS=64
,以在系统调用周围公开_LARGEFILE64_SOURCE
和struct statfs64
类型以及相应的struct statvfs64
和statfs64()
包装。这可以避免让glibc做任何猜测,并确保您使用可以正确描述所有Linux文件系统大小的系统调用版本。
这两个选项都适用于所有Linux体系结构,32位和64位。
答案 1 :(得分:1)
不是完整的答案,但关于内核代码(v4.9,我目前没有内核代码,但我怀疑这部分已经发生了很大的变化),你应该搜索一个值> 0xffffffff
用于以下参数之一:f_blocks
,f_bfree
,f_bavail
,f_bsize
,f_frsize
,f_files
或{{ 1}},即除f_files
,f_fsid
和f_flag
以外的任何参数:
f_namemax