@@ -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);
@@ -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);
@@ -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;
}