On Fri, Aug 23, 2019 at 4:58 PM Max Reitz <mre...@redhat.com> wrote: > On 22.08.19 21:01, Nir Soffer wrote: > ...
> > > > @@ -1794,6 +1815,8 @@ static int handle_aiocb_truncate(void > > *opaque) > > > > /* posix_fallocate() doesn't set errno. */ > > > > error_setg_errno(errp, -result, > > > > "Could not preallocate new > > data"); > > > > + } else if (current_length == 0) { > > > > + allocate_first_block(fd); > > > > > > Should posix_fallocate() not take care of precisely this? > > > > > > > > > Only if the filesystem does not support fallocate() (e.g. NFS < > 4.2). > > > > > > In this case posix_fallocate() is doing: > > > > > > for (offset += (len - 1) % increment; len > 0; offset += > increment) > > > { > > > len -= increment; > > > if (offset < st.st_size) > > > { > > > unsigned char c; > > > ssize_t rsize = __pread (fd, &c, 1, offset); > > > if (rsize < 0) > > > return errno; > > > /* If there is a non-zero byte, the block must have been > > > allocated already. */ > > > else if (rsize == 1 && c != 0) > > > continue; > > > } > > > if (__pwrite (fd, "", 1, offset) != 1) > > > return errno; > > > } > > > > > > > > > https://code.woboq.org/userspace/glibc/sysdeps/posix/posix_fallocate.c.html#96 > > > > > > So opening a file with O_DIRECT will break preallocation=falloc on > > such > > > filesystems, > > > > But won’t the function above just fail with EINVAL? > > allocate_first_block() is executed only in case of success. > > > > > > Sure, but if posix_fallocate() fails, we fail qemu-img create/convert. > > Exactly. But if posix_fallocate() works, it should have allocated the > first block. > Only if the file system does not support fallocate(). posix_fallocate() first try fallocate(), and fall back to manual preallocation: https://code.woboq.org/userspace/glibc/sysdeps/unix/sysv/linux/posix_fallocate.c.html#27 Here is an example using fallocate --posix: $ sudo mount -t glusterfs gluster1:/gv0 /tmp/gv0 (gv0 is gluster volume backed by XFS on top of VDO device with 4k sector size) $ fallocate -l 1g --posix empty.raw $ dd if=empty.raw bs=1 count=1 of=/dev/null iflag=direct status=none $ dd if=/dev/zero bs=1 count=1 of=empty.raw conv=notrunc status=none $ dd if=empty.raw bs=1 count=1 of=/dev/null iflag=direct status=none dd: error reading 'empty.raw': Invalid argument $ dd if=empty.raw bs=512 count=1 of=/dev/null iflag=direct status=none dd: error reading 'empty.raw': Invalid argument $ dd if=empty.raw bs=4096 count=1 of=/dev/null iflag=direct status=none Here is example using gluster storage with sector size of 512 bytes. $ sudo mount -t glusterfs gluster1:/gv1 /tmp/gv1 $ fallocate -l 1g --posix empty.raw $ dd if=empty.raw bs=1 count=1 of=/dev/null iflag=direct status=none $ dd if=/dev/zero bs=1 count=1 of=empty.raw conv=notrunc status=none $ dd if=empty.raw bs=1 count=1 of=/dev/null iflag=direct status=none dd: error reading 'empty.raw': Invalid argument $ dd if=empty.raw bs=512 count=1 of=/dev/null iflag=direct status=none So we must allocated using write() after calling posix_fallocate(). Nir