• Jan Kara's avatar
    jbd2: Fix a race between checkpointing code and journal_get_write_access() · f91d1d04
    Jan Kara authored
    The following race can happen:
    
     CPU1                          CPU2
                                   checkpointing code checks the buffer, adds
                                     it to an array for writeback
     do_get_write_access()
     ...
     lock_buffer()
     unlock_buffer()
                                   flush_batch() submits the buffer for IO
     __jbd2_journal_file_buffer()
    
    So a buffer under writeout is returned from
    do_get_write_access(). Since the filesystem code relies on the fact
    that journaled buffers cannot be written out, it does not take the
    buffer lock and so it can modify buffer while it is under
    writeout. That can lead to a filesystem corruption if we crash at the
    right moment.
    
    We fix the problem by clearing the buffer dirty bit under buffer_lock
    even if the buffer is on BJ_None list. Actually, we clear the dirty
    bit regardless the list the buffer is in and warn about the fact if
    the buffer is already journalled.
    
    Thanks for spotting the problem goes to dingdinghua <dingdinghua85@gmail.com>.
    Reported-by: default avatardingdinghua <dingdinghua85@gmail.com>
    Signed-off-by: default avatarJan Kara <jack@suse.cz>
    Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
    f91d1d04
transaction.c 63 KB