Punch hole on a reflinked file needs dax_iomap_cow_copy() too.
Otherwise, data in not aligned area will be not correct.  So, add the
CoW operation for not aligned case in dax_memzero().

Signed-off-by: Shiyang Ruan <ruansy.f...@fujitsu.com>
Reviewed-by: Ritesh Harjani <rite...@linux.ibm.com>
Reviewed-by: Darrick J. Wong <djw...@kernel.org>
Reviewed-by: Christoph Hellwig <h...@lst.de>

==
This patch changed a lot when rebasing to next-20220504 branch.  Though it
has been tested by myself, I think it needs a re-review.
==
---
 fs/dax.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/fs/dax.c b/fs/dax.c
index 78e26204697b..b3aa863e9fec 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -1220,17 +1220,27 @@ static vm_fault_t dax_pmd_load_hole(struct xa_state 
*xas, struct vm_fault *vmf,
 }
 #endif /* CONFIG_FS_DAX_PMD */
 
-static int dax_memzero(struct dax_device *dax_dev, pgoff_t pgoff,
-               unsigned int offset, size_t size)
+static int dax_memzero(struct iomap_iter *iter, loff_t pos, size_t size)
 {
+       const struct iomap *iomap = &iter->iomap;
+       const struct iomap *srcmap = iomap_iter_srcmap(iter);
+       unsigned offset = offset_in_page(pos);
+       pgoff_t pgoff = dax_iomap_pgoff(iomap, pos);
        void *kaddr;
        long ret;
 
-       ret = dax_direct_access(dax_dev, pgoff, 1, &kaddr, NULL);
-       if (ret > 0) {
-               memset(kaddr + offset, 0, size);
-               dax_flush(dax_dev, kaddr + offset, size);
-       }
+       ret = dax_direct_access(iomap->dax_dev, pgoff, 1, &kaddr, NULL);
+       if (ret < 0)
+               return ret;
+       memset(kaddr + offset, 0, size);
+       if (srcmap->addr != iomap->addr) {
+               ret = dax_iomap_cow_copy(pos, size, PAGE_SIZE, srcmap,
+                                        kaddr);
+               if (ret < 0)
+                       return ret;
+               dax_flush(iomap->dax_dev, kaddr, PAGE_SIZE);
+       } else
+               dax_flush(iomap->dax_dev, kaddr + offset, size);
        return ret;
 }
 
@@ -1257,7 +1267,7 @@ static s64 dax_zero_iter(struct iomap_iter *iter, bool 
*did_zero)
                if (IS_ALIGNED(pos, PAGE_SIZE) && size == PAGE_SIZE)
                        rc = dax_zero_page_range(iomap->dax_dev, pgoff, 1);
                else
-                       rc = dax_memzero(iomap->dax_dev, pgoff, offset, size);
+                       rc = dax_memzero(iter, pos, size);
                dax_read_unlock(id);
 
                if (rc < 0)
-- 
2.35.1




Reply via email to