[02/11] ext4: Let S_DAX set only if DAX is really supported
diff mbox

Message ID 1478603297-11793-3-git-send-email-jack@suse.cz
State New
Headers show

Commit Message

Jan Kara Nov. 8, 2016, 11:08 a.m. UTC
Currently we have S_DAX set inode->i_flags for a regular file whenever
ext4 is mounted with dax mount option. However in some cases we cannot
really do DAX - e.g. when inode is marked to use data journalling, when
inode data is being encrypted, or when inode is stored inline. Make sure
S_DAX flag is appropriately set/cleared in these cases.

Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/ext4/inline.c | 10 ++++++++++
 fs/ext4/inode.c  |  9 ++++++++-
 fs/ext4/super.c  |  5 +++++
 3 files changed, 23 insertions(+), 1 deletion(-)

Comments

Ross Zwisler Nov. 10, 2016, 9:46 p.m. UTC | #1
On Tue, Nov 08, 2016 at 12:08:08PM +0100, Jan Kara wrote:
> Currently we have S_DAX set inode->i_flags for a regular file whenever
> ext4 is mounted with dax mount option. However in some cases we cannot
> really do DAX - e.g. when inode is marked to use data journalling, when
> inode data is being encrypted, or when inode is stored inline. Make sure
> S_DAX flag is appropriately set/cleared in these cases.
> 
> Signed-off-by: Jan Kara <jack@suse.cz>
> ---
<>
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index 20da99da0a34..b3108e6fa5f3 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -1126,6 +1126,10 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
>  			ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
>  			ext4_clear_inode_state(inode,
>  					EXT4_STATE_MAY_INLINE_DATA);
> +			/*
> +			 * Update inode->i_flags - e.g. S_DAX may get disabled
> +			 */
> +			ext4_set_inode_flags(inode);
>  		}
>  		return res;
>  	}
> @@ -1140,6 +1144,7 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
>  			len, 0);
>  	if (!res) {
>  		ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
> +		/* Update inode->i_flags - e.g. S_DAX may get disabled */

Missing call to ext4_set_inode_flags(inode)?

>  		res = ext4_mark_inode_dirty(handle, inode);
>  		if (res)
>  			EXT4_ERROR_INODE(inode, "Failed to mark inode dirty");
> -- 
> 2.6.6
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jan Kara Nov. 11, 2016, 10:08 a.m. UTC | #2
On Thu 10-11-16 14:46:39, Ross Zwisler wrote:
> On Tue, Nov 08, 2016 at 12:08:08PM +0100, Jan Kara wrote:
> > Currently we have S_DAX set inode->i_flags for a regular file whenever
> > ext4 is mounted with dax mount option. However in some cases we cannot
> > really do DAX - e.g. when inode is marked to use data journalling, when
> > inode data is being encrypted, or when inode is stored inline. Make sure
> > S_DAX flag is appropriately set/cleared in these cases.
> > 
> > Signed-off-by: Jan Kara <jack@suse.cz>
> > ---
> <>
> > diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> > index 20da99da0a34..b3108e6fa5f3 100644
> > --- a/fs/ext4/super.c
> > +++ b/fs/ext4/super.c
> > @@ -1126,6 +1126,10 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
> >  			ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
> >  			ext4_clear_inode_state(inode,
> >  					EXT4_STATE_MAY_INLINE_DATA);
> > +			/*
> > +			 * Update inode->i_flags - e.g. S_DAX may get disabled
> > +			 */
> > +			ext4_set_inode_flags(inode);
> >  		}
> >  		return res;
> >  	}
> > @@ -1140,6 +1144,7 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
> >  			len, 0);
> >  	if (!res) {
> >  		ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
> > +		/* Update inode->i_flags - e.g. S_DAX may get disabled */
> 
> Missing call to ext4_set_inode_flags(inode)?

Yeah, fixed. Thanks!

								Honza
Ross Zwisler Nov. 11, 2016, 5:56 p.m. UTC | #3
On Fri, Nov 11, 2016 at 11:08:57AM +0100, Jan Kara wrote:
> On Thu 10-11-16 14:46:39, Ross Zwisler wrote:
> > On Tue, Nov 08, 2016 at 12:08:08PM +0100, Jan Kara wrote:
> > > Currently we have S_DAX set inode->i_flags for a regular file whenever
> > > ext4 is mounted with dax mount option. However in some cases we cannot
> > > really do DAX - e.g. when inode is marked to use data journalling, when
> > > inode data is being encrypted, or when inode is stored inline. Make sure
> > > S_DAX flag is appropriately set/cleared in these cases.
> > > 
> > > Signed-off-by: Jan Kara <jack@suse.cz>
> > > ---
> > <>
> > > diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> > > index 20da99da0a34..b3108e6fa5f3 100644
> > > --- a/fs/ext4/super.c
> > > +++ b/fs/ext4/super.c
> > > @@ -1126,6 +1126,10 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
> > >  			ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
> > >  			ext4_clear_inode_state(inode,
> > >  					EXT4_STATE_MAY_INLINE_DATA);
> > > +			/*
> > > +			 * Update inode->i_flags - e.g. S_DAX may get disabled
> > > +			 */
> > > +			ext4_set_inode_flags(inode);
> > >  		}
> > >  		return res;
> > >  	}
> > > @@ -1140,6 +1144,7 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
> > >  			len, 0);
> > >  	if (!res) {
> > >  		ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
> > > +		/* Update inode->i_flags - e.g. S_DAX may get disabled */
> > 
> > Missing call to ext4_set_inode_flags(inode)?
> 
> Yeah, fixed. Thanks!

Cool, you can add:

Reviewed-by: Ross Zwisler <ross.zwisler@linux.intel.com>
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch
diff mbox

diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index f74d5ee2cdec..c29678965c3c 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -299,6 +299,11 @@  static int ext4_create_inline_data(handle_t *handle,
 	EXT4_I(inode)->i_inline_size = len + EXT4_MIN_INLINE_DATA_SIZE;
 	ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS);
 	ext4_set_inode_flag(inode, EXT4_INODE_INLINE_DATA);
+	/*
+	 * Propagate changes to inode->i_flags as well - e.g. S_DAX may
+	 * get cleared
+	 */
+	ext4_set_inode_flags(inode);
 	get_bh(is.iloc.bh);
 	error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
 
@@ -442,6 +447,11 @@  static int ext4_destroy_inline_data_nolock(handle_t *handle,
 		}
 	}
 	ext4_clear_inode_flag(inode, EXT4_INODE_INLINE_DATA);
+	/*
+	 * Propagate changes to inode->i_flags as well - e.g. S_DAX may
+	 * get set.
+	 */
+	ext4_set_inode_flags(inode);
 
 	get_bh(is.iloc.bh);
 	error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 3d58b2b477e8..5337828c68a7 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4355,7 +4355,9 @@  void ext4_set_inode_flags(struct inode *inode)
 		new_fl |= S_NOATIME;
 	if (flags & EXT4_DIRSYNC_FL)
 		new_fl |= S_DIRSYNC;
-	if (test_opt(inode->i_sb, DAX) && S_ISREG(inode->i_mode))
+	if (test_opt(inode->i_sb, DAX) && S_ISREG(inode->i_mode) &&
+	    !ext4_should_journal_data(inode) && !ext4_has_inline_data(inode) &&
+	    !ext4_encrypted_inode(inode))
 		new_fl |= S_DAX;
 	inode_set_flags(inode, new_fl,
 			S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_DAX);
@@ -5623,6 +5625,11 @@  int ext4_change_inode_journal_flag(struct inode *inode, int val)
 		ext4_clear_inode_flag(inode, EXT4_INODE_JOURNAL_DATA);
 	}
 	ext4_set_aops(inode);
+	/*
+	 * Update inode->i_flags after EXT4_INODE_JOURNAL_DATA was updated.
+	 * E.g. S_DAX may get cleared / set.
+	 */
+	ext4_set_inode_flags(inode);
 
 	jbd2_journal_unlock_updates(journal);
 	percpu_up_write(&sbi->s_journal_flag_rwsem);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 20da99da0a34..b3108e6fa5f3 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1126,6 +1126,10 @@  static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
 			ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
 			ext4_clear_inode_state(inode,
 					EXT4_STATE_MAY_INLINE_DATA);
+			/*
+			 * Update inode->i_flags - e.g. S_DAX may get disabled
+			 */
+			ext4_set_inode_flags(inode);
 		}
 		return res;
 	}
@@ -1140,6 +1144,7 @@  static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,
 			len, 0);
 	if (!res) {
 		ext4_set_inode_flag(inode, EXT4_INODE_ENCRYPT);
+		/* Update inode->i_flags - e.g. S_DAX may get disabled */
 		res = ext4_mark_inode_dirty(handle, inode);
 		if (res)
 			EXT4_ERROR_INODE(inode, "Failed to mark inode dirty");