Consider i have the following piece of code:
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
int main(int argc, char** argv) {
if (argc > 2) {
int fd = open(argv[1], O_CREAT|O_WRONLY, 0777);
size_t size = atoi(argv[2]);
if (fd > 0) {
//int result = fallocate(fd, 0, 0, size);
//printf("itak: %d, errno: %d (%s)\n", result, errno, strerror(errno));
int result = posix_fallocate(fd, 0, size);
printf("itak: %d, errno: %d (%s)\n", result, result, strerror(result));
} else {
printf("failed opening file\n");
}
} else {
printf("Usage blah\n");
}
}
Which is a simple version of /usr/bin/fallocate i made to test my assumptions. I found out that if i use it to create a file which is larger than the filesystem free space it will return -1 and a proper errno, but will still create a file of a maximum allowed size. This seems strange to me, because the command explicitly returned -1, which should be a signal for a failure, but it still did something. And moreover it did not what i asked for - it created a file of an unknown (at the moment i run it) size. If i use fallocate() to reserve some space for, i dunno, kitten photos it would be useless for me if it reserves less space than i asked.
Yes, fallocate() and posix_fallocate() behave the save way, I checked both as you can see.
Naturally i thought i am doing something wrong. Because if you run into problems while programming that is what happens in 99.9%. So i tried the /usr/bin/fallocate utility and yes, it "failes", but still creates a file.
Here is an example of me running the utility:
rakul@lucky-star /tmp $ strace fallocate -l 10G /tmp/test 2>&1 | grep fallocate
execve("/usr/bin/fallocate", ["fallocate", "-l", "10G", "/tmp/test"], [/* 47 vars */]) = 0
fallocate(3, 0, 0, 10737418240) = -1 ENOSPC (No space left on device)
write(2, "fallocate: ", 11fallocate: ) = 11
write(2, "fallocate failed", 16fallocate failed) = 16
rakul@lucky-star /tmp $ ls -l /tmp/test
-rw-r--r-- 1 rakul rakul 9794732032 сен 26 19:15 /tmp/test
rakul@lucky-star
As you can see it had no specific mode set on the fallocate() call, it failed, but the file got created, of an unexpected size.
I found out that some guys on the internet see the opposite behavior:
rxxxx@home/tmp> fallocate -l 10G test.img
fallocate: fallocate failed: На устройстве не осталось свободного места
rxxxx@home/tmp> ls -l test.img
-rw-r--r-- 1 rogue rogue 0 Врс 26 17:36 test.img
(it says "not enough space left" in russian)
I have tried ext4 and tmpfs with same results. I have gentoo linux, 3.18 kernel. However originally i have seen this issue on an up-to-date SLES12.
My question is: why there are different results and how can i prevent /usr/bin/fallocate or fallocate() from creating a file in case there is not enough a