|
@@ -940,9 +940,6 @@ ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
|
|
|
loff_t offset = iocb->ki_pos;
|
|
|
ssize_t ret;
|
|
|
|
|
|
- if (WARN_ON_ONCE(IS_DAX(inode)))
|
|
|
- return -EIO;
|
|
|
-
|
|
|
ret = blockdev_direct_IO(iocb, inode, iter, ext2_get_block);
|
|
|
if (ret < 0 && iov_iter_rw(iter) == WRITE)
|
|
|
ext2_write_failed(mapping, offset + count);
|
|
@@ -952,17 +949,16 @@ ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
|
|
|
static int
|
|
|
ext2_writepages(struct address_space *mapping, struct writeback_control *wbc)
|
|
|
{
|
|
|
-#ifdef CONFIG_FS_DAX
|
|
|
- if (dax_mapping(mapping)) {
|
|
|
- return dax_writeback_mapping_range(mapping,
|
|
|
- mapping->host->i_sb->s_bdev,
|
|
|
- wbc);
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
return mpage_writepages(mapping, wbc, ext2_get_block);
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+ext2_dax_writepages(struct address_space *mapping, struct writeback_control *wbc)
|
|
|
+{
|
|
|
+ return dax_writeback_mapping_range(mapping,
|
|
|
+ mapping->host->i_sb->s_bdev, wbc);
|
|
|
+}
|
|
|
+
|
|
|
const struct address_space_operations ext2_aops = {
|
|
|
.readpage = ext2_readpage,
|
|
|
.readpages = ext2_readpages,
|
|
@@ -990,6 +986,13 @@ const struct address_space_operations ext2_nobh_aops = {
|
|
|
.error_remove_page = generic_error_remove_page,
|
|
|
};
|
|
|
|
|
|
+static const struct address_space_operations ext2_dax_aops = {
|
|
|
+ .writepages = ext2_dax_writepages,
|
|
|
+ .direct_IO = noop_direct_IO,
|
|
|
+ .set_page_dirty = noop_set_page_dirty,
|
|
|
+ .invalidatepage = noop_invalidatepage,
|
|
|
+};
|
|
|
+
|
|
|
/*
|
|
|
* Probably it should be a library function... search for first non-zero word
|
|
|
* or memcmp with zero_page, whatever is better for particular architecture.
|
|
@@ -1388,6 +1391,18 @@ void ext2_set_inode_flags(struct inode *inode)
|
|
|
inode->i_flags |= S_DAX;
|
|
|
}
|
|
|
|
|
|
+void ext2_set_file_ops(struct inode *inode)
|
|
|
+{
|
|
|
+ inode->i_op = &ext2_file_inode_operations;
|
|
|
+ inode->i_fop = &ext2_file_operations;
|
|
|
+ if (IS_DAX(inode))
|
|
|
+ inode->i_mapping->a_ops = &ext2_dax_aops;
|
|
|
+ else if (test_opt(inode->i_sb, NOBH))
|
|
|
+ inode->i_mapping->a_ops = &ext2_nobh_aops;
|
|
|
+ else
|
|
|
+ inode->i_mapping->a_ops = &ext2_aops;
|
|
|
+}
|
|
|
+
|
|
|
struct inode *ext2_iget (struct super_block *sb, unsigned long ino)
|
|
|
{
|
|
|
struct ext2_inode_info *ei;
|
|
@@ -1480,14 +1495,7 @@ struct inode *ext2_iget (struct super_block *sb, unsigned long ino)
|
|
|
ei->i_data[n] = raw_inode->i_block[n];
|
|
|
|
|
|
if (S_ISREG(inode->i_mode)) {
|
|
|
- inode->i_op = &ext2_file_inode_operations;
|
|
|
- if (test_opt(inode->i_sb, NOBH)) {
|
|
|
- inode->i_mapping->a_ops = &ext2_nobh_aops;
|
|
|
- inode->i_fop = &ext2_file_operations;
|
|
|
- } else {
|
|
|
- inode->i_mapping->a_ops = &ext2_aops;
|
|
|
- inode->i_fop = &ext2_file_operations;
|
|
|
- }
|
|
|
+ ext2_set_file_ops(inode);
|
|
|
} else if (S_ISDIR(inode->i_mode)) {
|
|
|
inode->i_op = &ext2_dir_inode_operations;
|
|
|
inode->i_fop = &ext2_dir_operations;
|