On Thu, Oct 04, 2018 at 06:05:46PM +0200, Jan Kara wrote:
On Thu 04-10-18 08:44:02, Greg KH wrote:
On Thu, Oct 04, 2018 at 12:46:40PM +0200, Jan Kara wrote:
The code cleaning transaction's lists of checkpoint buffers has a bug where it increases bh refcount only after releasing journal->j_list_lock. Thus the following race is possible:
CPU0 CPU1 jbd2_log_do_checkpoint() jbd2_journal_try_to_free_buffers() __journal_try_to_free_buffer(bh) ... while (transaction->t_checkpoint_io_list) ... if (buffer_locked(bh)) {
<-- IO completes now, buffer gets unlocked -->
spin_unlock(&journal->j_list_lock); spin_lock(&journal->j_list_lock); __jbd2_journal_remove_checkpoint(jh); spin_unlock(&journal->j_list_lock); try_to_free_buffers(page); get_bh(bh) <-- accesses freed bh
Fix the problem by grabbing bh reference before unlocking journal->j_list_lock.
Fixes: dc6e8d669cf5cb3ff84707c372c0a2a8a5e80845 Fixes: be1158cc615fd723552f0d9912087423c7cadda5
Nit, this normally looks like:
Fixes: dc6e8d669cf5 ("jbd2: don't call get_bh() before calling __jbd2_journal_remove_checkpoint()")
And this is created by: git show -s --abbrev-commit --abbrev=12 --pretty=format:"%h ("%s")%n"
OK, ok, will do next time. The full git commit ID is faster to cut-n-paste which shows how lazy I'm ;)
I have this in the .gitconfig
[pretty] fixes = Fixes: %h ("%s")
which helps. I think I found it in the docs somewhere.
-Lukas
Honza
-- Jan Kara jack@suse.com SUSE Labs, CR