Skip to content

Commit fb094c9

Browse files
committed
ext2, dax: introduce ext2_dax_aops
In preparation for the dax implementation to start associating dax pages to inodes via page->mapping, we need to provide a 'struct address_space_operations' instance for dax. Otherwise, direct-I/O triggers incorrect page cache assumptions and warnings. Reviewed-by: Jan Kara <jack@suse.com> Reported-by: kbuild test robot <lkp@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent 5f0663b commit fb094c9

File tree

3 files changed

+30
-35
lines changed

3 files changed

+30
-35
lines changed

fs/ext2/ext2.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,7 @@ extern const struct inode_operations ext2_file_inode_operations;
814814
extern const struct file_operations ext2_file_operations;
815815

816816
/* inode.c */
817+
extern void ext2_set_file_ops(struct inode *inode);
817818
extern const struct address_space_operations ext2_aops;
818819
extern const struct address_space_operations ext2_nobh_aops;
819820
extern const struct iomap_ops ext2_iomap_ops;

fs/ext2/inode.c

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -940,9 +940,6 @@ ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
940940
loff_t offset = iocb->ki_pos;
941941
ssize_t ret;
942942

943-
if (WARN_ON_ONCE(IS_DAX(inode)))
944-
return -EIO;
945-
946943
ret = blockdev_direct_IO(iocb, inode, iter, ext2_get_block);
947944
if (ret < 0 && iov_iter_rw(iter) == WRITE)
948945
ext2_write_failed(mapping, offset + count);
@@ -952,17 +949,16 @@ ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
952949
static int
953950
ext2_writepages(struct address_space *mapping, struct writeback_control *wbc)
954951
{
955-
#ifdef CONFIG_FS_DAX
956-
if (dax_mapping(mapping)) {
957-
return dax_writeback_mapping_range(mapping,
958-
mapping->host->i_sb->s_bdev,
959-
wbc);
960-
}
961-
#endif
962-
963952
return mpage_writepages(mapping, wbc, ext2_get_block);
964953
}
965954

955+
static int
956+
ext2_dax_writepages(struct address_space *mapping, struct writeback_control *wbc)
957+
{
958+
return dax_writeback_mapping_range(mapping,
959+
mapping->host->i_sb->s_bdev, wbc);
960+
}
961+
966962
const struct address_space_operations ext2_aops = {
967963
.readpage = ext2_readpage,
968964
.readpages = ext2_readpages,
@@ -990,6 +986,13 @@ const struct address_space_operations ext2_nobh_aops = {
990986
.error_remove_page = generic_error_remove_page,
991987
};
992988

989+
static const struct address_space_operations ext2_dax_aops = {
990+
.writepages = ext2_dax_writepages,
991+
.direct_IO = noop_direct_IO,
992+
.set_page_dirty = noop_set_page_dirty,
993+
.invalidatepage = noop_invalidatepage,
994+
};
995+
993996
/*
994997
* Probably it should be a library function... search for first non-zero word
995998
* or memcmp with zero_page, whatever is better for particular architecture.
@@ -1388,6 +1391,18 @@ void ext2_set_inode_flags(struct inode *inode)
13881391
inode->i_flags |= S_DAX;
13891392
}
13901393

1394+
void ext2_set_file_ops(struct inode *inode)
1395+
{
1396+
inode->i_op = &ext2_file_inode_operations;
1397+
inode->i_fop = &ext2_file_operations;
1398+
if (IS_DAX(inode))
1399+
inode->i_mapping->a_ops = &ext2_dax_aops;
1400+
else if (test_opt(inode->i_sb, NOBH))
1401+
inode->i_mapping->a_ops = &ext2_nobh_aops;
1402+
else
1403+
inode->i_mapping->a_ops = &ext2_aops;
1404+
}
1405+
13911406
struct inode *ext2_iget (struct super_block *sb, unsigned long ino)
13921407
{
13931408
struct ext2_inode_info *ei;
@@ -1480,14 +1495,7 @@ struct inode *ext2_iget (struct super_block *sb, unsigned long ino)
14801495
ei->i_data[n] = raw_inode->i_block[n];
14811496

14821497
if (S_ISREG(inode->i_mode)) {
1483-
inode->i_op = &ext2_file_inode_operations;
1484-
if (test_opt(inode->i_sb, NOBH)) {
1485-
inode->i_mapping->a_ops = &ext2_nobh_aops;
1486-
inode->i_fop = &ext2_file_operations;
1487-
} else {
1488-
inode->i_mapping->a_ops = &ext2_aops;
1489-
inode->i_fop = &ext2_file_operations;
1490-
}
1498+
ext2_set_file_ops(inode);
14911499
} else if (S_ISDIR(inode->i_mode)) {
14921500
inode->i_op = &ext2_dir_inode_operations;
14931501
inode->i_fop = &ext2_dir_operations;

fs/ext2/namei.c

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,7 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, umode_t mode
107107
if (IS_ERR(inode))
108108
return PTR_ERR(inode);
109109

110-
inode->i_op = &ext2_file_inode_operations;
111-
if (test_opt(inode->i_sb, NOBH)) {
112-
inode->i_mapping->a_ops = &ext2_nobh_aops;
113-
inode->i_fop = &ext2_file_operations;
114-
} else {
115-
inode->i_mapping->a_ops = &ext2_aops;
116-
inode->i_fop = &ext2_file_operations;
117-
}
110+
ext2_set_file_ops(inode);
118111
mark_inode_dirty(inode);
119112
return ext2_add_nondir(dentry, inode);
120113
}
@@ -125,14 +118,7 @@ static int ext2_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
125118
if (IS_ERR(inode))
126119
return PTR_ERR(inode);
127120

128-
inode->i_op = &ext2_file_inode_operations;
129-
if (test_opt(inode->i_sb, NOBH)) {
130-
inode->i_mapping->a_ops = &ext2_nobh_aops;
131-
inode->i_fop = &ext2_file_operations;
132-
} else {
133-
inode->i_mapping->a_ops = &ext2_aops;
134-
inode->i_fop = &ext2_file_operations;
135-
}
121+
ext2_set_file_ops(inode);
136122
mark_inode_dirty(inode);
137123
d_tmpfile(dentry, inode);
138124
unlock_new_inode(inode);

0 commit comments

Comments
 (0)