diff options
author | Dan Williams <dan.j.williams@intel.com> | 2017-12-21 15:25:11 -0500 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2018-04-03 08:41:05 -0400 |
commit | fb094c90748fbeba1063927eeb751add147b35b9 (patch) | |
tree | 332b11f81eb36df6ca73a11d00b1f3f2a2928e8d | |
parent | 5f0663bb4a64f588f0a2dd6d1be68d40f9af0086 (diff) |
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>
-rw-r--r-- | fs/ext2/ext2.h | 1 | ||||
-rw-r--r-- | fs/ext2/inode.c | 46 | ||||
-rw-r--r-- | fs/ext2/namei.c | 18 |
3 files changed, 30 insertions, 35 deletions
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 032295e1d386..cc40802ddfa8 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h | |||
@@ -814,6 +814,7 @@ extern const struct inode_operations ext2_file_inode_operations; | |||
814 | extern const struct file_operations ext2_file_operations; | 814 | extern const struct file_operations ext2_file_operations; |
815 | 815 | ||
816 | /* inode.c */ | 816 | /* inode.c */ |
817 | extern void ext2_set_file_ops(struct inode *inode); | ||
817 | extern const struct address_space_operations ext2_aops; | 818 | extern const struct address_space_operations ext2_aops; |
818 | extern const struct address_space_operations ext2_nobh_aops; | 819 | extern const struct address_space_operations ext2_nobh_aops; |
819 | extern const struct iomap_ops ext2_iomap_ops; | 820 | extern const struct iomap_ops ext2_iomap_ops; |
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 9b2ac55ac34f..1e01fabef130 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c | |||
@@ -940,9 +940,6 @@ ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter) | |||
940 | loff_t offset = iocb->ki_pos; | 940 | loff_t offset = iocb->ki_pos; |
941 | ssize_t ret; | 941 | ssize_t ret; |
942 | 942 | ||
943 | if (WARN_ON_ONCE(IS_DAX(inode))) | ||
944 | return -EIO; | ||
945 | |||
946 | ret = blockdev_direct_IO(iocb, inode, iter, ext2_get_block); | 943 | ret = blockdev_direct_IO(iocb, inode, iter, ext2_get_block); |
947 | if (ret < 0 && iov_iter_rw(iter) == WRITE) | 944 | if (ret < 0 && iov_iter_rw(iter) == WRITE) |
948 | ext2_write_failed(mapping, offset + count); | 945 | ext2_write_failed(mapping, offset + count); |
@@ -952,17 +949,16 @@ ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter) | |||
952 | static int | 949 | static int |
953 | ext2_writepages(struct address_space *mapping, struct writeback_control *wbc) | 950 | ext2_writepages(struct address_space *mapping, struct writeback_control *wbc) |
954 | { | 951 | { |
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 | |||
963 | return mpage_writepages(mapping, wbc, ext2_get_block); | 952 | return mpage_writepages(mapping, wbc, ext2_get_block); |
964 | } | 953 | } |
965 | 954 | ||
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 | |||
966 | const struct address_space_operations ext2_aops = { | 962 | const struct address_space_operations ext2_aops = { |
967 | .readpage = ext2_readpage, | 963 | .readpage = ext2_readpage, |
968 | .readpages = ext2_readpages, | 964 | .readpages = ext2_readpages, |
@@ -990,6 +986,13 @@ const struct address_space_operations ext2_nobh_aops = { | |||
990 | .error_remove_page = generic_error_remove_page, | 986 | .error_remove_page = generic_error_remove_page, |
991 | }; | 987 | }; |
992 | 988 | ||
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 | |||
993 | /* | 996 | /* |
994 | * Probably it should be a library function... search for first non-zero word | 997 | * Probably it should be a library function... search for first non-zero word |
995 | * or memcmp with zero_page, whatever is better for particular architecture. | 998 | * or memcmp with zero_page, whatever is better for particular architecture. |
@@ -1388,6 +1391,18 @@ void ext2_set_inode_flags(struct inode *inode) | |||
1388 | inode->i_flags |= S_DAX; | 1391 | inode->i_flags |= S_DAX; |
1389 | } | 1392 | } |
1390 | 1393 | ||
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 | |||
1391 | struct inode *ext2_iget (struct super_block *sb, unsigned long ino) | 1406 | struct inode *ext2_iget (struct super_block *sb, unsigned long ino) |
1392 | { | 1407 | { |
1393 | struct ext2_inode_info *ei; | 1408 | struct ext2_inode_info *ei; |
@@ -1480,14 +1495,7 @@ struct inode *ext2_iget (struct super_block *sb, unsigned long ino) | |||
1480 | ei->i_data[n] = raw_inode->i_block[n]; | 1495 | ei->i_data[n] = raw_inode->i_block[n]; |
1481 | 1496 | ||
1482 | if (S_ISREG(inode->i_mode)) { | 1497 | if (S_ISREG(inode->i_mode)) { |
1483 | inode->i_op = &ext2_file_inode_operations; | 1498 | ext2_set_file_ops(inode); |
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 | } | ||
1491 | } else if (S_ISDIR(inode->i_mode)) { | 1499 | } else if (S_ISDIR(inode->i_mode)) { |
1492 | inode->i_op = &ext2_dir_inode_operations; | 1500 | inode->i_op = &ext2_dir_inode_operations; |
1493 | inode->i_fop = &ext2_dir_operations; | 1501 | inode->i_fop = &ext2_dir_operations; |
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index e078075dc66f..55f7caadb093 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c | |||
@@ -107,14 +107,7 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, umode_t mode | |||
107 | if (IS_ERR(inode)) | 107 | if (IS_ERR(inode)) |
108 | return PTR_ERR(inode); | 108 | return PTR_ERR(inode); |
109 | 109 | ||
110 | inode->i_op = &ext2_file_inode_operations; | 110 | ext2_set_file_ops(inode); |
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 | } | ||
118 | mark_inode_dirty(inode); | 111 | mark_inode_dirty(inode); |
119 | return ext2_add_nondir(dentry, inode); | 112 | return ext2_add_nondir(dentry, inode); |
120 | } | 113 | } |
@@ -125,14 +118,7 @@ static int ext2_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
125 | if (IS_ERR(inode)) | 118 | if (IS_ERR(inode)) |
126 | return PTR_ERR(inode); | 119 | return PTR_ERR(inode); |
127 | 120 | ||
128 | inode->i_op = &ext2_file_inode_operations; | 121 | ext2_set_file_ops(inode); |
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 | } | ||
136 | mark_inode_dirty(inode); | 122 | mark_inode_dirty(inode); |
137 | d_tmpfile(dentry, inode); | 123 | d_tmpfile(dentry, inode); |
138 | unlock_new_inode(inode); | 124 | unlock_new_inode(inode); |