fsdax: dedupe: iter two files at the same time

The iomap_iter() on a range of one file may loop more than once.  In this
case, the inner dst_iter can update its iomap but the outer src_iter
can't.  This may cause the wrong remapping in filesystem.  Let them called
at the same time.

Link: https://lkml.kernel.org/r/1669908701-93-1-git-send-email-ruansy.fnst@fujitsu.com
Signed-off-by: Shiyang Ruan <ruansy.fnst@fujitsu.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Cc: Alistair Popple <apopple@nvidia.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Jason Gunthorpe <jgg@nvidia.com>
Cc: John Hubbard <jhubbard@nvidia.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Shiyang Ruan 2022-12-01 15:31:41 +00:00 committed by Andrew Morton
parent c6f0b395b2
commit 0e79e3736d

View file

@ -1965,15 +1965,15 @@ int dax_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
.len = len,
.flags = IOMAP_DAX,
};
int ret;
int ret, compared = 0;
while ((ret = iomap_iter(&src_iter, ops)) > 0) {
while ((ret = iomap_iter(&dst_iter, ops)) > 0) {
dst_iter.processed = dax_range_compare_iter(&src_iter,
&dst_iter, len, same);
}
if (ret <= 0)
src_iter.processed = ret;
while ((ret = iomap_iter(&src_iter, ops)) > 0 &&
(ret = iomap_iter(&dst_iter, ops)) > 0) {
compared = dax_range_compare_iter(&src_iter, &dst_iter, len,
same);
if (compared < 0)
return ret;
src_iter.processed = dst_iter.processed = compared;
}
return ret;
}