* 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