How-to: fcntl + F_PREALLOCATE + F_ALLOCATECONTIG and mmap
How-to: fcntl + F_PREALLOCATE + F_ALLOCATECONTIG and mmap
- Subject: How-to: fcntl + F_PREALLOCATE + F_ALLOCATECONTIG and mmap
- From: David Hoerl <email@hidden>
- Date: Fri, 14 Dec 2007 15:52:46 -0500
[For the archives.]
This post will hopefully help some other poor soul struggling with
how to use this tantilizing feature, given that a deep google search
found nothing more than the fcntl man page.
Preallocating disk space on OSX / Darwin using fcntl, possibly for
use with mmap().
You may need these headers:
#include <fcntl.h>
#include <sys/stat.h>
Create a file with open():
open("/tmp/preallocTest", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
Then setup a fstore_t structure per the fcntl man page:
fstore_t fst;
fst.fst_flags = F_ALLOCATECONTIG; // could add F_ALLOCATEALL
fst.fst_posmode = F_PEOFPOSMODE; // allocate from EOF (0)
fst.fst_offset = 0; // offset relative to the EOF
fst.fst_length = desiredSize;
fst.fst_bytesalloc = 0; // why not but is not needed
ret = fcntl(fd, F_PREALLOCATE, &fst);
if(ret == -1) { // read fcntl docs - must test against -1
fprintf(stderr, "failed to expand temp file to size %d (errno %d -
%s).\n", imageSize, errno, strerror(errno));
exit(0);
}
Now, it gets interesting. Unless "desiredSize" is on a block
boundary, what you get back will probably be more than you asked for.
So, really, I cannot find any good reason to test the size after this call.
You are probably doing this as a potential performance enhancer. But
if you do the test, expect that the number will most likely be higher
than the request, but could be less too.
To test for success, you MUST test for "!= -1" (read the fcntl docs),
not "!= 0".
Now this was the most confusing aspect to me:
ret = fstat(fd, &sb);
if(ret != 0) {
fprintf(stderr, "failed to write to temp file to establish
the size.\n");
exit(0);
}
assert(sb.st_size == 0);
succeeds! Also, seeking to the end of the file also shows the file
has a 0 length!
Then, how do we know anything happened? Well, look at the sb record:
fprintf(stderr, "BLOCKS %d\n", sb.st_blocks );
Yup, lots of disk blocks, awaiting your data!
If you want the file actually allocated (for use with mmap, my
application), you can fill it with zeros now by:
ret = ftruncate(fd, desiredSize); // NOT fst.fst_bytesAllocated!
if(ret != 0) {
fprintf(stderr, "failed to write to temp file to establish the size
(%d).\n", errno);
exit();
}
Hope this helps someone out - I could have used it two years ago!
David
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden