]> git.hungrycats.org Git - bees/commitdiff
fs: get rid of 16 MiB limit on dedupe requests
authorZygo Blaxell <bees@furryterror.org>
Tue, 12 Nov 2024 01:47:36 +0000 (20:47 -0500)
committerZygo Blaxell <bees@furryterror.org>
Sun, 1 Dec 2024 04:30:33 +0000 (23:30 -0500)
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 <bees@furryterror.org>
lib/fs.cc

index 86bfba588b86cca8ad5ce04305f0f4816b3fb3f9..f063a0a6d068af447b1cc4a95ff49e0f61ead148 100644 (file)
--- 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;