From: Pádraig Brady
Date: Sun, 2 May 2021 20:27:17 +0000 (+0100) Subject: copy: ensure we enforce --reflink=never X-Git-Tag: v9.0~112 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ea9af99234031ab8d5169c8a669434e2a6b4f864;p=thirdparty%2Fcoreutils.git copy: ensure we enforce --reflink=never * src/copy.c (sparse_copy): Don't use copy_file_range() with --reflink=never as copy_file_range() may implicitly use acceleration techniques like reflinking. (extent_copy): Pass through whether we allow reflinking. (lseek_copy): Likewise. Fixes https://bugs.gnu.org/48164 --- diff --git a/src/copy.c b/src/copy.c index b7ec9747fa..3e1abee289 100644 --- a/src/copy.c +++ b/src/copy.c @@ -258,7 +258,7 @@ create_hole (int fd, char const *name, bool punch_holes, off_t size) bytes read. */ static bool sparse_copy (int src_fd, int dest_fd, char *buf, size_t buf_size, - size_t hole_size, bool punch_holes, + size_t hole_size, bool punch_holes, bool allow_reflink, char const *src_name, char const *dst_name, uintmax_t max_n_read, off_t *total_n_read, bool *last_write_made_hole) @@ -266,8 +266,9 @@ sparse_copy (int src_fd, int dest_fd, char *buf, size_t buf_size, *last_write_made_hole = false; *total_n_read = 0; - /* If not looking for holes, use copy_file_range if available. */ - if (!hole_size) + /* If not looking for holes, use copy_file_range if available, + but don't use if reflink disallowed as that may be implicit. */ + if ((! hole_size) && allow_reflink) while (max_n_read) { /* Copy at most COPY_MAX bytes at a time; this is min @@ -466,6 +467,7 @@ static bool extent_copy (int src_fd, int dest_fd, char *buf, size_t buf_size, size_t hole_size, off_t src_total_size, enum Sparse_type sparse_mode, + bool allow_reflink, char const *src_name, char const *dst_name, struct extent_scan *scan) { @@ -579,8 +581,8 @@ extent_copy (int src_fd, int dest_fd, char *buf, size_t buf_size, if ( ! sparse_copy (src_fd, dest_fd, buf, buf_size, sparse_mode == SPARSE_ALWAYS ? hole_size: 0, - true, src_name, dst_name, ext_len, &n_read, - &read_hole)) + true, allow_reflink, src_name, dst_name, + ext_len, &n_read, &read_hole)) goto fail; dest_pos = ext_start + n_read; @@ -655,6 +657,7 @@ static bool lseek_copy (int src_fd, int dest_fd, char *buf, size_t buf_size, size_t hole_size, off_t ext_start, off_t src_total_size, enum Sparse_type sparse_mode, + bool allow_reflink, char const *src_name, char const *dst_name) { off_t last_ext_start = 0; @@ -729,8 +732,8 @@ lseek_copy (int src_fd, int dest_fd, char *buf, size_t buf_size, bool read_hole; if ( ! sparse_copy (src_fd, dest_fd, buf, buf_size, sparse_mode == SPARSE_NEVER ? 0 : hole_size, - true, src_name, dst_name, ext_len, &n_read, - &read_hole)) + true, allow_reflink, src_name, dst_name, + ext_len, &n_read, &read_hole)) return false; dest_pos = ext_start + n_read; @@ -1526,17 +1529,20 @@ copy_reg (char const *src_name, char const *dst_name, ? extent_copy (source_desc, dest_desc, buf, buf_size, hole_size, src_open_sb.st_size, make_holes ? x->sparse_mode : SPARSE_NEVER, + x->reflink_mode != REFLINK_NEVER, src_name, dst_name, &scan_inference.extent_scan) #ifdef SEEK_HOLE : scantype == LSEEK_SCANTYPE ? lseek_copy (source_desc, dest_desc, buf, buf_size, hole_size, scan_inference.ext_start, src_open_sb.st_size, make_holes ? x->sparse_mode : SPARSE_NEVER, + x->reflink_mode != REFLINK_NEVER, src_name, dst_name) #endif : sparse_copy (source_desc, dest_desc, buf, buf_size, make_holes ? hole_size : 0, x->sparse_mode == SPARSE_ALWAYS, + x->reflink_mode != REFLINK_NEVER, src_name, dst_name, UINTMAX_MAX, &n_read, &wrote_hole_at_eof))) {