coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] cp: with --sparse=never, avoid COW and copy offload


From: Pádraig Brady
Subject: [PATCH] cp: with --sparse=never, avoid COW and copy offload
Date: Mon, 21 Aug 2023 14:29:16 +0100

* src/cp.c (main): Set default reflink mode appropriately
with --sparse=never.
* src/copy.c (infer_scantype): Add a comment to related code.
* tests/cp/sparse-2.sh: Add a test case.
* NEWS: Mention the bug.
---
 NEWS                 | 4 ++++
 src/copy.c           | 2 ++
 src/cp.c             | 7 +++++++
 tests/cp/sparse-2.sh | 5 +++++
 4 files changed, 18 insertions(+)

diff --git a/NEWS b/NEWS
index c7e6b47c3..a104c97a2 100644
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,10 @@ GNU coreutils NEWS                                    -*- 
outline -*-
   Previously it would have failed with a "No such file or directory" error.
   [bug introduced in coreutils-9.1]
 
+  'cp --sparse=never' will avoid copy-on-write (reflinking) and copy 
offloading,
+  to ensure no holes present in the destination copy.
+  [bug introduced in coreutils-9.0]
+
   cksum again diagnoses read errors in its default CRC32 mode.
   [bug introduced in coreutils-9.0]
 
diff --git a/src/copy.c b/src/copy.c
index a4aad06a8..4943619c2 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -1139,6 +1139,8 @@ infer_scantype (int fd, struct stat const *sb,
 {
   scan_inference->ext_start = -1;  /* avoid -Wmaybe-uninitialized */
 
+  /* Only attempt SEEK_HOLE if this heuristic
+     suggests the file is sparse.  */
   if (! (HAVE_STRUCT_STAT_ST_BLOCKS
          && S_ISREG (sb->st_mode)
          && ST_NBLOCKS (*sb) < sb->st_size / ST_NBLOCKSIZE))
diff --git a/src/cp.c b/src/cp.c
index 412ef500b..e451a7e29 100644
--- a/src/cp.c
+++ b/src/cp.c
@@ -1201,6 +1201,13 @@ main (int argc, char **argv)
         }
     }
 
+  /* With --sparse=never, disable reflinking so we create a non sparse copy.
+     This will also have the effect of disabling copy offload as that may
+     propagate holes.  For e.g. FreeBSD documents that copy_file_range()
+     will try to propagate holes.  */
+  if (x.reflink_mode == REFLINK_AUTO && x.sparse_mode == SPARSE_NEVER)
+    x.reflink_mode = REFLINK_NEVER;
+
   if (x.hard_link && x.symbolic_link)
     {
       error (0, 0, _("cannot make both hard and symbolic links"));
diff --git a/tests/cp/sparse-2.sh b/tests/cp/sparse-2.sh
index 65607648a..5d3c5ece9 100755
--- a/tests/cp/sparse-2.sh
+++ b/tests/cp/sparse-2.sh
@@ -48,4 +48,9 @@ cp --debug --reflink=never --sparse=always k k2 >cp.out || 
fail=1
 cmp k k2 || fail=1
 grep 'sparse detection: .*zeros' cp.out || { cat cp.out; fail=1; }
 
+# cp should disable reflink AND copy offload with --sparse=never
+cp --debug --sparse=never k k2 >cp.out || fail=1
+cmp k k2 || fail=1
+grep 'copy offload: avoided, reflink: no' cp.out || { cat cp.out; fail=1; }
+
 Exit $fail
-- 
2.41.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]