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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

thank you for your work on Linux. I'm trying to report what looks to me like a
kernel issue: 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

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux