From: Goldwyn Rodrigues <[email protected]> copy_file_range() performs an internal copy and is faster than bringing the data to userspace and writing it back.
If the copy_file_range() fails, it falls back to the older method of reading and writing for data copy. Signed-off-by: Goldwyn Rodrigues <[email protected]> --- configure.ac | 1 + src/copy.c | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 669e9d1f2..f0bd3be23 100644 --- a/configure.ac +++ b/configure.ac @@ -261,6 +261,7 @@ AC_CHECK_FUNCS([gethostid], gl_ADD_PROG([optional_bin_progs], [hostid])) AC_CHECK_FUNCS([sigsuspend], gl_ADD_PROG([optional_bin_progs], [timeout])) +AC_CHECK_FUNCS(copy_file_range) gl_WINSIZE_IN_PTEM diff --git a/src/copy.c b/src/copy.c index 3df635e81..7b5e79775 100644 --- a/src/copy.c +++ b/src/copy.c @@ -234,7 +234,29 @@ sparse_copy (int src_fd, int dest_fd, char *buf, size_t buf_size, while (max_n_read) { - ssize_t n_read = read (src_fd, buf, MIN (max_n_read, buf_size)); + ssize_t n_read = 0; + +#ifdef HAVE_COPY_FILE_RANGE + /* + * Since we don't have to create holes, we don't have to read the data + * Attempt a copy_file_range() + */ + if (!punch_holes) { + n_read = copy_file_range(src_fd, NULL, dest_fd, NULL, max_n_read, 0); + if (n_read > 0) { + max_n_read -= n_read; + *total_n_read += n_read; + continue; + } + if (n_read == 0) + break; + /* + * FALLTHROUGH: Attempt the regular read/write cycle + * if copy_file_range() fails + */ + } +#endif + n_read = read (src_fd, buf, MIN (max_n_read, buf_size)); if (n_read < 0) { if (errno == EINTR) -- 2.16.3
