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>
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);
29 + * Propagate changes to inode->i_flags as well - e.g. S_DAX may
32 + ext4_set_inode_flags(inode);
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,
39 ext4_clear_inode_flag(inode, EXT4_INODE_INLINE_DATA);
41 + * Propagate changes to inode->i_flags as well - e.g. S_DAX may
44 + ext4_set_inode_flags(inode);
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
52 @@ -4355,7 +4355,9 @@ void ext4_set_inode_flags(struct inode *inode)
54 if (flags & EXT4_DIRSYNC_FL)
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))
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);
68 + * Update inode->i_flags after EXT4_INODE_JOURNAL_DATA was updated.
69 + * E.g. S_DAX may get cleared / set.
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
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);
84 + * Update inode->i_flags - e.g. S_DAX may get disabled
86 + ext4_set_inode_flags(inode);
90 @@ -1140,6 +1144,8 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
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);
98 EXT4_ERROR_INODE(inode, "Failed to mark inode dirty");