| From 82a25b027ca48d7ef197295846b352345853dfa8 Mon Sep 17 00:00:00 2001 |
| From: Jan Kara <jack@suse.cz> |
| Date: Thu, 23 May 2019 23:07:08 -0400 |
| Subject: ext4: wait for outstanding dio during truncate in nojournal mode |
| |
| From: Jan Kara <jack@suse.cz> |
| |
| commit 82a25b027ca48d7ef197295846b352345853dfa8 upstream. |
| |
| We didn't wait for outstanding direct IO during truncate in nojournal |
| mode (as we skip orphan handling in that case). This can lead to fs |
| corruption or stale data exposure if truncate ends up freeing blocks |
| and these get reallocated before direct IO finishes. Fix the condition |
| determining whether the wait is necessary. |
| |
| CC: stable@vger.kernel.org |
| Fixes: 1c9114f9c0f1 ("ext4: serialize unlocked dio reads with truncate") |
| Reviewed-by: Ira Weiny <ira.weiny@intel.com> |
| Signed-off-by: Jan Kara <jack@suse.cz> |
| Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/ext4/inode.c | 21 +++++++++------------ |
| 1 file changed, 9 insertions(+), 12 deletions(-) |
| |
| --- a/fs/ext4/inode.c |
| +++ b/fs/ext4/inode.c |
| @@ -5624,20 +5624,17 @@ int ext4_setattr(struct dentry *dentry, |
| goto err_out; |
| } |
| } |
| - if (!shrink) |
| + if (!shrink) { |
| pagecache_isize_extended(inode, oldsize, inode->i_size); |
| - |
| - /* |
| - * Blocks are going to be removed from the inode. Wait |
| - * for dio in flight. Temporarily disable |
| - * dioread_nolock to prevent livelock. |
| - */ |
| - if (orphan) { |
| - if (!ext4_should_journal_data(inode)) { |
| - inode_dio_wait(inode); |
| - } else |
| - ext4_wait_for_tail_page_commit(inode); |
| + } else { |
| + /* |
| + * Blocks are going to be removed from the inode. Wait |
| + * for dio in flight. |
| + */ |
| + inode_dio_wait(inode); |
| } |
| + if (orphan && ext4_should_journal_data(inode)) |
| + ext4_wait_for_tail_page_commit(inode); |
| down_write(&EXT4_I(inode)->i_mmap_sem); |
| |
| rc = ext4_break_layouts(inode); |