Re: ftruncate() after FICLONERANGE costs 300-600us/file, ~10x more than the clone itself

From: Matteo Croce

Date: Tue Jul 07 2026 - 11:13:38 EST


Il giorno mar 7 lug 2026 alle ore 07:56 Darrick J. Wong
<djwong@xxxxxxxxxx> ha scritto:
> Assuming src.dat is the fully written 90000 byte file, can you
>
> $ xfs_io -c "reflink src.dat 86016 86016 0" dest.dat
>
> to link only the eof-block into dest.dat and keep its file size at
> 90000?
>

Yes, that works nicely:

$ dd if=/dev/urandom of=src.dat bs=90000 count=1; sync
$ strace -T -e trace=ioctl,ftruncate xfs_io -f \
-c "reflink src.dat 86016 86016 0" dest.dat
ioctl(3, FICLONERANGE, {src_fd=4, src_offset=86016, src_length=0,
dest_offset=86016}) = 0 <0.000093>
$ stat -c %s dest.dat
90000
$ cmp -i 86016 src.dat dest.dat && echo tail OK
tail OK
$ filefrag -v dest.dat
Filesystem type is: 58465342
File size of dest.dat is 90000 (22 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 21.. 21: 45.. 45: 1:
21: last,shared,eof
dest.dat: 1 extent found

The clone of the unaligned EOF block costs the same ~90us as any
other clone, it sets the destination size without any truncate, and
the block is really shared. So the whole overhead I measured is in
the truncate-down zeroing of the shared tail block, as you said.

The out of place write is also nicely visible in filefrag after the
clone+truncate sequence (src.dat is a 1 MiB file here, so the cloned
range lies inside it): only the tail block loses the sharing, and it
lands out of sequence with respect to the shared run:

$ xfs_io -f -c "reflink src.dat 0 0 90112" -c "truncate 90000" dest.dat
$ filefrag -v dest.dat
File size of dest.dat is 90000 (22 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 20: 46.. 66: 21: shared
1: 21.. 21: 45.. 45: 1: 67: last,eof
dest.dat: 2 extents found

Sadly, tar cannot use the eof-block shape for the general case: the
member data does not end at the archive EOF (the end-of-archive
marker follows), so there is no source EOF to link from. The plan
for tar on the affected filesystems is to clone the whole blocks and
write the final partial block, which avoids the truncate entirely
and in my prototype turns the 3.4x slowdown into a 1.6x speedup.

Regards,
--
per aspera ad upstream