[RFC PATCH v2 5/7] dax: memcpy before zeroing range

From: Shiyang Ruan
Date: Wed Oct 30 2019 - 00:14:33 EST


From: Goldwyn Rodrigues <rgoldwyn@xxxxxxxx>

However, this needed more iomap fields, so it was easier
to pass iomap and compute inside the function rather
than passing a log of arguments.

Note, there is subtle difference between iomap_sector and
dax_iomap_sector(). Can we replace dax_iomap_sector with
iomap_sector()? It would need pos & PAGE_MASK though or else
bdev_dax_pgoff() return -EINVAL.

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@xxxxxxxx>
---
fs/dax.c | 21 ++++++++++++++++-----
fs/iomap/buffered-io.c | 8 ++++----
include/linux/dax.h | 12 ++++++------
3 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/fs/dax.c b/fs/dax.c
index a4f90f3faddb..eab6bb256205 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -1117,11 +1117,16 @@ static int dax_copy_edges(loff_t pos, loff_t length, struct iomap *srcmap,
return ret;
}

-int __dax_zero_page_range(struct block_device *bdev,
- struct dax_device *dax_dev, sector_t sector,
- unsigned int offset, unsigned int size)
+int __dax_zero_page_range(struct iomap *iomap, struct iomap *srcmap, loff_t pos,
+ unsigned int offset, unsigned int size)
{
- if (dax_range_is_aligned(bdev, offset, size)) {
+ sector_t sector = dax_iomap_sector(iomap, pos & PAGE_MASK);
+ struct block_device *bdev = iomap->bdev;
+ struct dax_device *dax_dev = iomap->dax_dev;
+ int ret = 0;
+
+ if (iomap == srcmap &&
+ dax_range_is_aligned(bdev, offset, size)) {
sector_t start_sector = sector + (offset >> 9);

return blkdev_issue_zeroout(bdev, start_sector,
@@ -1141,11 +1146,17 @@ int __dax_zero_page_range(struct block_device *bdev,
dax_read_unlock(id);
return rc;
}
+ if (iomap != srcmap) {
+ ret = dax_copy_edges(pos, size, srcmap, kaddr, false);
+ if (ret)
+ goto out_unlock;
+ }
memset(kaddr + offset, 0, size);
dax_flush(dax_dev, kaddr + offset, size);
+out_unlock:
dax_read_unlock(id);
}
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(__dax_zero_page_range);

diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index c62e807956b6..3fa79389e4d0 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -960,10 +960,9 @@ static int iomap_zero(struct inode *inode, loff_t pos, unsigned offset,
}

static int iomap_dax_zero(loff_t pos, unsigned offset, unsigned bytes,
- struct iomap *iomap)
+ struct iomap *iomap, struct iomap *srcmap)
{
- return __dax_zero_page_range(iomap->bdev, iomap->dax_dev,
- iomap_sector(iomap, pos & PAGE_MASK), offset, bytes);
+ return __dax_zero_page_range(iomap, srcmap, pos, offset, bytes);
}

static loff_t
@@ -985,7 +984,8 @@ iomap_zero_range_actor(struct inode *inode, loff_t pos, loff_t count,
bytes = min_t(loff_t, PAGE_SIZE - offset, count);

if (IS_DAX(inode))
- status = iomap_dax_zero(pos, offset, bytes, iomap);
+ status = iomap_dax_zero(pos, offset, bytes, iomap,
+ srcmap);
else
status = iomap_zero(inode, pos, offset, bytes, iomap,
srcmap);
diff --git a/include/linux/dax.h b/include/linux/dax.h
index 4533bfb99683..7adf3b9e1061 100644
--- a/include/linux/dax.h
+++ b/include/linux/dax.h
@@ -12,6 +12,7 @@

typedef unsigned long dax_entry_t;

+struct iomap;
struct iomap_ops;
struct dax_device;
struct dax_operations {
@@ -226,13 +227,12 @@ int dax_file_range_compare(struct inode *src, loff_t srcoff,
const struct iomap_ops *ops);

#ifdef CONFIG_FS_DAX
-int __dax_zero_page_range(struct block_device *bdev,
- struct dax_device *dax_dev, sector_t sector,
- unsigned int offset, unsigned int length);
+int __dax_zero_page_range(struct iomap *iomap, struct iomap *srcmap, loff_t pos,
+ unsigned int offset, unsigned int size);
#else
-static inline int __dax_zero_page_range(struct block_device *bdev,
- struct dax_device *dax_dev, sector_t sector,
- unsigned int offset, unsigned int length)
+static inline int __dax_zero_page_range(struct iomap *iomap,
+ struct iomap *srcmap, loff_t pos,
+ unsigned int offset, unsigned int size)
{
return -ENXIO;
}
--
2.23.0