statvfs 系统调用失败,错误值对于定义的数据类型来说太大
statvfs system call fails with error Value too large for defined data type
我的服务器上安装了 Red Hat Enterprise Linux 服务器版本 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 分区的大小有关。
Note: Partitions are of xfs file system type.
不是一个完整的答案,但是关于内核代码(v4.9,我目前没有你内核的代码,但我怀疑这部分有很大的变化),你应该搜索一个值> 0xffffffff
对于以下参数之一:f_blocks
、f_bfree
、f_bavail
、f_bsize
、f_frsize
、f_files
或 f_files
,即除 f_fsid
、f_flag
和 f_namemax
:
之外的任何参数
if (sizeof buf->f_blocks == 4) {
if ((st.f_blocks | st.f_bfree | st.f_bavail |
st.f_bsize | st.f_frsize) &
0xffffffff00000000ULL)
return -EOVERFLOW;
/*
* f_files and f_ffree may be -1; it's okay to stuff
* that into 32 bits
*/
if (st.f_files != -1 &&
(st.f_files & 0xffffffff00000000ULL))
return -EOVERFLOW;
if (st.f_ffree != -1 &&
(st.f_ffree & 0xffffffff00000000ULL))
return -EOVERFLOW;
}
如 man 2 statfs
手册页所述:
The original Linux statfs() and fstatfs() system calls were not designed with extremely large file sizes in mind. Subsequently, Linux 2.6 added new statfs64() and fstatfs64() system calls that employ a new structure, statfs64. The new structure contains the same fields as the original statfs structure, but the sizes of various fields are increased, to accommodate large file sizes. The glibc statfs() and fstatfs() wrapper functions transparently deal with the kernel differences.
在您的情况下,您出于某种原因正在使用非 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
复制到用户空间struct statfs
缓冲区。问题是,许多内核结构字段比用户空间缓冲区中的字段大。 do_statfs_native()
验证值是否合适,如果不合适,将 return -EOVERFLOW
否则。
这是我能找到的唯一一种可能导致对 return -EOVERFLOW
.
的四个系统调用中的任何一个的情况
对于statfs64()
和fstatfs64()
,内核函数do_statfs64()
用于将字段从内核内部struct kstatfs
复制到用户空间struct statfs64
缓冲区.用户空间缓冲区字段至少与内核结构字段一样大,因此不存在溢出风险。 (函数从不 returns -EOVERFLOW
。)
修复是为了确保您使用 64 位版本的 struct statfs
和相应的系统调用。
为确保 glibc 使用结构的正确版本(可以正确描述非常大的文件系统的版本),请确保您有
#define _FILE_OFFSET_BITS 64
在任何 #include
之前;或者,将 -D_FILE_OFFSET_BITS=64
添加到您的编译器标志中。
所有这一切都是为了确保 glibc 知道您在 Linux 2.6 或更高版本的内核(3.x、4.x 等)上 运行 ,并且它绝对应该尝试使用具有适当大小字段的结构版本。
或者,您可以定义 _LARGEFILE64_SOURCE
,以公开 struct statfs64
和 struct statvfs64
类型以及相应的 statfs64()
和 statvfs64()
系统调用包装器。这避免让 glibc 做任何猜测,并确保您使用可以正确描述所有 Linux 文件系统大小的系统调用版本。
这两个选项都适用于所有 Linux 架构,32 位和 64 位。
我的服务器上安装了 Red Hat Enterprise Linux 服务器版本 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 分区的大小有关。
Note: Partitions are of xfs file system type.
不是一个完整的答案,但是关于内核代码(v4.9,我目前没有你内核的代码,但我怀疑这部分有很大的变化),你应该搜索一个值> 0xffffffff
对于以下参数之一:f_blocks
、f_bfree
、f_bavail
、f_bsize
、f_frsize
、f_files
或 f_files
,即除 f_fsid
、f_flag
和 f_namemax
:
if (sizeof buf->f_blocks == 4) {
if ((st.f_blocks | st.f_bfree | st.f_bavail |
st.f_bsize | st.f_frsize) &
0xffffffff00000000ULL)
return -EOVERFLOW;
/*
* f_files and f_ffree may be -1; it's okay to stuff
* that into 32 bits
*/
if (st.f_files != -1 &&
(st.f_files & 0xffffffff00000000ULL))
return -EOVERFLOW;
if (st.f_ffree != -1 &&
(st.f_ffree & 0xffffffff00000000ULL))
return -EOVERFLOW;
}
如 man 2 statfs
手册页所述:
The original Linux statfs() and fstatfs() system calls were not designed with extremely large file sizes in mind. Subsequently, Linux 2.6 added new statfs64() and fstatfs64() system calls that employ a new structure, statfs64. The new structure contains the same fields as the original statfs structure, but the sizes of various fields are increased, to accommodate large file sizes. The glibc statfs() and fstatfs() wrapper functions transparently deal with the kernel differences.
在您的情况下,您出于某种原因正在使用非 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
复制到用户空间struct statfs
缓冲区。问题是,许多内核结构字段比用户空间缓冲区中的字段大。 do_statfs_native()
验证值是否合适,如果不合适,将 return -EOVERFLOW
否则。
这是我能找到的唯一一种可能导致对 return -EOVERFLOW
.
对于statfs64()
和fstatfs64()
,内核函数do_statfs64()
用于将字段从内核内部struct kstatfs
复制到用户空间struct statfs64
缓冲区.用户空间缓冲区字段至少与内核结构字段一样大,因此不存在溢出风险。 (函数从不 returns -EOVERFLOW
。)
修复是为了确保您使用 64 位版本的 struct statfs
和相应的系统调用。
为确保 glibc 使用结构的正确版本(可以正确描述非常大的文件系统的版本),请确保您有
#define _FILE_OFFSET_BITS 64
在任何 #include
之前;或者,将 -D_FILE_OFFSET_BITS=64
添加到您的编译器标志中。
所有这一切都是为了确保 glibc 知道您在 Linux 2.6 或更高版本的内核(3.x、4.x 等)上 运行 ,并且它绝对应该尝试使用具有适当大小字段的结构版本。
或者,您可以定义 _LARGEFILE64_SOURCE
,以公开 struct statfs64
和 struct statvfs64
类型以及相应的 statfs64()
和 statvfs64()
系统调用包装器。这避免让 glibc 做任何猜测,并确保您使用可以正确描述所有 Linux 文件系统大小的系统调用版本。
这两个选项都适用于所有 Linux 架构,32 位和 64 位。