add patch fix-mmp-use-after-free-during-umount
[ext4-patch-queue.git] / let-S_DAX-set-only-if-DAX-is-really-supported
blob9fd221d66c9df23415250205064026f729217a88
1 ext4: only set S_DAX if DAX is really supported
3 From: Jan Kara <jack@suse.cz>
5 Currently we have S_DAX set inode->i_flags for a regular file whenever
6 ext4 is mounted with dax mount option. However in some cases we cannot
7 really do DAX - e.g. when inode is marked to use data journalling, when
8 inode data is being encrypted, or when inode is stored inline. Make sure
9 S_DAX flag is appropriately set/cleared in these cases.
11 Reviewed-by: Ross Zwisler <ross.zwisler@linux.intel.com>
12 Signed-off-by: Jan Kara <jack@suse.cz>
13 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
14 ---
15  fs/ext4/inline.c | 10 ++++++++++
16  fs/ext4/inode.c  |  9 ++++++++-
17  fs/ext4/super.c  |  6 ++++++
18  3 files changed, 24 insertions(+), 1 deletion(-)
20 diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
21 index f74d5ee2cdec..c29678965c3c 100644
22 --- a/fs/ext4/inline.c
23 +++ b/fs/ext4/inline.c
24 @@ -299,6 +299,11 @@ static int ext4_create_inline_data(handle_t *handle,
25         EXT4_I(inode)->i_inline_size = len + EXT4_MIN_INLINE_DATA_SIZE;
26         ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS);
27         ext4_set_inode_flag(inode, EXT4_INODE_INLINE_DATA);
28 +       /*
29 +        * Propagate changes to inode->i_flags as well - e.g. S_DAX may
30 +        * get cleared
31 +        */
32 +       ext4_set_inode_flags(inode);
33         get_bh(is.iloc.bh);
34         error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
36 @@ -442,6 +447,11 @@ static int ext4_destroy_inline_data_nolock(handle_t *handle,
37                 }
38         }
39         ext4_clear_inode_flag(inode, EXT4_INODE_INLINE_DATA);
40 +       /*
41 +        * Propagate changes to inode->i_flags as well - e.g. S_DAX may
42 +        * get set.
43 +        */
44 +       ext4_set_inode_flags(inode);
46         get_bh(is.iloc.bh);
47         error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
48 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
49 index 3d58b2b477e8..5337828c68a7 100644
50 --- a/fs/ext4/inode.c
51 +++ b/fs/ext4/inode.c
52 @@ -4355,7 +4355,9 @@ void ext4_set_inode_flags(struct inode *inode)
53                 new_fl |= S_NOATIME;
54         if (flags & EXT4_DIRSYNC_FL)
55                 new_fl |= S_DIRSYNC;
56 -       if (test_opt(inode->i_sb, DAX) && S_ISREG(inode->i_mode))
57 +       if (test_opt(inode->i_sb, DAX) && S_ISREG(inode->i_mode) &&
58 +           !ext4_should_journal_data(inode) && !ext4_has_inline_data(inode) &&
59 +           !ext4_encrypted_inode(inode))
60                 new_fl |= S_DAX;
61         inode_set_flags(inode, new_fl,
62                         S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_DAX);
63 @@ -5623,6 +5625,11 @@ int ext4_change_inode_journal_flag(struct inode *inode, int val)
64                 ext4_clear_inode_flag(inode, EXT4_INODE_JOURNAL_DATA);
65         }
66         ext4_set_aops(inode);
67 +       /*
68 +        * Update inode->i_flags after EXT4_INODE_JOURNAL_DATA was updated.
69 +        * E.g. S_DAX may get cleared / set.
70 +        */
71 +       ext4_set_inode_flags(inode);
73         jbd2_journal_unlock_updates(journal);
74         percpu_up_write(&sbi->s_journal_flag_rwsem);
75 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
76 index 20da99da0a34..d5b94cc6a74e 100644
77 --- a/fs/ext4/super.c
78 +++ b/fs/ext4/super.c
79 @@ -1126,6 +1126,10 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
80                         ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
81                         ext4_clear_inode_state(inode,
82                                         EXT4_STATE_MAY_INLINE_DATA);
83 +                       /*
84 +                        * Update inode->i_flags - e.g. S_DAX may get disabled
85 +                        */
86 +                       ext4_set_inode_flags(inode);
87                 }
88                 return res;
89         }
90 @@ -1140,6 +1144,8 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
91                         len, 0);
92         if (!res) {
93                 ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
94 +               /* Update inode->i_flags - e.g. S_DAX may get disabled */
95 +               ext4_set_inode_flags(inode);
96                 res = ext4_mark_inode_dirty(handle, inode);
97                 if (res)
98                         EXT4_ERROR_INODE(inode, "Failed to mark inode dirty");
99 -- 
100 2.6.6