Fix a race identified by Chris Mason <mason@suse.com>
journal_unmap_buffer -> __dispose_buffers has the j_list_lock and the
jbd_lock_bh_state held.
journal_get_write_access calls journal_put_journal_head, which takes
jbd_lock_bh_journal_head(bh) and doesn't seem to have any other locks held.
Since journal_unmap_buffers trusts the buffer_jbd bit to see if we need to
call __dispose_buffer, and nobody seems to test buffer_jbd after taking
jbd_lock_bh_journal_head. The kernel dereferences a null jh pointer in
__journal_remove_journal_head.
The patch fixes this by using journal_grab_journal_head() in
journal_unmap_buffer(). It ensures that we either grab and pin the
journal_head if the bh has one, or we bale out if the bh doesn't have a
journal_head.
Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>