mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 06:25:52 +02:00
ext4: Fix ext4_should_writeback_data() for no-journal mode
commit441c850857upstream. ext4_should_writeback_data() had an incorrect sequence of tests to determine if it should return 0 or 1: in particular, even in no-journal mode, 0 was being returned for a non-regular-file inode. This meant that, in non-journal mode, we would use ext4_journalled_aops for directories, symlinks, and other non-regular files. However, calling journalled aop callbacks when there is no valid handle, can cause problems. This would cause a kernel crash with Jan Kara's commit2d859db3e4("ext4: fix data corruption in inodes with journalled data"), because we now dereference 'handle' in ext4_journalled_write_end(). I also added BUG_ONs to check for a valid handle in the obviously journal-only aops callbacks. I tested this running xfstests with a scratch device in these modes: - no-journal - data=ordered - data=writeback - data=journal All work fine; the data=journal run has many failures and a crash in xfstests 074, but this is no different from a vanilla kernel. Signed-off-by: Curt Wohlgemuth <curtw@google.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
f5dce23cc1
commit
2fb522e963
|
|
@ -289,10 +289,10 @@ static inline int ext4_should_order_data(struct inode *inode)
|
|||
|
||||
static inline int ext4_should_writeback_data(struct inode *inode)
|
||||
{
|
||||
if (!S_ISREG(inode->i_mode))
|
||||
return 0;
|
||||
if (EXT4_JOURNAL(inode) == NULL)
|
||||
return 1;
|
||||
if (!S_ISREG(inode->i_mode))
|
||||
return 0;
|
||||
if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
|
||||
return 0;
|
||||
if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
|
||||
|
|
|
|||
|
|
@ -1849,6 +1849,8 @@ static int ext4_journalled_write_end(struct file *file,
|
|||
from = pos & (PAGE_CACHE_SIZE - 1);
|
||||
to = from + len;
|
||||
|
||||
BUG_ON(!ext4_handle_valid(handle));
|
||||
|
||||
if (copied < len) {
|
||||
if (!PageUptodate(page))
|
||||
copied = 0;
|
||||
|
|
@ -2564,6 +2566,8 @@ static int __ext4_journalled_writepage(struct page *page,
|
|||
goto out;
|
||||
}
|
||||
|
||||
BUG_ON(!ext4_handle_valid(handle));
|
||||
|
||||
ret = walk_page_buffers(handle, page_bufs, 0, len, NULL,
|
||||
do_journal_get_write_access);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user