#899027 Calling sendfile(2) on sparse files on tmpfs allocates space for them

Package:
src:linux
Source:
linux
Submitter:
Enrico Zini
Date:
2021-05-23 19:12:03 UTC
Severity:
normal
Tags:
#899027#5
Date:
2018-05-18 15:19:04 UTC
From:
To:
Hello,

the code below, if run on a normal file system prints:

After creation: 0/1048576
After read: 0/1048576

but if run on a tmpfs it prints:

After creation: 0/1048576
After read: 1048576/1048576

This unexpected allocation happens only when using sendfile(2), not
while reading the file with read(2).

I observed this behaviour on a range of kernels, from Centos7's 3.10.0
to 4.16 currently running in my machine.

This is the code to reproduce it:

#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <unistd.h>
#include <stdio.h>

int main()
{
    int fd = open("test", O_WRONLY | O_CREAT, 0644);
    if (fd == -1)
    {
        perror("cannot open for writing");
        return 1;
    }

    if (ftruncate(fd, 1024*1024) == -1)
    {
        perror("cannot ftruncate");
        return 1;
    }

    close(fd);

    struct stat st;
    if (stat("test", &st) == -1)
    {
        perror("cannot stat after creation");
        return 1;
    }
    fprintf(stdout, "After creation: %d/%d\n", st.st_blocks * 512, st.st_size);

    fd = open("test", O_RDONLY);
    if (fd == -1)
    {
        perror("cannot open for reading");
        return 1;
    }

    int out = open("/dev/null", O_WRONLY);
    if (out == -1)
    {
        perror("cannot open /dev/null");
        return 1;
    }

    off_t offset = 0;
    ssize_t res = sendfile(out, fd, &offset, st.st_size);
    if (res == -1)
    {
        perror("cannot sendfile");
        return 1;
    }
    if (res != st.st_size)
        fprintf(stderr, "warning: partial sendfile\n");

    if (stat("test", &st) == -1)
    {
        perror("cannot stat after read");
        return 1;
    }
    fprintf(stdout, "After read: %d/%d\n", st.st_blocks * 512, st.st_size);

    close(out);
    close(fd);
    unlink("test");
    return 0;
}


Thanks,

Enrico

#899027#10
Date:
2018-05-20 14:13:57 UTC
From:
To:
Please report this upstream.  I would suggest sending to Alexander Viro
<viro@zeniv.linux.org.uk> and <linux-fsdevel@vger.kernel.org>.

Ben.