fsdax: dedupe: iter two files at the same time
authorShiyang Ruan <ruansy.fnst@fujitsu.com>
Thu, 1 Dec 2022 15:31:41 +0000 (15:31 +0000)
committerAndrew Morton <akpm@linux-foundation.org>
Mon, 12 Dec 2022 02:12:16 +0000 (18:12 -0800)
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>
fs/dax.c

index fa547ce..8fb928c 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -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;
 }