]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
shared/copy: simplify return convention for try_reflink_copy_bytes
authorZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Wed, 15 Jul 2026 10:39:30 +0000 (12:39 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Wed, 15 Jul 2026 11:54:28 +0000 (13:54 +0200)
Follow-up for 5a12005c834eab92d7c76d61c7090aa78b61cdfb.

Also a rescue a comment from the discussion in the PR.

src/repart/repart.c
src/shared/copy.c

index 7eadfe4a6afb292882ec4d5f381dc8f5443ba610..002fb782be53f5eb1ec8219cf03550ba7c72785c 100644 (file)
@@ -6371,6 +6371,12 @@ static int context_copy_blocks(Context *context) {
                                 return log_error_errno(errno, "Failed to seek to copy blocks offset in %s: %m", p->copy_blocks_path);
                 }
 
+                /* We call copy_bytes_full() instead of copy_file_range() directly, because copy_file_range()
+                 * needs to be called with a size limit to allow for progress updates. But we don't want that
+                 * for cloning, we want one big massive reflink if possible, and unfortunately we can't know
+                 * if copy_file_range() will do reflink or not, so we can't call it without the size limit.
+                 * Hence, call copy_bytes_full(), which tries FICLONE/BTRFS_IOC_CLONE first to do one big
+                 * clone, and then falls back to copying in chunks. */
                 r = copy_bytes_full(
                                 p->copy_blocks_fd,
                                 partition_target_fd(t),
index 7a87842a344bb58529a59cf189a773ba714911e8..ded40b524ebc40863041f73984f8e9a98e760958 100644 (file)
@@ -130,36 +130,31 @@ static int create_hole(int fd, off_t size) {
         return 0;
 }
 
-/* Returns positive if the range was cloned, zero if cloning is unavailable, and negative if finalizing a
- * successful clone failed. If the range was cloned, returns the copy_bytes_full() result in ret_copy_result. */
 static int try_reflink_copy_bytes(
                 int fdf,
                 int fdt,
                 uint64_t max_bytes,
-                CopyFlags copy_flags,
-                int *ret_copy_result) {
+                CopyFlags copy_flags) {
 
-        off_t foffset, toffset;
         int r;
 
         assert(fdf >= 0);
         assert(fdt >= 0);
-        assert(ret_copy_result);
 
         if (max_bytes == 0)
-                return 0;
+                return -EOPNOTSUPP;
 
-        foffset = FLAGS_SET(copy_flags, COPY_SEEK0_SOURCE) ? 0 : lseek(fdf, 0, SEEK_CUR);
+        off_t foffset = FLAGS_SET(copy_flags, COPY_SEEK0_SOURCE) ? 0 : lseek(fdf, 0, SEEK_CUR);
         if (foffset < 0)
-                return 0;
+                return -EOPNOTSUPP;
 
-        toffset = FLAGS_SET(copy_flags, COPY_SEEK0_TARGET) ? 0 : lseek(fdt, 0, SEEK_CUR);
+        off_t toffset = FLAGS_SET(copy_flags, COPY_SEEK0_TARGET) ? 0 : lseek(fdt, 0, SEEK_CUR);
         if (toffset < 0)
-                return 0;
+                return -EOPNOTSUPP;
 
         r = reflink_range(fdf, foffset, fdt, toffset, max_bytes == UINT64_MAX ? 0 : max_bytes);
         if (r < 0)
-                return 0;
+                return -EOPNOTSUPP;
 
         if (max_bytes == UINT64_MAX) {
                 off_t end;
@@ -172,15 +167,11 @@ static int try_reflink_copy_bytes(
 
                 if (lseek(fdt, toffset + (end - foffset), SEEK_SET) < 0)
                         return -errno;
-
-                *ret_copy_result = 0; /* We copied to EOF. */
         } else {
                 if (lseek(fdf, foffset + max_bytes, SEEK_SET) < 0)
                         return -errno;
                 if (lseek(fdt, toffset + max_bytes, SEEK_SET) < 0)
                         return -errno;
-
-                *ret_copy_result = 1; /* We copied the requested range. */
         }
 
         if (FLAGS_SET(copy_flags, COPY_VERIFY_LINKED)) {
@@ -189,7 +180,8 @@ static int try_reflink_copy_bytes(
                         return r;
         }
 
-        return 1;
+        return max_bytes == UINT64_MAX ? 0 /* we copied until EOF */
+                                       : 1 /* we copied the requested range */;
 }
 
 int copy_bytes_full(
@@ -239,12 +231,9 @@ int copy_bytes_full(
             lseek(fdt, 0, SEEK_SET) < 0)
                 return -errno;
 
-        int reflink_result = 0;
-        r = try_reflink_copy_bytes(fdf, fdt, max_bytes, copy_flags, &reflink_result);
-        if (r < 0)
+        r = try_reflink_copy_bytes(fdf, fdt, max_bytes, copy_flags);
+        if (r != -EOPNOTSUPP)
                 return r;
-        if (r > 0)
-                return reflink_result;
 
         usec_t start_timestamp = USEC_INFINITY;
         if (progress)