jbd: Fix a race between checkpointing code and journal_get_write_access()
authorJan Kara <jack@suse.cz>
Wed, 24 Jun 2009 15:31:40 +0000 (17:31 +0200)
committerJan Kara <jack@suse.cz>
Wed, 15 Jul 2009 19:30:07 +0000 (21:30 +0200)
commit1e9fd53b783ea646de3ee09a4574afeb6778d504
tree0b87e9ca83c612a1c3c5b91a359f8604cde48c45
parent9eaaa2d5759837402ec5eee13b2a97921808c3eb
jbd: Fix a race between checkpointing code and journal_get_write_access()

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
  __jbd_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. The similar problem can happen with
the journal_get_create_access() path.
  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: dingdinghua <dingdinghua85@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
fs/jbd/transaction.c