add patch add-ext4_should_use_dax
[ext4-patch-queue.git] / add-iomap-support-for-inline-data
blob46cb5cd9bd2618fd38634cc42e52147d09151f86
1 ext4: Add iomap support for inline data
3 From: Andreas Gruenbacher <agruenba@redhat.com>
5 Report inline data as a IOMAP_F_DATA_INLINE mapping.  This allows to use
6 iomap_seek_hole and iomap_seek_data in ext4_llseek and makes switching
7 to iomap_fiemap in ext4_fiemap easier.
9 Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
10 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
11 Reviewed-by: Jan Kara <jack@suse.cz>
12 ---
13  fs/ext4/ext4.h   |  4 ++++
14  fs/ext4/inline.c | 33 +++++++++++++++++++++++++++++++++
15  fs/ext4/inode.c  | 16 ++++++++++++++--
16  3 files changed, 51 insertions(+), 2 deletions(-)
18 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
19 index e2abe01c8c6b..ae3e4a25821a 100644
20 --- a/fs/ext4/ext4.h
21 +++ b/fs/ext4/ext4.h
22 @@ -3048,6 +3048,10 @@ extern struct buffer_head *ext4_get_first_inline_block(struct inode *inode,
23  extern int ext4_inline_data_fiemap(struct inode *inode,
24                                    struct fiemap_extent_info *fieinfo,
25                                    int *has_inline, __u64 start, __u64 len);
27 +struct iomap;
28 +extern int ext4_inline_data_iomap(struct inode *inode, struct iomap *iomap);
30  extern int ext4_try_to_evict_inline_data(handle_t *handle,
31                                          struct inode *inode,
32                                          int needed);
33 diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
34 index 28c5c3abddb3..f0bbc8cb6555 100644
35 --- a/fs/ext4/inline.c
36 +++ b/fs/ext4/inline.c
37 @@ -12,6 +12,7 @@
38   * GNU General Public License for more details.
39   */
41 +#include <linux/iomap.h>
42  #include <linux/fiemap.h>
44  #include "ext4_jbd2.h"
45 @@ -1827,6 +1828,38 @@ int ext4_destroy_inline_data(handle_t *handle, struct inode *inode)
46         return ret;
47  }
49 +int ext4_inline_data_iomap(struct inode *inode, struct iomap *iomap)
51 +       __u64 addr;
52 +       int error = -EAGAIN;
53 +       struct ext4_iloc iloc;
55 +       down_read(&EXT4_I(inode)->xattr_sem);
56 +       if (!ext4_has_inline_data(inode))
57 +               goto out;
59 +       error = ext4_get_inode_loc(inode, &iloc);
60 +       if (error)
61 +               goto out;
63 +       addr = (__u64)iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits;
64 +       addr += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data;
65 +       addr += offsetof(struct ext4_inode, i_block);
67 +       brelse(iloc.bh);
69 +       iomap->addr = addr;
70 +       iomap->offset = 0;
71 +       iomap->length = min_t(loff_t, ext4_get_inline_size(inode),
72 +                             i_size_read(inode));
73 +       iomap->type = 0;
74 +       iomap->flags = IOMAP_F_DATA_INLINE;
76 +out:
77 +       up_read(&EXT4_I(inode)->xattr_sem);
78 +       return error;
81  int ext4_inline_data_fiemap(struct inode *inode,
82                             struct fiemap_extent_info *fieinfo,
83                             int *has_inline, __u64 start, __u64 len)
84 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
85 index d9e633c12aae..7755f41bdfc3 100644
86 --- a/fs/ext4/inode.c
87 +++ b/fs/ext4/inode.c
88 @@ -3404,8 +3404,20 @@ static int ext4_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
89         struct ext4_map_blocks map;
90         int ret;
92 -       if (WARN_ON_ONCE(ext4_has_inline_data(inode)))
93 -               return -ERANGE;
95 +       if (flags & IOMAP_REPORT) {
96 +               if (ext4_has_inline_data(inode)) {
97 +                       ret = ext4_inline_data_iomap(inode, iomap);
98 +                       if (ret != -EAGAIN) {
99 +                               if (ret == 0 && offset >= iomap->length)
100 +                                       ret = -ENOENT;
101 +                               return ret;
102 +                       }
103 +               }
104 +       } else {
105 +               if (WARN_ON_ONCE(ext4_has_inline_data(inode)))
106 +                       return -ERANGE;
107 +       }
109         map.m_lblk = first_block;
110         map.m_len = last_block - first_block + 1;
111 -- 
112 2.13.3