| From ddf4b773aa40790dfa936bd845c18e735a49c61c Mon Sep 17 00:00:00 2001 |
| From: Joseph Qi <joseph.qi@linux.alibaba.com> |
| Date: Sat, 29 Jan 2022 13:41:27 -0800 |
| Subject: ocfs2: fix a deadlock when commit trans |
| |
| From: Joseph Qi <joseph.qi@linux.alibaba.com> |
| |
| commit ddf4b773aa40790dfa936bd845c18e735a49c61c upstream. |
| |
| commit 6f1b228529ae introduces a regression which can deadlock as |
| follows: |
| |
| Task1: Task2: |
| jbd2_journal_commit_transaction ocfs2_test_bg_bit_allocatable |
| spin_lock(&jh->b_state_lock) jbd_lock_bh_journal_head |
| __jbd2_journal_remove_checkpoint spin_lock(&jh->b_state_lock) |
| jbd2_journal_put_journal_head |
| jbd_lock_bh_journal_head |
| |
| Task1 and Task2 lock bh->b_state and jh->b_state_lock in different |
| order, which finally result in a deadlock. |
| |
| So use jbd2_journal_[grab|put]_journal_head instead in |
| ocfs2_test_bg_bit_allocatable() to fix it. |
| |
| Link: https://lkml.kernel.org/r/20220121071205.100648-3-joseph.qi@linux.alibaba.com |
| Fixes: 6f1b228529ae ("ocfs2: fix race between searching chunks and release journal_head from buffer_head") |
| Signed-off-by: Joseph Qi <joseph.qi@linux.alibaba.com> |
| Reported-by: Gautham Ananthakrishna <gautham.ananthakrishna@oracle.com> |
| Tested-by: Gautham Ananthakrishna <gautham.ananthakrishna@oracle.com> |
| Reported-by: Saeed Mirzamohammadi <saeed.mirzamohammadi@oracle.com> |
| Cc: "Theodore Ts'o" <tytso@mit.edu> |
| Cc: Andreas Dilger <adilger.kernel@dilger.ca> |
| Cc: Changwei Ge <gechangwei@live.cn> |
| Cc: Gang He <ghe@suse.com> |
| Cc: Joel Becker <jlbec@evilplan.org> |
| Cc: Jun Piao <piaojun@huawei.com> |
| Cc: Junxiao Bi <junxiao.bi@oracle.com> |
| Cc: Mark Fasheh <mark@fasheh.com> |
| Cc: <stable@vger.kernel.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/ocfs2/suballoc.c | 25 +++++++++++-------------- |
| 1 file changed, 11 insertions(+), 14 deletions(-) |
| |
| --- a/fs/ocfs2/suballoc.c |
| +++ b/fs/ocfs2/suballoc.c |
| @@ -1251,26 +1251,23 @@ static int ocfs2_test_bg_bit_allocatable |
| { |
| struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data; |
| struct journal_head *jh; |
| - int ret = 1; |
| + int ret; |
| |
| if (ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap)) |
| return 0; |
| |
| - if (!buffer_jbd(bg_bh)) |
| + jh = jbd2_journal_grab_journal_head(bg_bh); |
| + if (!jh) |
| return 1; |
| |
| - jbd_lock_bh_journal_head(bg_bh); |
| - if (buffer_jbd(bg_bh)) { |
| - jh = bh2jh(bg_bh); |
| - spin_lock(&jh->b_state_lock); |
| - bg = (struct ocfs2_group_desc *) jh->b_committed_data; |
| - if (bg) |
| - ret = !ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap); |
| - else |
| - ret = 1; |
| - spin_unlock(&jh->b_state_lock); |
| - } |
| - jbd_unlock_bh_journal_head(bg_bh); |
| + spin_lock(&jh->b_state_lock); |
| + bg = (struct ocfs2_group_desc *) jh->b_committed_data; |
| + if (bg) |
| + ret = !ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap); |
| + else |
| + ret = 1; |
| + spin_unlock(&jh->b_state_lock); |
| + jbd2_journal_put_journal_head(jh); |
| |
| return ret; |
| } |