From 792fdbbb135f2d2fc8be8e41890ff759cb1bb735 Mon Sep 17 00:00:00 2001 From: Zygo Blaxell Date: Mon, 11 Nov 2024 20:47:36 -0500 Subject: [PATCH] fs: get rid of 16 MiB limit on dedupe requests The kernel has not required a 16 MiB limit on dedupe requests since v4.18-rc1 b67287682688 ("Btrfs: dedupe_file_range ioctl: remove 16MiB restriction"). Kernels before v4.18 would truncate the request and return the size actually deduped in `bytes_deduped`. Kernel v4.18 and later will loop in the kernel until the entire request is satisfied (although still in 16 MiB chunks, so larger extents will be split). Modify the loop in userspace to measure the size the kernel actually deduped, instead of assuming the kernel will only accept 16 MiB. On current kernels this will always loop exactly once. Since we now rely on `bytes_deduped`, make sure it has a sane value. Signed-off-by: Zygo Blaxell --- lib/fs.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/fs.cc b/lib/fs.cc index 86bfba5..f063a0a 100644 --- a/lib/fs.cc +++ b/lib/fs.cc @@ -159,12 +159,13 @@ namespace crucible { { THROW_CHECK1(invalid_argument, src_length, src_length > 0); while (src_length > 0) { - off_t length = min(off_t(BTRFS_MAX_DEDUPE_LEN), src_length); - BtrfsExtentSame bes(src_fd, src_offset, length); + BtrfsExtentSame bes(src_fd, src_offset, src_length); bes.add(dst_fd, dst_offset); bes.do_ioctl(); - auto status = bes.m_info.at(0).status; + const auto status = bes.m_info.at(0).status; if (status == 0) { + const off_t length = bes.m_info.at(0).bytes_deduped; + THROW_CHECK0(invalid_argument, length > 0); src_offset += length; dst_offset += length; src_length -= length;