How useful should copy_file_range be?
lwn.net
lwn.net
Linux gets feature velocity by playing fast and loose sometimes with stability. Demanding users like the Go authors are a necessary and welcome counterbalance.
I can understand functions like sendfile() being able to cut down on context switches and being helpful for bulk data transfer, but is that the case here? How much benefit do you get from copy_file_range() vs. a read/write loop?
I do note with some amusement how the kernel developer basically went "Why are you using copy_file_range on things that aren't actually files?"
I suspect that some, correctly aligned, ranges could be copied with CoW semantics, thereby skipping the read/write altogether.
Reading the manpage for copy_file_range the notes section states:
copy_file_range() gives filesystems an opportunity to implement "copy
acceleration" techniques, such as the use of reflinks (i.e., two or
more inodes that share pointers to the same copy-on-write disk blocks)
or server-side-copy (in the case of NFS).
But doesn't mention if these techniques are actually used. I guess there's some help in future proofing your code.Edit: I tested this on my Ubuntu 20.04 machine and a 1GB file full of random data sitting in the file cache. Using copy_file_range I could make a local-local copy in 0.595 seconds on average. Using a primitive copy/write loop took 0.600 seconds. But these values are somewhat noisy and the difference is down in the error margin. It doesn't appear that my 5.4.0 kernel on ext4 is employing the reflinks optimization.
Right, but if you don't, then you definitely don't need to query the file length in the first place...
So if you wanted to add bytes to the front of the file you would have to allocate new blocks to store it, but since there is no map of length for each block you would have to only move it by exact block lengths. Same for shrinking the file by cutting off the head, you can't handle values other than full blocks.
It's certainly possible to build a filesystem where this would work, but when you wrote programs using the feature they wouldn't be portable to any other commonly used filesystem. People also don't change filesystems very often, so even if you got the change into Ext and waited a decade many people would still be incompatible.
Finally, it's a feature that is helpful only rarely. So there isn't enough demand to push through such a massive change given the headwinds it has.
You could also try creating a new file and use copy_file_range to copy the tail of the file to the new one, then move it over the old one. That might reuse a good chunk of the storage on a CoW filesystem.