ext4: wait for outstanding dio during truncate in nojournal mode
authorJan Kara <jack@suse.cz>
Fri, 24 May 2019 03:07:08 +0000 (23:07 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Fri, 24 May 2019 03:07:08 +0000 (23:07 -0400)
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>
fs/ext4/inode.c

index 82298c63ea6d6c904cdad8bb32e0f40e801b9785..9bcb7f2b86dd891f11bd1690824133b6ed81cd95 100644 (file)
@@ -5630,20 +5630,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);