In the Analyzer's data collection library, the data files are
grown by ftruncating the file to a larger size, and then mmaping
the new space. When the filesystem is close to full, both those syscalls
succeed, but at some later point writing into the mapped area gets SIGBUS.
It would be much easier to cope with an error if either the ftruncate or
the mmap would fail, at the time we're growing the file, rather than have
a later unrecoverable failure during the writing of the data.
Work Around
Several:
a) use mmap()/memset()/msync() sequence:
ftruncate(fd, new_size);
addr = mmap (0, new_size-old_size, <>, <>, fd, old_size);
sigaction (SIGBUS, &temp_excp_catcher, &save);
memset (addr, 0, new_size-old_size);
msync (addr, new_size-old_size, MS_SYNC);
sigaction (SIGBUS, &save, NULL);
This may be problematic in MT programs but preserves the "suggested syntax".
b) mmap anon memory and use pwrite() to write it to the to-be-extended file:
tmpaddr = mmap(0, new_size-old_size, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0);
memset(tmpaddr, 0, new_size-old_size);
pwrite(fd, tmpaddr, new_size-old_size, old_size);
munmap(tmpaddr, new_size-old_size);
c) S8 and above: Use sendfile():
tmpfd = open("/dev/zero", O_RDONLY, 0);
lseek (fd, 0, SEEK_END);
sendfile(fd, tmpfd, 0, new_size-old_size);
close (tmpfd);
These two require a change in syntax but perform the same task - in the sendfile case likely much more effective than all other solutions, including the way the submitter wants to do the task of extending a file.