Skip to content

Commit c6f4046

Browse files
Christoph Hellwigdjbw
authored andcommitted
fsdax: decouple zeroing from the iomap buffered I/O code
Unshare the DAX and iomap buffered I/O page zeroing code. This code previously did a IS_DAX check deep inside the iomap code, which in fact was the only DAX check in the code. Instead move these checks into the callers. Most callers already have DAX special casing anyway and XFS will need it for reflink support as well. Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Dan Williams <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dan Williams <[email protected]>
1 parent e5c7195 commit c6f4046

File tree

6 files changed

+94
-44
lines changed

6 files changed

+94
-44
lines changed

fs/dax.c

Lines changed: 63 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,24 +1135,73 @@ static int dax_memzero(struct dax_device *dax_dev, pgoff_t pgoff,
11351135
return ret;
11361136
}
11371137

1138-
s64 dax_iomap_zero(loff_t pos, u64 length, struct iomap *iomap)
1138+
static s64 dax_zero_iter(struct iomap_iter *iter, bool *did_zero)
11391139
{
1140-
pgoff_t pgoff = dax_iomap_pgoff(iomap, pos);
1141-
long rc, id;
1142-
unsigned offset = offset_in_page(pos);
1143-
unsigned size = min_t(u64, PAGE_SIZE - offset, length);
1140+
const struct iomap *iomap = &iter->iomap;
1141+
const struct iomap *srcmap = iomap_iter_srcmap(iter);
1142+
loff_t pos = iter->pos;
1143+
u64 length = iomap_length(iter);
1144+
s64 written = 0;
1145+
1146+
/* already zeroed? we're done. */
1147+
if (srcmap->type == IOMAP_HOLE || srcmap->type == IOMAP_UNWRITTEN)
1148+
return length;
1149+
1150+
do {
1151+
unsigned offset = offset_in_page(pos);
1152+
unsigned size = min_t(u64, PAGE_SIZE - offset, length);
1153+
pgoff_t pgoff = dax_iomap_pgoff(iomap, pos);
1154+
long rc;
1155+
int id;
11441156

1145-
id = dax_read_lock();
1146-
if (IS_ALIGNED(pos, PAGE_SIZE) && size == PAGE_SIZE)
1147-
rc = dax_zero_page_range(iomap->dax_dev, pgoff, 1);
1148-
else
1149-
rc = dax_memzero(iomap->dax_dev, pgoff, offset, size);
1150-
dax_read_unlock(id);
1157+
id = dax_read_lock();
1158+
if (IS_ALIGNED(pos, PAGE_SIZE) && size == PAGE_SIZE)
1159+
rc = dax_zero_page_range(iomap->dax_dev, pgoff, 1);
1160+
else
1161+
rc = dax_memzero(iomap->dax_dev, pgoff, offset, size);
1162+
dax_read_unlock(id);
11511163

1152-
if (rc < 0)
1153-
return rc;
1154-
return size;
1164+
if (rc < 0)
1165+
return rc;
1166+
pos += size;
1167+
length -= size;
1168+
written += size;
1169+
if (did_zero)
1170+
*did_zero = true;
1171+
} while (length > 0);
1172+
1173+
return written;
1174+
}
1175+
1176+
int dax_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero,
1177+
const struct iomap_ops *ops)
1178+
{
1179+
struct iomap_iter iter = {
1180+
.inode = inode,
1181+
.pos = pos,
1182+
.len = len,
1183+
.flags = IOMAP_ZERO,
1184+
};
1185+
int ret;
1186+
1187+
while ((ret = iomap_iter(&iter, ops)) > 0)
1188+
iter.processed = dax_zero_iter(&iter, did_zero);
1189+
return ret;
1190+
}
1191+
EXPORT_SYMBOL_GPL(dax_zero_range);
1192+
1193+
int dax_truncate_page(struct inode *inode, loff_t pos, bool *did_zero,
1194+
const struct iomap_ops *ops)
1195+
{
1196+
unsigned int blocksize = i_blocksize(inode);
1197+
unsigned int off = pos & (blocksize - 1);
1198+
1199+
/* Block boundary? Nothing to do */
1200+
if (!off)
1201+
return 0;
1202+
return dax_zero_range(inode, pos, blocksize - off, did_zero, ops);
11551203
}
1204+
EXPORT_SYMBOL_GPL(dax_truncate_page);
11561205

11571206
static loff_t dax_iomap_iter(const struct iomap_iter *iomi,
11581207
struct iov_iter *iter)

fs/ext2/inode.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <linux/iomap.h>
3737
#include <linux/namei.h>
3838
#include <linux/uio.h>
39+
#include <linux/dax.h>
3940
#include "ext2.h"
4041
#include "acl.h"
4142
#include "xattr.h"
@@ -1297,9 +1298,9 @@ static int ext2_setsize(struct inode *inode, loff_t newsize)
12971298
inode_dio_wait(inode);
12981299

12991300
if (IS_DAX(inode)) {
1300-
error = iomap_zero_range(inode, newsize,
1301-
PAGE_ALIGN(newsize) - newsize, NULL,
1302-
&ext2_iomap_ops);
1301+
error = dax_zero_range(inode, newsize,
1302+
PAGE_ALIGN(newsize) - newsize, NULL,
1303+
&ext2_iomap_ops);
13031304
} else if (test_opt(inode->i_sb, NOBH))
13041305
error = nobh_truncate_page(inode->i_mapping,
13051306
newsize, ext2_get_block);

fs/ext4/inode.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <linux/bitops.h>
4242
#include <linux/iomap.h>
4343
#include <linux/iversion.h>
44+
#include <linux/dax.h>
4445

4546
#include "ext4_jbd2.h"
4647
#include "xattr.h"
@@ -3780,8 +3781,8 @@ static int ext4_block_zero_page_range(handle_t *handle,
37803781
length = max;
37813782

37823783
if (IS_DAX(inode)) {
3783-
return iomap_zero_range(inode, from, length, NULL,
3784-
&ext4_iomap_ops);
3784+
return dax_zero_range(inode, from, length, NULL,
3785+
&ext4_iomap_ops);
37853786
}
37863787
return __ext4_block_zero_page_range(handle, mapping, from, length);
37873788
}

fs/iomap/buffered-io.c

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -870,26 +870,8 @@ iomap_file_unshare(struct inode *inode, loff_t pos, loff_t len,
870870
}
871871
EXPORT_SYMBOL_GPL(iomap_file_unshare);
872872

873-
static s64 __iomap_zero_iter(struct iomap_iter *iter, loff_t pos, u64 length)
874-
{
875-
struct page *page;
876-
int status;
877-
unsigned offset = offset_in_page(pos);
878-
unsigned bytes = min_t(u64, PAGE_SIZE - offset, length);
879-
880-
status = iomap_write_begin(iter, pos, bytes, &page);
881-
if (status)
882-
return status;
883-
884-
zero_user(page, offset, bytes);
885-
mark_page_accessed(page);
886-
887-
return iomap_write_end(iter, pos, bytes, bytes, page);
888-
}
889-
890873
static loff_t iomap_zero_iter(struct iomap_iter *iter, bool *did_zero)
891874
{
892-
struct iomap *iomap = &iter->iomap;
893875
const struct iomap *srcmap = iomap_iter_srcmap(iter);
894876
loff_t pos = iter->pos;
895877
loff_t length = iomap_length(iter);
@@ -900,12 +882,19 @@ static loff_t iomap_zero_iter(struct iomap_iter *iter, bool *did_zero)
900882
return length;
901883

902884
do {
903-
s64 bytes;
885+
unsigned offset = offset_in_page(pos);
886+
size_t bytes = min_t(u64, PAGE_SIZE - offset, length);
887+
struct page *page;
888+
int status;
904889

905-
if (IS_DAX(iter->inode))
906-
bytes = dax_iomap_zero(pos, length, iomap);
907-
else
908-
bytes = __iomap_zero_iter(iter, pos, length);
890+
status = iomap_write_begin(iter, pos, bytes, &page);
891+
if (status)
892+
return status;
893+
894+
zero_user(page, offset, bytes);
895+
mark_page_accessed(page);
896+
897+
bytes = iomap_write_end(iter, pos, bytes, bytes, page);
909898
if (bytes < 0)
910899
return bytes;
911900

fs/xfs/xfs_iomap.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
#include "xfs_dquot.h"
2929
#include "xfs_reflink.h"
3030

31-
3231
#define XFS_ALLOC_ALIGN(mp, off) \
3332
(((off) >> mp->m_allocsize_log) << mp->m_allocsize_log)
3433

@@ -1321,6 +1320,9 @@ xfs_zero_range(
13211320
{
13221321
struct inode *inode = VFS_I(ip);
13231322

1323+
if (IS_DAX(inode))
1324+
return dax_zero_range(inode, pos, len, did_zero,
1325+
&xfs_buffered_write_iomap_ops);
13241326
return iomap_zero_range(inode, pos, len, did_zero,
13251327
&xfs_buffered_write_iomap_ops);
13261328
}
@@ -1333,6 +1335,9 @@ xfs_truncate_page(
13331335
{
13341336
struct inode *inode = VFS_I(ip);
13351337

1338+
if (IS_DAX(inode))
1339+
return dax_truncate_page(inode, pos, did_zero,
1340+
&xfs_buffered_write_iomap_ops);
13361341
return iomap_truncate_page(inode, pos, did_zero,
13371342
&xfs_buffered_write_iomap_ops);
13381343
}

include/linux/dax.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ typedef unsigned long dax_entry_t;
1414
struct dax_device;
1515
struct gendisk;
1616
struct iomap_ops;
17+
struct iomap_iter;
1718
struct iomap;
1819

1920
struct dax_operations {
@@ -170,6 +171,11 @@ static inline void dax_unlock_page(struct page *page, dax_entry_t cookie)
170171
}
171172
#endif
172173

174+
int dax_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero,
175+
const struct iomap_ops *ops);
176+
int dax_truncate_page(struct inode *inode, loff_t pos, bool *did_zero,
177+
const struct iomap_ops *ops);
178+
173179
#if IS_ENABLED(CONFIG_DAX)
174180
int dax_read_lock(void);
175181
void dax_read_unlock(int id);
@@ -204,7 +210,6 @@ vm_fault_t dax_finish_sync_fault(struct vm_fault *vmf,
204210
int dax_delete_mapping_entry(struct address_space *mapping, pgoff_t index);
205211
int dax_invalidate_mapping_entry_sync(struct address_space *mapping,
206212
pgoff_t index);
207-
s64 dax_iomap_zero(loff_t pos, u64 length, struct iomap *iomap);
208213
static inline bool dax_mapping(struct address_space *mapping)
209214
{
210215
return mapping->host && IS_DAX(mapping->host);

0 commit comments

Comments
 (0)