[PATCH] xfs: retry dqpurge when dquot buffer is busy
From: Yingjie Gao
Date: Fri Jun 26 2026 - 05:54:07 EST
xfs_qm_dqpurge() marks a zero-reference dquot dead before trying to flush
a dirty dquot. If the attached buffer is busy, xfs_dquot_use_attached_buf()
returns -EAGAIN.
The error path restores q_lockref.count but then jumps to out_funlock,
which continues into the successful purge tail and destroys the dquot. At
that point the attached buffer has not been detached and the dquot log item
may still be in the AIL.
Restore the retry behavior by dropping the locks and returning -EAGAIN
after resurrecting the lockref.
Link: https://lore.kernel.org/linux-xfs/20260625175519.GF6078@frogsfrogsfrogs/
Fixes: 0c5e80bd579f ("xfs: use a lockref for the xfs_dquot reference count")
Cc: stable@xxxxxxxxxxxxxxx # v6.19+
Signed-off-by: Yingjie Gao <gaoyingjie@xxxxxxxxxxxxx>
---
fs/xfs/xfs_qm.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index aa0d2976f1c3..0622c72292d8 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -155,8 +155,12 @@ xfs_qm_dqpurge(
error = xfs_dquot_use_attached_buf(dqp, &bp);
if (error == -EAGAIN) {
/* resurrect the refcount from the dead. */
+ xfs_dqfunlock(dqp);
+ mutex_unlock(&dqp->q_qlock);
+ spin_lock(&dqp->q_lockref.lock);
dqp->q_lockref.count = 0;
- goto out_funlock;
+ spin_unlock(&dqp->q_lockref.lock);
+ return -EAGAIN;
}
if (!bp)
goto out_funlock;
--
2.20.1