summaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorJan Kara2019-05-24 05:07:08 +0200
committerGreg Kroah-Hartman2019-05-31 15:46:00 +0200
commit5220582c427bb377c8c4b28ed911f545e7da859d (patch)
treedcdd9cab37becfe9a42b166c269f92075a4d8df6 /fs/ext4
parentext4: do not delete unlinked inode from orphan list on failed truncate (diff)
downloadkernel-qcow2-linux-5220582c427bb377c8c4b28ed911f545e7da859d.tar.gz
kernel-qcow2-linux-5220582c427bb377c8c4b28ed911f545e7da859d.tar.xz
kernel-qcow2-linux-5220582c427bb377c8c4b28ed911f545e7da859d.zip
ext4: wait for outstanding dio during truncate in nojournal mode
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>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/inode.c21
1 files changed, 9 insertions, 12 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 82dee8addb4b..05dc5a4ba481 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -5601,20 +5601,17 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
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);