Commit 441c850857148935babe000fc2ba1455fe54a6a9

Authored by Curt Wohlgemuth
Committed by Theodore Ts'o
1 parent 322a8b0340

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

... ... @@ -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)
... ... @@ -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);