jbd2: Fix a race between checkpointing code and journal_get_write_access()
commitf91d1d04171026e56c7e343ee3cdcc801dd85cfb
authorJan Kara <jack@suse.cz>
Mon, 13 Jul 2009 20:16:20 +0000 (13 16:16 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 13 Jul 2009 20:16:20 +0000 (13 16:16 -0400)
tree282341868e06cb09ecd6c0838ea027feec514c2c
parent3e03f9ca6a2599db1823bb0ea24e0845219a0e69
jbd2: 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
 __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: dingdinghua <dingdinghua85@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
fs/jbd2/transaction.c