aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Johnston <[email protected]>2024-07-23 10:20:46 -0400
committerTony Hutter <[email protected]>2024-08-22 15:17:21 -0700
commit3a36797ad65f55701d34f576c85f0e883b63c0e7 (patch)
tree569f81437904607587aac7bdd9af520a7e13d8b9
parentac6500389b12da35c954e81d6317944338cce9dc (diff)
FreeBSD: Fix RLIMIT_FSIZE handling for block cloning
ZFS implements copy_file_range(2) using block cloning when possible. This implementation must respect the RLIMIT_FSIZE limit. zfs_clone_range() already checks the limit, so it is safe to remove this check in zfs_freebsd_copy_file_range(). Moreover, the removed check produces false positives: the length passed to copy_file_range(2) may be larger than the input file size; as the man page notes, "for best performance, call copy_file_range() with the largest len value possible." In particular, some existing code passes SSIZE_MAX there. The check in zfs_clone_range() clamps the length to the input file's size before checking, but the removed check uses the caller supplied length, so something like $ echo a > /tmp/foo $ limits -f 1024 cat /tmp/foo > /tmp/bar fails because FreeBSD's cat(1) uses copy_file_range(2) in the manner described above. Reported-by: Philip Paeps <[email protected]> Signed-off-by: Mark Johnston <[email protected]> Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Allan Jude <[email protected]> Reviewed-by: Tino Reichardt <[email protected]> Reviewed-by: Tony Hutter <[email protected]>
-rw-r--r--module/os/freebsd/zfs/zfs_vnops_os.c7
1 files changed, 0 insertions, 7 deletions
diff --git a/module/os/freebsd/zfs/zfs_vnops_os.c b/module/os/freebsd/zfs/zfs_vnops_os.c
index 5962baf23..68cf57074 100644
--- a/module/os/freebsd/zfs/zfs_vnops_os.c
+++ b/module/os/freebsd/zfs/zfs_vnops_os.c
@@ -6268,7 +6268,6 @@ zfs_freebsd_copy_file_range(struct vop_copy_file_range_args *ap)
struct vnode *invp = ap->a_invp;
struct vnode *outvp = ap->a_outvp;
struct mount *mp;
- struct uio io;
int error;
uint64_t len = *ap->a_lenp;
@@ -6316,12 +6315,6 @@ zfs_freebsd_copy_file_range(struct vop_copy_file_range_args *ap)
goto out_locked;
#endif
- io.uio_offset = *ap->a_outoffp;
- io.uio_resid = *ap->a_lenp;
- error = vn_rlimit_fsize(outvp, &io, ap->a_fsizetd);
- if (error != 0)
- goto out_locked;
-
error = zfs_clone_range(VTOZ(invp), ap->a_inoffp, VTOZ(outvp),
ap->a_outoffp, &len, ap->a_outcred);
if (error == EXDEV || error == EAGAIN || error == EINVAL ||