ext4: wait for outstanding dio during truncate in nojournal mode [Linux 5.2]

ext4: wait for outstanding dio during truncate in nojournal mode [Linux 5.2]

This Linux kernel change "ext4: wait for outstanding dio during truncate in nojournal mode" is included in the Linux 5.2 release. This change is authored by Jan Kara <jack [at] suse.cz> on Thu May 23 23:07:08 2019 -0400. The commit for this change in Linux stable tree is 82a25b0 (patch).

ext4: wait for outstanding dio during truncate in nojournal mode

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: [email protected]
Fixes: 1c9114f9c0f1 ("ext4: serialize unlocked dio reads with truncate")
Reviewed-by: Ira Weiny <[email protected]>
Signed-off-by: Jan Kara <[email protected]>
Signed-off-by: Theodore Ts'o <[email protected]>

There are 21 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 fs/ext4/inode.c | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 82298c6..9bcb7f2 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -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);

Leave a Reply

Your email address will not be published. Required fields are marked *