One of our users had asked about running WildFly and while putting
together the package for it I noticed a call to copy_file_range was
failing. In many cases these types of functions are opportunistic -
that is they fall back on other less performant ways of doing the same
thing. You can actually see this happening in this trace:
Typically if you want to copy one file to another you must open a
file, read it entirely into the kernel, then write the contents back out
from the kernel to your other file. You might have to do this in many
several chunks too. This can be slow. What
copy_file_range does is that it performs a copy from one fd to another
within the kernel skipping the kernel<>user roundtrips. Functions like these are considered a zero copy
mechanism. io_uring also exists in this realm.
An example I ripped from the man page might look like the
following:
As shown just a little bit ago, a related syscall, sendfile,
is very similar, however copy_file_range allows both input and output offsets to be set. On some filesystems that
support COW (copy on write) this can also allow for instant copies
where reflinks are created that point at the same data block and the
actual duplication only occurs when a file is changed.
At first blush copy_file_range looks precisely the same as another very
similar syscall called splice.
ssize_t copy_file_range(int fd_in, off_t *_Nullable off_in,
int fd_out, off_t *_Nullable off_out,
size_t size, unsigned int flags);
ssize_t splice(int fd_in, off_t *_Nullable off_in,
int fd_out, off_t *_Nullable off_out,
size_t size, unsigned int flags);
The difference is that with splice one of the fds has to be a pipe.
copy_file_range is by default going to be faster for file to file
copying. So now you know what the difference between these various
syscalls and when you might want to use one vs the other. Til next time.
Stop Deploying 50 Year Old Systems
Introducing the future cloud.
Ready for the future cloud?
Ready for the revolution in operating systems we've all been waiting for?