From 2c5754649e08a664f3d43f7bc1df08f498bc1554 Mon Sep 17 00:00:00 2001 From: =?utf8?q?P=C3=A1draig=20Brady?= Date: Fri, 31 Oct 2025 15:37:55 +0000 Subject: [PATCH] copy: be more defensive/restrictive with posix_fadvise * src/copy-file-data.c (copy_file_data): Only give the POSIX_FADV_SEQUENTIAL hint when we _know_ we'll definitely use a read/write loop to copy the data. Also only apply the hint to the whole file, as we've seen OpenZFS at least special case that. (sparse_copy): Update stale comment. --- src/copy-file-data.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/copy-file-data.c b/src/copy-file-data.c index 8fd25fee92..c46b7edc52 100644 --- a/src/copy-file-data.c +++ b/src/copy-file-data.c @@ -105,8 +105,6 @@ is_CLONENOTSUP (int err) If HOLE_SIZE, look for holes in the input; *HOLE_SIZE contains the size of the current hole so far, and update *HOLE_SIZE at end to be the size of the hole at the end of the copy. - Set *TOTAL_N_READ to the number of bytes read; this counts - the trailing hole, which has not yet been output. Read and update *DEBUG as needed. If successful, return the number of bytes copied, otherwise diagnose the failure and return -1. */ @@ -542,14 +540,17 @@ copy_file_data (int ifd, struct stat const *ist, off_t ipos, char const *iname, || (x->sparse_mode == SPARSE_AUTO && scantype != PLAIN_SCANTYPE))); - /* Don't bother calling fadvise for small copies, as it is not - likely to help performance and might even hurt it. - Note it's important to use a 0 length to indicate the whole file + /* If we _know_ we're going to read data sequentially into the process, + i.e., --reflink or --sparse are not in auto mode, + give that hint to the kernel so it can tune caching behavior. + Also we don't bother calling fadvise for small copies, + as it is not likely to help performance and might even hurt it. + Also we only apply this hint for the whole file (0 length) as OpenZFS 2.2.2 at least will otherwise synchronously (decompress and) populate the cache when given a specific length. */ - if (IO_BUFSIZE < ibytes) - fdadvise (ifd, ipos, ibytes < OFF_T_MAX - ipos ? ibytes : 0, - FADVISE_SEQUENTIAL); + if (ipos == 0 && ibytes == COUNT_MAX + && (x->reflink_mode != REFLINK_AUTO || x->sparse_mode != SPARSE_AUTO)) + fdadvise (ifd, 0, 0, FADVISE_SEQUENTIAL); /* If not making a sparse file, try to use a more-efficient buffer size. */ -- 2.47.3