jbd: Issue cache flush after checkpointing
authorJan Kara <jack@suse.cz>
Fri, 25 Nov 2011 23:35:39 +0000 (00:35 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 3 Feb 2012 17:21:32 +0000 (09:21 -0800)
commitfde1c2621a4c32c8767d3fa488c14fd396f700f9
treea76677c96c2ab1a25332379079c2c8a811fc2c2c
parent427038dfb7208899adbe4b17b11c310616953070
jbd: Issue cache flush after checkpointing

commit 353b67d8ced4dc53281c88150ad295e24bc4b4c5 upstream.

When we reach cleanup_journal_tail(), there is no guarantee that
checkpointed buffers are on a stable storage - especially if buffers were
written out by log_do_checkpoint(), they are likely to be only in disk's
caches. Thus when we update journal superblock, effectively removing old
transaction from journal, this write of superblock can get to stable storage
before those checkpointed buffers which can result in filesystem corruption
after a crash.

A similar problem can happen if we replay the journal and wipe it before
flushing disk's caches.

Thus we must unconditionally issue a cache flush before we update journal
superblock in these cases. The fix is slightly complicated by the fact that we
have to get log tail before we issue cache flush but we can store it in the
journal superblock only after the cache flush. Otherwise we risk races where
new tail is written before appropriate cache flush is finished.

I managed to reproduce the corruption using somewhat tweaked Chris Mason's
barrier-test scheduler. Also this should fix occasional reports of 'Bit already
freed' filesystem errors which are totally unreproducible but inspection of
several fs images I've gathered over time points to a problem like this.

Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/jbd/checkpoint.c
fs/jbd/recovery.c