lkml.org 
[lkml]   [2011]   [Aug]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[18/35] ext4: Fix ext4_should_writeback_data() for no-journal mode
    3.0-stable review patch.  If anyone has any objections, please let us know.

    ------------------

    From: Curt Wohlgemuth <curtw@google.com>

    commit 441c850857148935babe000fc2ba1455fe54a6a9 upstream.

    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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

    ---
    fs/ext4/ext4_jbd2.h | 4 ++--
    fs/ext4/inode.c | 4 ++++
    2 files changed, 6 insertions(+), 2 deletions(-)

    --- a/fs/ext4/ext4_jbd2.h
    +++ b/fs/ext4/ext4_jbd2.h
    @@ -289,10 +289,10 @@ static inline int ext4_should_order_data

    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)
    --- a/fs/ext4/inode.c
    +++ b/fs/ext4/inode.c
    @@ -1849,6 +1849,8 @@ static int ext4_journalled_write_end(str
    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(s
    goto out;
    }

    + BUG_ON(!ext4_handle_valid(handle));
    +
    ret = walk_page_buffers(handle, page_bufs, 0, len, NULL,
    do_journal_get_write_access);




    \
     
     \ /
      Last update: 2011-08-27 17:07    [W:3.537 / U:0.036 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site