]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
copy: be more defensive/restrictive with posix_fadvise
authorPádraig Brady <P@draigBrady.com>
Fri, 31 Oct 2025 15:37:55 +0000 (15:37 +0000)
committerPádraig Brady <P@draigBrady.com>
Sat, 1 Nov 2025 11:24:59 +0000 (11:24 +0000)
* 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

index 8fd25fee9201eda7bd0a8caf01f02821a3390448..c46b7edc5228f5f1e9c398d8ad7ff20b6fa60fb6 100644 (file)
@@ -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.  */