Skip to content

dedupe: clamp the source range to the file size to avoid EINVAL (#398) - #409

Open
martinus wants to merge 1 commit into
markfasheh:masterfrom
martinus:backport/dedupe-einval-clamp
Open

dedupe: clamp the source range to the file size to avoid EINVAL (#398)#409
martinus wants to merge 1 commit into
markfasheh:masterfrom
martinus:backport/dedupe-einval-clamp

Conversation

@martinus

Copy link
Copy Markdown

What this fixes

The kernel rejects the entire FIDEDUPERANGE ioctl with EINVAL when the source range extends past the end of the source file — the off + len > i_size_read(src) check in vfs_dedupe_file_range().

Extent lengths come from fiemap's fe_length, which is rounded up to the filesystem block size, so a file's final extent typically reports a length that overshoots the real end of file. (A file that shrank since it was scanned does the same.)

What happens without the fix

Deduping genuinely-duplicate data fails with Dedupe ioctl returns 22: Invalid argument, and the whole batch of destinations sharing that source is dropped — so real, deduplicable data is silently left un-deduped. This is the common #398 report.

The fix

Clamp the request to the source file's current size (fstat) before issuing the ioctl, so we dedupe what actually exists. If the source offset is now entirely past EOF, move the queued requests to the completed list and skip the doomed ioctl. A too-short destination is unaffected — the kernel reports that per-file via info->status.

Fixes: #398

…fasheh#398)

The kernel rejects the entire FIDEDUPERANGE ioctl with EINVAL when the
source range extends past the end of the source (ioctl) file - the
"off + len > i_size_read(src)" check in vfs_dedupe_file_range().

Extent lengths come from fiemap's fe_length, which is rounded up to the
filesystem block size, so a file's final extent typically reports a
length that overshoots the real end of file (a file that shrank since it
was scanned does the same). Using that as the dedupe source range fails
the whole batch with "Dedupe ioctl returns 22: Invalid argument" even
though the data is genuinely deduplicable.

Clamp the request to the source file's current size before the ioctl. If
the source offset is now entirely past EOF, move the queued requests to
the completed list and skip the doomed ioctl. A too-short destination is
unaffected - the kernel reports that per-file via info->status.

Fixes: markfasheh#398
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ioctl returns 22: Invalid argument

1 participant