Commit 441c850857148935babe000fc2ba1455fe54a6a9
Committed by
Theodore Ts'o
1 parent
322a8b0340
Exists in
master
and in
6 other branches
ext4: Fix ext4_should_writeback_data() for no-journal mode
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 commit 2d859db3e4 ("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> Cc: stable@kernel.org
Showing 2 changed files with 6 additions and 2 deletions Side-by-side Diff
fs/ext4/ext4_jbd2.h
... | ... | @@ -289,10 +289,10 @@ |
289 | 289 | |
290 | 290 | static inline int ext4_should_writeback_data(struct inode *inode) |
291 | 291 | { |
292 | - if (!S_ISREG(inode->i_mode)) | |
293 | - return 0; | |
294 | 292 | if (EXT4_JOURNAL(inode) == NULL) |
295 | 293 | return 1; |
294 | + if (!S_ISREG(inode->i_mode)) | |
295 | + return 0; | |
296 | 296 | if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA)) |
297 | 297 | return 0; |
298 | 298 | if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) |
fs/ext4/inode.c
... | ... | @@ -983,6 +983,8 @@ |
983 | 983 | from = pos & (PAGE_CACHE_SIZE - 1); |
984 | 984 | to = from + len; |
985 | 985 | |
986 | + BUG_ON(!ext4_handle_valid(handle)); | |
987 | + | |
986 | 988 | if (copied < len) { |
987 | 989 | if (!PageUptodate(page)) |
988 | 990 | copied = 0; |
... | ... | @@ -1698,6 +1700,8 @@ |
1698 | 1700 | ret = PTR_ERR(handle); |
1699 | 1701 | goto out; |
1700 | 1702 | } |
1703 | + | |
1704 | + BUG_ON(!ext4_handle_valid(handle)); | |
1701 | 1705 | |
1702 | 1706 | ret = walk_page_buffers(handle, page_bufs, 0, len, NULL, |
1703 | 1707 | do_journal_get_write_access); |