aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2016-09-18 21:30:29 -0400
committerDave Chinner <david@fromorbit.com>2016-09-18 21:30:29 -0400
commit25f4e70291a309749a93b30ffa58d2eac9f200f8 (patch)
tree0b8f01267a81cb947303b362b6073f126fe78f3a
parent6750ad71986d286a666e6245f160b89f4c15e7b0 (diff)
ext2: use iomap to implement DAX
Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Ross Zwisler <ross.zwisler@linux.intel.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
-rw-r--r--fs/ext2/Kconfig1
-rw-r--r--fs/ext2/ext2.h1
-rw-r--r--fs/ext2/file.c76
-rw-r--r--fs/ext2/inode.c63
4 files changed, 129 insertions, 12 deletions
diff --git a/fs/ext2/Kconfig b/fs/ext2/Kconfig
index c634874e12d9..36bea5adcaba 100644
--- a/fs/ext2/Kconfig
+++ b/fs/ext2/Kconfig
@@ -1,5 +1,6 @@
1config EXT2_FS 1config EXT2_FS
2 tristate "Second extended fs support" 2 tristate "Second extended fs support"
3 select FS_IOMAP if FS_DAX
3 help 4 help
4 Ext2 is a standard Linux file system for hard disks. 5 Ext2 is a standard Linux file system for hard disks.
5 6
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 06af2f92226c..37e2be784ac7 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -814,6 +814,7 @@ extern const struct file_operations ext2_file_operations;
814/* inode.c */ 814/* inode.c */
815extern const struct address_space_operations ext2_aops; 815extern const struct address_space_operations ext2_aops;
816extern const struct address_space_operations ext2_nobh_aops; 816extern const struct address_space_operations ext2_nobh_aops;
817extern struct iomap_ops ext2_iomap_ops;
817 818
818/* namei.c */ 819/* namei.c */
819extern const struct inode_operations ext2_dir_inode_operations; 820extern const struct inode_operations ext2_dir_inode_operations;
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 5efeefe17abb..423cc01c9d41 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -22,11 +22,59 @@
22#include <linux/pagemap.h> 22#include <linux/pagemap.h>
23#include <linux/dax.h> 23#include <linux/dax.h>
24#include <linux/quotaops.h> 24#include <linux/quotaops.h>
25#include <linux/iomap.h>
26#include <linux/uio.h>
25#include "ext2.h" 27#include "ext2.h"
26#include "xattr.h" 28#include "xattr.h"
27#include "acl.h" 29#include "acl.h"
28 30
29#ifdef CONFIG_FS_DAX 31#ifdef CONFIG_FS_DAX
32static ssize_t ext2_dax_read_iter(struct kiocb *iocb, struct iov_iter *to)
33{
34 struct inode *inode = iocb->ki_filp->f_mapping->host;
35 ssize_t ret;
36
37 if (!iov_iter_count(to))
38 return 0; /* skip atime */
39
40 inode_lock_shared(inode);
41 ret = iomap_dax_rw(iocb, to, &ext2_iomap_ops);
42 inode_unlock_shared(inode);
43
44 file_accessed(iocb->ki_filp);
45 return ret;
46}
47
48static ssize_t ext2_dax_write_iter(struct kiocb *iocb, struct iov_iter *from)
49{
50 struct file *file = iocb->ki_filp;
51 struct inode *inode = file->f_mapping->host;
52 ssize_t ret;
53
54 inode_lock(inode);
55 ret = generic_write_checks(iocb, from);
56 if (ret <= 0)
57 goto out_unlock;
58 ret = file_remove_privs(file);
59 if (ret)
60 goto out_unlock;
61 ret = file_update_time(file);
62 if (ret)
63 goto out_unlock;
64
65 ret = iomap_dax_rw(iocb, from, &ext2_iomap_ops);
66 if (ret > 0 && iocb->ki_pos > i_size_read(inode)) {
67 i_size_write(inode, iocb->ki_pos);
68 mark_inode_dirty(inode);
69 }
70
71out_unlock:
72 inode_unlock(inode);
73 if (ret > 0)
74 ret = generic_write_sync(iocb, ret);
75 return ret;
76}
77
30/* 78/*
31 * The lock ordering for ext2 DAX fault paths is: 79 * The lock ordering for ext2 DAX fault paths is:
32 * 80 *
@@ -51,7 +99,7 @@ static int ext2_dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
51 } 99 }
52 down_read(&ei->dax_sem); 100 down_read(&ei->dax_sem);
53 101
54 ret = dax_fault(vma, vmf, ext2_get_block); 102 ret = iomap_dax_fault(vma, vmf, &ext2_iomap_ops);
55 103
56 up_read(&ei->dax_sem); 104 up_read(&ei->dax_sem);
57 if (vmf->flags & FAULT_FLAG_WRITE) 105 if (vmf->flags & FAULT_FLAG_WRITE)
@@ -156,14 +204,28 @@ int ext2_fsync(struct file *file, loff_t start, loff_t end, int datasync)
156 return ret; 204 return ret;
157} 205}
158 206
159/* 207static ssize_t ext2_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
160 * We have mostly NULL's here: the current defaults are ok for 208{
161 * the ext2 filesystem. 209#ifdef CONFIG_FS_DAX
162 */ 210 if (IS_DAX(iocb->ki_filp->f_mapping->host))
211 return ext2_dax_read_iter(iocb, to);
212#endif
213 return generic_file_read_iter(iocb, to);
214}
215
216static ssize_t ext2_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
217{
218#ifdef CONFIG_FS_DAX
219 if (IS_DAX(iocb->ki_filp->f_mapping->host))
220 return ext2_dax_write_iter(iocb, from);
221#endif
222 return generic_file_write_iter(iocb, from);
223}
224
163const struct file_operations ext2_file_operations = { 225const struct file_operations ext2_file_operations = {
164 .llseek = generic_file_llseek, 226 .llseek = generic_file_llseek,
165 .read_iter = generic_file_read_iter, 227 .read_iter = ext2_file_read_iter,
166 .write_iter = generic_file_write_iter, 228 .write_iter = ext2_file_write_iter,
167 .unlocked_ioctl = ext2_ioctl, 229 .unlocked_ioctl = ext2_ioctl,
168#ifdef CONFIG_COMPAT 230#ifdef CONFIG_COMPAT
169 .compat_ioctl = ext2_compat_ioctl, 231 .compat_ioctl = ext2_compat_ioctl,
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 2a69ab2e7bb0..aae5f61f980b 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -32,6 +32,7 @@
32#include <linux/buffer_head.h> 32#include <linux/buffer_head.h>
33#include <linux/mpage.h> 33#include <linux/mpage.h>
34#include <linux/fiemap.h> 34#include <linux/fiemap.h>
35#include <linux/iomap.h>
35#include <linux/namei.h> 36#include <linux/namei.h>
36#include <linux/uio.h> 37#include <linux/uio.h>
37#include "ext2.h" 38#include "ext2.h"
@@ -787,6 +788,59 @@ int ext2_get_block(struct inode *inode, sector_t iblock,
787 788
788} 789}
789 790
791#ifdef CONFIG_FS_DAX
792static int ext2_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
793 unsigned flags, struct iomap *iomap)
794{
795 unsigned int blkbits = inode->i_blkbits;
796 unsigned long first_block = offset >> blkbits;
797 unsigned long max_blocks = (length + (1 << blkbits) - 1) >> blkbits;
798 bool new = false, boundary = false;
799 u32 bno;
800 int ret;
801
802 ret = ext2_get_blocks(inode, first_block, max_blocks,
803 &bno, &new, &boundary, flags & IOMAP_WRITE);
804 if (ret < 0)
805 return ret;
806
807 iomap->flags = 0;
808 iomap->bdev = inode->i_sb->s_bdev;
809 iomap->offset = first_block << blkbits;
810
811 if (ret == 0) {
812 iomap->type = IOMAP_HOLE;
813 iomap->blkno = IOMAP_NULL_BLOCK;
814 iomap->length = 1 << blkbits;
815 } else {
816 iomap->type = IOMAP_MAPPED;
817 iomap->blkno = (sector_t)bno << (blkbits - 9);
818 iomap->length = (u64)ret << blkbits;
819 iomap->flags |= IOMAP_F_MERGED;
820 }
821
822 if (new)
823 iomap->flags |= IOMAP_F_NEW;
824 return 0;
825}
826
827static int
828ext2_iomap_end(struct inode *inode, loff_t offset, loff_t length,
829 ssize_t written, unsigned flags, struct iomap *iomap)
830{
831 if (iomap->type == IOMAP_MAPPED &&
832 written < length &&
833 (flags & IOMAP_WRITE))
834 ext2_write_failed(inode->i_mapping, offset + length);
835 return 0;
836}
837
838struct iomap_ops ext2_iomap_ops = {
839 .iomap_begin = ext2_iomap_begin,
840 .iomap_end = ext2_iomap_end,
841};
842#endif /* CONFIG_FS_DAX */
843
790int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, 844int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
791 u64 start, u64 len) 845 u64 start, u64 len)
792{ 846{
@@ -872,11 +926,10 @@ ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
872 loff_t offset = iocb->ki_pos; 926 loff_t offset = iocb->ki_pos;
873 ssize_t ret; 927 ssize_t ret;
874 928
875 if (IS_DAX(inode)) 929 if (WARN_ON_ONCE(IS_DAX(inode)))
876 ret = dax_do_io(iocb, inode, iter, ext2_get_block, NULL, 930 return -EIO;
877 DIO_LOCKING); 931
878 else 932 ret = blockdev_direct_IO(iocb, inode, iter, ext2_get_block);
879 ret = blockdev_direct_IO(iocb, inode, iter, ext2_get_block);
880 if (ret < 0 && iov_iter_rw(iter) == WRITE) 933 if (ret < 0 && iov_iter_rw(iter) == WRITE)
881 ext2_write_failed(mapping, offset + count); 934 ext2_write_failed(mapping, offset + count);
882 return ret; 935 return ret;