[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <lsq.1539530740.678899079@decadent.org.uk>
Date: Sun, 14 Oct 2018 16:25:40 +0100
From: Ben Hutchings <ben@...adent.org.uk>
To: linux-kernel@...r.kernel.org, stable@...r.kernel.org
CC: akpm@...ux-foundation.org, "Jan Kara" <jack@...e.cz>,
"Eryu Guan" <guaneryu@...il.com>, "Theodore Ts'o" <tytso@....edu>
Subject: [PATCH 3.16 045/366] ext4: protect i_disksize update by
i_data_sem in direct write path
3.16.60-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Eryu Guan <guaneryu@...il.com>
commit 73fdad00b208b139cf43f3163fbc0f67e4c6047c upstream.
i_disksize update should be protected by i_data_sem, by either taking
the lock explicitly or by using ext4_update_i_disksize() helper. But the
i_disksize updates in ext4_direct_IO_write() are not protected at all,
which may be racing with i_disksize updates in writeback path in
delalloc buffer write path.
This is found by code inspection, and I didn't hit any i_disksize
corruption due to this bug. Thanks to Jan Kara for catching this bug and
suggesting the fix!
Reported-by: Jan Kara <jack@...e.cz>
Suggested-by: Jan Kara <jack@...e.cz>
Signed-off-by: Eryu Guan <guaneryu@...il.com>
Signed-off-by: Theodore Ts'o <tytso@....edu>
[bwh: Backported to 3.16: The relevant code is in ext4_ind_direct_IO()]
Signed-off-by: Ben Hutchings <ben@...adent.org.uk>
---
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -649,7 +649,6 @@ ssize_t ext4_ind_direct_IO(int rw, struc
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
- struct ext4_inode_info *ei = EXT4_I(inode);
handle_t *handle;
ssize_t ret;
int orphan = 0;
@@ -672,7 +671,7 @@ ssize_t ext4_ind_direct_IO(int rw, struc
goto out;
}
orphan = 1;
- ei->i_disksize = inode->i_size;
+ ext4_update_i_disksize(inode, inode->i_size);
ext4_journal_stop(handle);
}
}
@@ -731,7 +730,7 @@ locked:
if (ret > 0) {
loff_t end = offset + ret;
if (end > inode->i_size) {
- ei->i_disksize = end;
+ ext4_update_i_disksize(inode, end);
i_size_write(inode, end);
/*
* We're going to return a positive `ret'
Powered by blists - more mailing lists