diff options
| author | Christoph Hellwig <hch@lst.de> | 2025-11-10 14:22:57 +0100 |
|---|---|---|
| committer | Carlos Maiolino <cem@kernel.org> | 2025-11-11 11:45:57 +0100 |
| commit | 0c5e80bd579f7bec3704bad6c1f72b13b0d73b53 (patch) | |
| tree | 51be9ec5f30da3d0229e243bc9b7e79d8f1f122d /fs/xfs/xfs_dquot.c | |
| parent | 6129b088e1f10938b86f44948ad698b39dd19faa (diff) | |
xfs: use a lockref for the xfs_dquot reference count
The xfs_dquot structure currently uses the anti-pattern of using the
in-object lock that protects the content to also serialize reference
count updates for the structure, leading to a cumbersome free path.
This is partially papered over by the fact that we never free the dquot
directly but always through the LRU. Switch to use a lockref instead and
move the reference counter manipulations out of q_qlock.
To make this work, xfs_qm_flush_one and xfs_qm_flush_one are converted to
acquire a dquot reference while flushing to integrate with the lockref
"get if not dead" scheme.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
Diffstat (limited to 'fs/xfs/xfs_dquot.c')
| -rw-r--r-- | fs/xfs/xfs_dquot.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index c2326cee7fae..34c325524ab9 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -816,20 +816,17 @@ restart: return NULL; } - mutex_lock(&dqp->q_qlock); - if (dqp->q_flags & XFS_DQFLAG_FREEING) { - mutex_unlock(&dqp->q_qlock); + if (!lockref_get_not_dead(&dqp->q_lockref)) { mutex_unlock(&qi->qi_tree_lock); trace_xfs_dqget_freeing(dqp); delay(1); goto restart; } - - dqp->q_nrefs++; mutex_unlock(&qi->qi_tree_lock); trace_xfs_dqget_hit(dqp); XFS_STATS_INC(mp, xs_qm_dqcachehits); + mutex_lock(&dqp->q_qlock); return dqp; } @@ -866,7 +863,7 @@ xfs_qm_dqget_cache_insert( /* Return a locked dquot to the caller, with a reference taken. */ mutex_lock(&dqp->q_qlock); - dqp->q_nrefs = 1; + lockref_init(&dqp->q_lockref); qi->qi_dquots++; out_unlock: @@ -1124,18 +1121,22 @@ void xfs_qm_dqput( struct xfs_dquot *dqp) { - ASSERT(dqp->q_nrefs > 0); ASSERT(XFS_DQ_IS_LOCKED(dqp)); trace_xfs_dqput(dqp); - if (--dqp->q_nrefs == 0) { + if (lockref_put_or_lock(&dqp->q_lockref)) + goto out_unlock; + + if (!--dqp->q_lockref.count) { struct xfs_quotainfo *qi = dqp->q_mount->m_quotainfo; trace_xfs_dqput_free(dqp); if (list_lru_add_obj(&qi->qi_lru, &dqp->q_lru)) XFS_STATS_INC(dqp->q_mount, xs_qm_dquot_unused); } + spin_unlock(&dqp->q_lockref.lock); +out_unlock: mutex_unlock(&dqp->q_qlock); } |
