在经过以下修剪的4个调用之后,我无法在应用程序中重现此问题,但这与我在gpfs文件系统上的单线程应用程序一致。
重要的通话顺序是
const int64_t capacity = 8458240;
ftruncate64(fd, current_size + capacity);
fstat(fd, &buf);
munmap(base, capacity);
base = mmap64(nullptr, capacity, PROT_READ|PROT_WRITE, MAP_SHARED, fd, current_size);
它可用于除gpfs之外的所有可用文件系统。 注意:current_size不会四舍五入为容量,但是会单调增加。 因此,程序及以上调用成功运行了一段时间,直到被截断5724962816。在这种情况下,文件在gpfs上调整为仅5716836352(恰好是5716MB)。较小的尺寸效果很好。 在strace输出上可见:
ftruncate(6, 5724962816) = 0
fstat(6, {st_mode=S_IFREG|0640, st_size=5716836352, ...}) = 0
对往远处看有什么建议吗?
谢谢。
PS: 我能够产生简单的问题代码:
int main(int argc, char* argv[])
{
auto m_fd = ::open(argv[1], O_RDWR|O_CREAT|O_TRUNC, (S_IRUSR | S_IWUSR) | (S_IRGRP | S_IWGRP));
long m_capacity = 8458240L;
long size = 60033856276L/8458240L;
long increment = 8417280L;
for(long i = 1; i<size; i++)
{
if( ::ftruncate64(m_fd, m_capacity + increment*i) < 0 )
{
std::cerr<<"ftruncate failed "<< errno << " "<<::strerror(errno) <<endl;
return 1;
}
int8_t* base = (int8_t*)::mmap(nullptr, m_capacity, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, increment*i);
if(base == MAP_FAILED)
{
std::cerr<<"mmap failed"<< errno << " "<<::strerror(errno) <<endl;
return 1;
}
struct stat buf;
::fstat(m_fd, &buf);
if(buf.st_size != m_capacity + increment*i)
{
std::cerr<< "size failed " << buf.st_size << " "<< (m_capacity + increment*i) << ", i " << i<< endl;
return 1;
}
for (int64_t i = 0; i < m_capacity; ++i)
{
volatile int8_t* addr = base + i;
int8_t x = *addr;
*addr = x;
}
::munmap(base, m_capacity);
}
return 0;
}
如果我返回,它将在“失败5716836352 5723791360,i 679”之后出现。
更新: 我通过基本调用第二次ftruncate64(如果大小不匹配)使用相同的值来创建解决方法。 值得注意的是,我遇到的第二个失败是第一个的x2,所以我可能会将其留给IBM。
大小失败5716836352 5723791360,i 679 大小失败11433672704 11439124480,i 1358