[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH] cp: with --sparse=never, avoid COW and copy offload,
Pádraig Brady <=