aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_dquot.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2011-12-06 21:58:17 +0000
committerBen Myers <bpm@sgi.com>2011-12-13 16:46:28 -0600
commitbe7ffc38a80a78e6b68d0f51fae8e8d57b55324c (patch)
treebb5ca49fd1dc92051e9898a653d7bdd26c93af59 /fs/xfs/xfs_dquot.c
parent80a376bfb7f8ff8f1942cb1bdd0052e908918252 (diff)
xfs: implement lazy removal for the dquot freelist
Do not remove dquots from the freelist when we grab a reference to them in xfs_qm_dqlookup, but leave them on the freelist util scanning notices that they have a reference. This speeds up the lookup fastpath, and greatly simplifies the lock ordering constraints. Note that the same scheme is used by the VFS inode and dentry caches. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_dquot.c')
-rw-r--r--fs/xfs/xfs_dquot.c67
1 files changed, 18 insertions, 49 deletions
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 3f94f2428a3..35d2b8aad0f 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -722,58 +722,25 @@ xfs_qm_dqlookup(
* dqlock to look at the id field of the dquot, since the
* id can't be modified without the hashlock anyway.
*/
- if (be32_to_cpu(dqp->q_core.d_id) == id && dqp->q_mount == mp) {
- trace_xfs_dqlookup_found(dqp);
+ if (be32_to_cpu(dqp->q_core.d_id) != id || dqp->q_mount != mp)
+ continue;
- /*
- * All in core dquots must be on the dqlist of mp
- */
- ASSERT(!list_empty(&dqp->q_mplist));
-
- xfs_dqlock(dqp);
- if (dqp->q_nrefs == 0) {
- ASSERT(!list_empty(&dqp->q_freelist));
- if (!mutex_trylock(&xfs_Gqm->qm_dqfrlist_lock)) {
- trace_xfs_dqlookup_want(dqp);
-
- /*
- * We may have raced with dqreclaim_one()
- * (and lost). So, flag that we don't
- * want the dquot to be reclaimed.
- */
- dqp->dq_flags |= XFS_DQ_WANT;
- xfs_dqunlock(dqp);
- mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
- xfs_dqlock(dqp);
- dqp->dq_flags &= ~(XFS_DQ_WANT);
- }
-
- if (dqp->q_nrefs == 0) {
- /* take it off the freelist */
- trace_xfs_dqlookup_freelist(dqp);
- list_del_init(&dqp->q_freelist);
- xfs_Gqm->qm_dqfrlist_cnt--;
- }
- XFS_DQHOLD(dqp);
- mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
- } else {
- XFS_DQHOLD(dqp);
- }
+ trace_xfs_dqlookup_found(dqp);
- /*
- * move the dquot to the front of the hashchain
- */
- ASSERT(mutex_is_locked(&qh->qh_lock));
- list_move(&dqp->q_hashlist, &qh->qh_list);
- trace_xfs_dqlookup_done(dqp);
- *O_dqpp = dqp;
- return 0;
- }
+ xfs_dqlock(dqp);
+ XFS_DQHOLD(dqp);
+
+ /*
+ * move the dquot to the front of the hashchain
+ */
+ list_move(&dqp->q_hashlist, &qh->qh_list);
+ trace_xfs_dqlookup_done(dqp);
+ *O_dqpp = dqp;
+ return 0;
}
*O_dqpp = NULL;
- ASSERT(mutex_is_locked(&qh->qh_lock));
- return (1);
+ return 1;
}
/*
@@ -1033,8 +1000,10 @@ xfs_qm_dqput(
if (--dqp->q_nrefs == 0) {
trace_xfs_dqput_free(dqp);
- list_add_tail(&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist);
- xfs_Gqm->qm_dqfrlist_cnt++;
+ if (list_empty(&dqp->q_freelist)) {
+ list_add_tail(&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist);
+ xfs_Gqm->qm_dqfrlist_cnt++;
+ }
/*
* If we just added a udquot to the freelist, then