mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 07:03:03 +02:00
xfs: release the dquot buf outside of qli_lock
Lai Yi reported a lockdep complaint about circular locking:
Chain exists of:
&lp->qli_lock --> &bch->bc_lock --> &l->lock
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&l->lock);
lock(&bch->bc_lock);
lock(&l->lock);
lock(&lp->qli_lock);
I /think/ the problem here is that xfs_dquot_attach_buf during
quotacheck will release the buffer while it's holding the qli_lock.
Because this is a cached buffer, xfs_buf_rele_cached takes b_lock before
decrementing b_hold. Other threads have taught lockdep that a locking
dependency chain is bp->b_lock -> bch->bc_lock -> l(ru)->lock; and that
another chain is l(ru)->lock -> lp->qli_lock. Hence we do not want to
take b_lock while holding qli_lock.
Reported-by: syzbot+3126ab3db03db42e7a31@syzkaller.appspotmail.com
Cc: <stable@vger.kernel.org> # v6.13-rc3
Fixes: ca378189fd ("xfs: convert quotacheck to attach dquot buffers")
Tested-by: syzbot+3126ab3db03db42e7a31@syzkaller.appspotmail.com
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
4b8d867ca6
commit
1aacd3fac2
|
|
@ -1315,7 +1315,8 @@ xfs_dquot_read_buf(
|
|||
|
||||
/*
|
||||
* Attach a dquot buffer to this dquot to avoid allocating a buffer during a
|
||||
* dqflush, since dqflush can be called from reclaim context.
|
||||
* dqflush, since dqflush can be called from reclaim context. Caller must hold
|
||||
* the dqlock.
|
||||
*/
|
||||
int
|
||||
xfs_dquot_attach_buf(
|
||||
|
|
@ -1336,13 +1337,16 @@ xfs_dquot_attach_buf(
|
|||
return error;
|
||||
|
||||
/*
|
||||
* Attach the dquot to the buffer so that the AIL does not have
|
||||
* to read the dquot buffer to push this item.
|
||||
* Hold the dquot buffer so that we retain our ref to it after
|
||||
* detaching it from the transaction, then give that ref to the
|
||||
* dquot log item so that the AIL does not have to read the
|
||||
* dquot buffer to push this item.
|
||||
*/
|
||||
xfs_buf_hold(bp);
|
||||
xfs_trans_brelse(tp, bp);
|
||||
|
||||
spin_lock(&qlip->qli_lock);
|
||||
lip->li_buf = bp;
|
||||
xfs_trans_brelse(tp, bp);
|
||||
}
|
||||
qlip->qli_dirty = true;
|
||||
spin_unlock(&qlip->qli_lock);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user