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

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

 



Hi Al,

On Sun, May 20, 2018 at 05:09:40PM +0200, Enrico Zini wrote:
> 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;
> }

This still seems reproducible in same way as well with 5.10.38. Is
this intentional behaviour in some way?

Note, this was originally reported downstream in Debian as
https://bugs.debian.org/899027 .

Regards,
Salvatore



[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