Thanks for the review. You are correct that dax_range_compare_iter()
has a bug where ALIGN(pos1 + len, PAGE_SIZE) passes an absolute file
offset instead of a relative length to dax_iomap_direct_access().
This causes dax_direct_access() to request a massively inflated
nr_pages via PHYS_PFN(size).

This is a real bug, but it is a separate pre-existing issue from the
error code propagation bug that this patch fixes. I have already
submitted a separate patch to fix it:

  "dax: fix dax_range_compare_iter() to use correct size and address offset"

That patch:
  1. Fixes the size by computing ALIGN(len + offset_in_page(pos),
     PAGE_SIZE), matching the pattern in dax_iomap_copy_around().
  2. Also fixes memcmp() by adding offset_in_page(pos1)/
     offset_in_page(pos2) to saddr/daddr, since the returned
     addresses are page-aligned starting addresses.

The two patches fix independent bugs and can be applied separately.

Thanks,
Jianyun

On Thu, Oct 15, 2026 at 10:53 PM <[email protected]> wrote:
>
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) 
> to consider:
> - [High] fsdax: incorrect size parameter in dax_range_compare_iter causes 
> massive direct access requests
> --
>
> commit 65ff21563702a9036c338f4961a061d5c576d038
> Author: Jianyun Gao <[email protected]>
>
> dax: fix wrong error code returned from dax_dedupe_file_range_compare()
>
> This commit fixes a bug in dax_dedupe_file_range_compare() where a positive
> return value was incorrectly propagated on failure. It now correctly returns
> the negative error code from dax_range_compare_iter().
>
> Link: 
> https://lore.kernel.org/lkml/[email protected]/
>
> > diff --git a/fs/dax.c b/fs/dax.c
> > index 08adeaed2baf1..97b6212bfa898 100644
> > --- a/fs/dax.c
> > +++ b/fs/dax.c
> > @@ -2254,7 +2254,7 @@ int dax_dedupe_file_range_compare(struct inode *src, 
> > loff_t srcoff,
> >               status = dax_range_compare_iter(&src_iter, &dst_iter,
> >                               min(src_iter.len, dst_iter.len), same);
> >               if (status < 0)
> > -                     return ret;
> > +                     return status;
>
> [Severity: High]
> By correctly propagating the error code here, does this patch now expose a
> bug in dax_range_compare_iter() that will break dedupe for large offsets?
>
> Looking at dax_range_compare_iter() in fs/dax.c, it appears to pass an
> absolute end offset instead of a length as the size parameter to
> dax_iomap_direct_access():
>
> static int dax_range_compare_iter(...)
> {
>         ...
>         ret = dax_iomap_direct_access(smap, pos1, ALIGN(pos1 + len, 
> PAGE_SIZE),
>                                       &saddr, NULL);
>         ...
> }
>
> When dax_iomap_direct_access() receives this size parameter, it converts it
> via PHYS_PFN() and interprets the massive absolute offset as a relative
> length:
>
> fs/dax.c:dax_iomap_direct_access() {
>         ...
>         length = dax_direct_access(iomap->dax_dev, pgoff, PHYS_PFN(size),
>                                    DAX_ACCESS, kaddr, pfnp);
>         ...
> }
>
> This requests an out-of-bounds mapping length from the underlying block
> driver (up to pos1 + len instead of just len), which typically fails with
> -EINVAL or -EIO for offsets that exceed device bounds.
>
> Since this patch changes the behavior from a silent pseudo-success to an
> explicit failure, will standard deduplication at non-zero offsets now
> consistently fail when dax_range_compare_iter() erroneously asks for an
> enormous number of pages?
>
> >               src_iter.status = dst_iter.status = status;
> >       }
> >       return ret;
>
> --
> Sashiko AI review · 
> https://sashiko.dev/#/patchset/[email protected]?part=1

Reply via email to