Re: ftruncate() after FICLONERANGE costs 300-600us/file, ~10x more than the clone itself
From: Matteo Croce
Date: Tue Jul 07 2026 - 11:23:32 EST
Il giorno mar 7 lug 2026 alle ore 08:20 Christoph Hellwig
<hch@xxxxxxxxxxxxx> ha scritto:
> I wonder if we hit the filemap_write_and_wait_range case in
> xfs_vn_setattr_size due to a non-uptodate i_disk_size for this
> workload somehow? Although reflink should update i_disk_size
> properly.
Possibly related datapoint, from the write-trunc mode of my
benchmark (write of the size rounded up to the block, then
ftruncate to the real size): the truncate synchronously flushes the
delalloc data even when it does not change the file size at all. A
no-op ftruncate at a block-aligned 65536 costs 514us on a freshly
written file, versus 7us for the same no-op on a freshly cloned
file, and the syncfs time of the run drops accordingly, so the
deferred writeback cost moves into the truncate. If a tracepoint or
counter would help pinpointing where the time goes, I am happy to
run it.
> >
> > 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?
>
> Only doing the reflink block aligned and copying data for partial
> blocks should indeed always be faster. But I wonder if we have
> some dragons lurking in the truncate down path.
>
That is the plan for tar: clone the whole blocks and write the
final partial block, avoiding the truncate entirely. In my
prototype this turns the 3.4x slowdown into a 1.6x speedup on XFS,
with the small cost that the tail block of each member is no longer
shared with the archive.
Regards,
--
per aspera ad upstream