[comp.sys.sun] creating file space via mmap

faulkner%jmullins@husc6.harvard.edu (Don Faulkner) (05/17/89)

I've been working with mmap to create file space.  There are some problems
in letting mmap set the size of the file.

>From "man mmap":
     It should be noted that the system will always zero-fill any
     partial  pages at the end of an object.  Further, the system
     will never write out any modified portions of the last  page
     of  an object which are beyond its end.  References to whole
     pages following the end of an  object  will  result  in  the
     delivery  of  a  SIGBUS  signal.  SIGBUS signals may also be
     delivered on various filesystem conditions, including  quota
     exceeded errors.


(the System Services Overview chapter "Memory Management" doesn't
add any info for my question ...)

So --- you can't just "mmap" with a "len" greater than the length
of the file, and let it grow ...

Experimentally, the following DOES work:

fd = open ("file", O_RDWR | O_CREAT, 0666)
lseek (fd, 10000000, L_SET)  /*  max file size reasonable  */
write (fd, "", 1)
This will create a file with an enormous hole.
Then, you can mmap with len=10000000
if you address and write into the middle of a file, those blocks
touched get allocated and filled in automagically ...
(I'm trying to avoid actually POPULATING a huge block if it's not needed...)

Afterwards, you could open a new file, and copy only the elements that
were actually created...

This DOES work; the question is:  can one DEPEND on it working?
Is there a better way?
--

 Don Faulkner                                       
 Building 1, Room 803
 Harvard University, School of Public Health
 665 Huntington Avenue
 Boston, MA  02115

 ARPA:      faulkner%jmullins@harvard.harvard.edu                
 BITNET:    faulkner@harvard
 Telephone: (617) 732-2297

guy@uunet.uu.net (Guy Harris) (05/26/89)

>I've been working with mmap to create file space.  There are some problems
>in letting mmap set the size of the file.

Yup, "mmap" doesn't set the size of the file.

>Experimentally, the following DOES work:

As should anything else that grows the file.

>This DOES work; the question is:  can one DEPEND on it working?

Yes.  Not having a pagein of a page backed by a hole work in the proper
UNIX fashion (which would be to zero the page out) would have been a Very
Bad Idea, so it works.  Similarly, modifying that page causes a pageout to
work, by filling in the hole.  (Besides, since "read" and "write" on UFS
and NFS file systems work, in effect, by an in-the-kernel fast path
through "mmap", it might well have broken "read" and "write" were it not
to work.)

>Is there a better way?

Well, it depends on your definition of "better", but:

Users who pored over the 4.0 TRUNCATE(2) man page with a fine-toothed
comb would have noticed that it says

   DESCRIPTION
	truncate() causes the file  referred  to  by  path  (or  for
	ftruncate()  the  object  referred  to by fd) to have a size
	equal to length bytes.  If the file  was  previously  longer
	than  length, the extra bytes are removed from the file.  If
								  ^^
	it was shorter, bytes between the old and  new  lengths  are
	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	read  as  zeroes.  With ftruncate, the file must be open for
	^^^^^^^^^^^^^^^^
	writing.

The pre-4.0 TRUNCATE(2), and the 4.xBSD ones, didn't say anything about
"(f)truncate" making files larger.  The reason why "(f)truncate" was,
extended to allow you to, err, umm, *extend* the file (no pun intended)
was to let you grow a file to which you were writing via "mmap" rather
than via "write". 

I don't know if this was mentioned in the Read (Me|This) First (one is
for software, one is for hardware, I can't remember which is which), so
it may have been somewhat obscure....

david@elroy.jpl.nasa.gov (David Robinson) (06/14/89)

In article <3551@kalliope.rice.edu>, auspex!guy@uunet.uu.net (Guy Harris) writes:
< Well, it depends on your definition of "better", but:
< 
< Users who pored over the 4.0 TRUNCATE(2) man page with a fine-toothed
< comb would have noticed that it says
< 
<    DESCRIPTION
< 	truncate() causes the file  referred  to  by  path  (or  for
< 	ftruncate()  the  object  referred  to by fd) to have a size
< 	equal to length bytes.  If the file  was  previously  longer
< 	than  length, the extra bytes are removed from the file.  If
< 								  ^^
< 	it was shorter, bytes between the old and  new  lengths  are
< 	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
< 	read  as  zeroes.  With ftruncate, the file must be open for
< 	^^^^^^^^^^^^^^^^
< 	writing.
< 
< The pre-4.0 TRUNCATE(2), and the 4.xBSD ones, didn't say anything about
< "(f)truncate" making files larger.  The reason why "(f)truncate" was,
< extended to allow you to, err, umm, *extend* the file (no pun intended)
< was to let you grow a file to which you were writing via "mmap" rather
< than via "write". 

This is a potential "gotcha" is if you are using NFS.  Many (currently most)
NFS servers, including SunOS 3.X, do not handle this correctly, SunOS 4.0
of course does.  These "broken" servers will not extend a file using
NFS_SETATTR() which is the SunOS 4.0 NFS equivilant of truncate().
Personally I think they should have implemented it as a write of a zero
byte for backwards bug compatibility.  This is the primary reason you
cannot run a 4.0 diskless client off a 3.X server.


-- 
	David Robinson		elroy!david@csvax.caltech.edu     ARPA
				david@elroy.jpl.nasa.gov	  ARPA
				{cit-vax,ames}!elroy!david	  UUCP
Disclaimer: No one listens to me anyway!