Hi, I noticed a strange and misleading edge case in FIDEDUPERANGE ioctl. For the files with the following content: f1: abcd f2: efghi FIDEDUPERANGE claims to succeed and reports 4 bytes deduplicated, despite the files being clearly different. Strace output: openat(AT_FDCWD, "f1", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "f2", O_WRONLY|O_CLOEXEC) = 4 ioctl(3, BTRFS_IOC_FILE_EXTENT_SAME or FIDEDUPERANGE, {src_offset=0, src_length=4, dest_count=1, info=[{dest_fd=4, dest_offset=0}]} => {info=[{bytes_deduped=4, status=0}]}) = 0 The reason is that generic_remap_checks function is doing block alignment of the deduplication length when the end of the destination file is not at the end of the deduplication range (as described in the comment): /* * If the user wanted us to link to the infile's EOF, round up to the * next block boundary for this check. * * Otherwise, make sure the count is also block-aligned, having * already confirmed the starting offsets' block alignment. */ So it effectively becomes a zero-length deduplication, which succeeds. Despite that it's reported as a successful 4 bytes deduplication. For a very similar test case, but with the files of the same length: f3: abcd f4: efgh FIDEDUPERANGE fails with FILE_DEDUPE_RANGE_DIFFERS. Strace output: openat(AT_FDCWD, "f3", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "f4", O_WRONLY|O_CLOEXEC) = 4 ioctl(3, BTRFS_IOC_FILE_EXTENT_SAME or FIDEDUPERANGE, {src_offset=0, src_length=4, dest_count=1, info=[{dest_fd=4, dest_offset=0}]} => {info=[{bytes_deduped=0, status=1}]}) = 0 For this case generic_remap_checks does not alter deduplication length, and deduplication fails when comparing the content of the files. Cheers, Zbigniew Halas