Skip to content

Commit eccc2df

Browse files
Darrick J. Wonggregkh
authored andcommitted
xfs: release the dquot buf outside of qli_lock
commit 1aacd3f upstream. 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: [email protected] Cc: <[email protected]> # v6.13-rc3 Fixes: ca37818 ("xfs: convert quotacheck to attach dquot buffers") Tested-by: [email protected] Signed-off-by: "Darrick J. Wong" <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 2aec967 commit eccc2df

File tree

1 file changed

+8
-4
lines changed

1 file changed

+8
-4
lines changed

fs/xfs/xfs_dquot.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,7 +1316,8 @@ xfs_dquot_read_buf(
13161316

13171317
/*
13181318
* Attach a dquot buffer to this dquot to avoid allocating a buffer during a
1319-
* dqflush, since dqflush can be called from reclaim context.
1319+
* dqflush, since dqflush can be called from reclaim context. Caller must hold
1320+
* the dqlock.
13201321
*/
13211322
int
13221323
xfs_dquot_attach_buf(
@@ -1337,13 +1338,16 @@ xfs_dquot_attach_buf(
13371338
return error;
13381339

13391340
/*
1340-
* Attach the dquot to the buffer so that the AIL does not have
1341-
* to read the dquot buffer to push this item.
1341+
* Hold the dquot buffer so that we retain our ref to it after
1342+
* detaching it from the transaction, then give that ref to the
1343+
* dquot log item so that the AIL does not have to read the
1344+
* dquot buffer to push this item.
13421345
*/
13431346
xfs_buf_hold(bp);
1347+
xfs_trans_brelse(tp, bp);
1348+
13441349
spin_lock(&qlip->qli_lock);
13451350
lip->li_buf = bp;
1346-
xfs_trans_brelse(tp, bp);
13471351
}
13481352
qlip->qli_dirty = true;
13491353
spin_unlock(&qlip->qli_lock);

0 commit comments

Comments
 (0)