OpenSolaris

Printable Version Enter a New Search
Bug ID 4517427
Synopsis All filesystems need a way to ftruncate/mmap a file with disk-space reservation
State 10-Fix Delivered (Fix available in build)
Category:Subcategory kernel:fs
Keywords 2004/395 | 2004/422 | 2005/208 | Perf-Council-reviewed | fallocate | ftruncate
Responsible Engineer Shawn Debnath
Reported Against 5.8 , 5.9 , 5.10 , generic
Duplicate Of
Introduced In
Commit to Fix snv_29
Fixed In snv_29
Release Fixed solaris_nevada(snv_29)
Related Bugs 6247728 , 6290811 , 6321352 , 6369900 , 4422184 , 4494566 , 4626090 , 4702432 , 4703993 , 4744182 , 5052113 , 5050736 , 5050738 , 6411034 , 6417437 , 6432412 , 6432459 , 6433665 , 6436393 , 6446856 , 6491953 , 6493590 , 6669199 , 6669307 , 6677939 , 6677946 , 6711995 , 4837083
Submit Date 20-October-2001
Last Update Date 3-December-2005
Description
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.
Comments
N/A