aboutsummaryrefslogtreecommitdiffstats
path: root/block/blk.h
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2011-06-13 15:38:22 -0400
committerTheodore Ts'o <tytso@mit.edu>2011-06-13 15:38:22 -0400
commitde1b794130b130e77ffa975bb58cb843744f9ae5 (patch)
tree8c4b37582128dc36c2b7385294fba58d017ce3e8 /block/blk.h
parent1fb74cda1b5e9c6207225fda5ef7504e815ce0e0 (diff)
downloadkernel_samsung_smdk4412-de1b794130b130e77ffa975bb58cb843744f9ae5.zip
kernel_samsung_smdk4412-de1b794130b130e77ffa975bb58cb843744f9ae5.tar.gz
kernel_samsung_smdk4412-de1b794130b130e77ffa975bb58cb843744f9ae5.tar.bz2
jbd2: Fix oops in jbd2_journal_remove_journal_head()
jbd2_journal_remove_journal_head() can oops when trying to access journal_head returned by bh2jh(). This is caused for example by the following race: TASK1 TASK2 jbd2_journal_commit_transaction() ... processing t_forget list __jbd2_journal_refile_buffer(jh); if (!jh->b_transaction) { jbd_unlock_bh_state(bh); jbd2_journal_try_to_free_buffers() jbd2_journal_grab_journal_head(bh) jbd_lock_bh_state(bh) __journal_try_to_free_buffer() jbd2_journal_put_journal_head(jh) jbd2_journal_remove_journal_head(bh); jbd2_journal_put_journal_head() in TASK2 sees that b_jcount == 0 and buffer is not part of any transaction and thus frees journal_head before TASK1 gets to doing so. Note that even buffer_head can be released by try_to_free_buffers() after jbd2_journal_put_journal_head() which adds even larger opportunity for oops (but I didn't see this happen in reality). Fix the problem by making transactions hold their own journal_head reference (in b_jcount). That way we don't have to remove journal_head explicitely via jbd2_journal_remove_journal_head() and instead just remove journal_head when b_jcount drops to zero. The result of this is that [__]jbd2_journal_refile_buffer(), [__]jbd2_journal_unfile_buffer(), and __jdb2_journal_remove_checkpoint() can free journal_head which needs modification of a few callers. Also we have to be careful because once journal_head is removed, buffer_head might be freed as well. So we have to get our own buffer_head reference where it matters. Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'block/blk.h')
0 files changed, 0 insertions, 0 deletions