From: Zbigniew Jędrzejewski-Szmek Date: Wed, 15 Jul 2026 10:59:45 +0000 (+0200) Subject: shared/copy: simplify argument convention for reflink_range X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F43034%2Fhead;p=thirdparty%2Fsystemd.git shared/copy: simplify argument convention for reflink_range reflink_range() would treat size==UINT64_MAX as "copy everything", but only if the offsets were 0. There are only two callers: one always passes a fixed size, the other translated size==UINT64_MAX to 0. Make things more uniform by always treating size==UINT64_MAX the same as size==0. --- diff --git a/src/shared/copy.c b/src/shared/copy.c index ded40b524eb..208e3fd52d2 100644 --- a/src/shared/copy.c +++ b/src/shared/copy.c @@ -152,7 +152,7 @@ static int try_reflink_copy_bytes( if (toffset < 0) return -EOPNOTSUPP; - r = reflink_range(fdf, foffset, fdt, toffset, max_bytes == UINT64_MAX ? 0 : max_bytes); + r = reflink_range(fdf, foffset, fdt, toffset, max_bytes); if (r < 0) return -EOPNOTSUPP; @@ -1748,22 +1748,19 @@ int reflink(int infd, int outfd) { assert_cc(sizeof(struct file_clone_range) == sizeof(struct btrfs_ioctl_clone_range_args)); -int reflink_range(int infd, uint64_t in_offset, int outfd, uint64_t out_offset, uint64_t sz) { - struct file_clone_range args = { - .src_fd = infd, - .src_offset = in_offset, - .src_length = sz, - .dest_offset = out_offset, - }; +int reflink_range(int infd, uint64_t in_offset, int outfd, uint64_t out_offset, uint64_t size) { int r; assert(infd >= 0); assert(outfd >= 0); + /* size==UINT64_MAX mean "clone everything". Translate to 0 for the kernel. */ + if (size == UINT64_MAX) + size = 0; + /* Inside the kernel, FICLONE is identical to FICLONERANGE with offsets and size set to zero, let's - * simplify things and use the simple ioctl in that case. Also, do the same if the size is - * UINT64_MAX, which is how we usually encode "everything". */ - if (in_offset == 0 && out_offset == 0 && IN_SET(sz, 0, UINT64_MAX)) + * simplify things and use the simple ioctl in that case. */ + if (in_offset == 0 && out_offset == 0 && size == 0) return reflink(infd, outfd); r = fd_verify_regular(outfd); @@ -1772,5 +1769,11 @@ int reflink_range(int infd, uint64_t in_offset, int outfd, uint64_t out_offset, assert_cc(FICLONERANGE == BTRFS_IOC_CLONE_RANGE); + struct file_clone_range args = { + .src_fd = infd, + .src_offset = in_offset, + .src_length = size, + .dest_offset = out_offset, + }; return RET_NERRNO(ioctl(outfd, FICLONERANGE, &args)); } diff --git a/src/shared/copy.h b/src/shared/copy.h index c5ced00bc9c..975b1e99424 100644 --- a/src/shared/copy.h +++ b/src/shared/copy.h @@ -109,4 +109,4 @@ static inline int copy_rights(int fdf, int fdt) { int copy_xattr(int df, const char *from, int dt, const char *to, CopyFlags copy_flags); int reflink(int infd, int outfd); -int reflink_range(int infd, uint64_t in_offset, int outfd, uint64_t out_offset, uint64_t sz); +int reflink_range(int infd, uint64_t in_offset, int outfd, uint64_t out_offset, uint64_t size);