提交 be7ffc38 编写于 作者: C Christoph Hellwig 提交者: Ben Myers

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: NChristoph Hellwig <hch@lst.de>
Reviewed-by: NDave Chinner <dchinner@redhat.com>
Signed-off-by: NBen Myers <bpm@sgi.com>
上级 80a376bf
...@@ -722,58 +722,25 @@ xfs_qm_dqlookup( ...@@ -722,58 +722,25 @@ xfs_qm_dqlookup(
* dqlock to look at the id field of the dquot, since the * dqlock to look at the id field of the dquot, since the
* id can't be modified without the hashlock anyway. * id can't be modified without the hashlock anyway.
*/ */
if (be32_to_cpu(dqp->q_core.d_id) == id && dqp->q_mount == mp) { if (be32_to_cpu(dqp->q_core.d_id) != id || dqp->q_mount != mp)
trace_xfs_dqlookup_found(dqp); continue;
/* trace_xfs_dqlookup_found(dqp);
* 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);
}
/* xfs_dqlock(dqp);
* move the dquot to the front of the hashchain XFS_DQHOLD(dqp);
*/
ASSERT(mutex_is_locked(&qh->qh_lock)); /*
list_move(&dqp->q_hashlist, &qh->qh_list); * move the dquot to the front of the hashchain
trace_xfs_dqlookup_done(dqp); */
*O_dqpp = dqp; list_move(&dqp->q_hashlist, &qh->qh_list);
return 0; trace_xfs_dqlookup_done(dqp);
} *O_dqpp = dqp;
return 0;
} }
*O_dqpp = NULL; *O_dqpp = NULL;
ASSERT(mutex_is_locked(&qh->qh_lock)); return 1;
return (1);
} }
/* /*
...@@ -1033,8 +1000,10 @@ xfs_qm_dqput( ...@@ -1033,8 +1000,10 @@ xfs_qm_dqput(
if (--dqp->q_nrefs == 0) { if (--dqp->q_nrefs == 0) {
trace_xfs_dqput_free(dqp); trace_xfs_dqput_free(dqp);
list_add_tail(&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist); if (list_empty(&dqp->q_freelist)) {
xfs_Gqm->qm_dqfrlist_cnt++; 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 * If we just added a udquot to the freelist, then
......
...@@ -517,13 +517,12 @@ xfs_qm_dqpurge_int( ...@@ -517,13 +517,12 @@ xfs_qm_dqpurge_int(
* get them off mplist and hashlist, but leave them on freelist. * get them off mplist and hashlist, but leave them on freelist.
*/ */
list_for_each_entry_safe(dqp, n, &q->qi_dqlist, q_mplist) { list_for_each_entry_safe(dqp, n, &q->qi_dqlist, q_mplist) {
/* xfs_dqlock(dqp);
* It's OK to look at the type without taking dqlock here. if ((dqp->dq_flags & dqtype) == 0) {
* We're holding the mplist lock here, and that's needed for xfs_dqunlock(dqp);
* a dqreclaim.
*/
if ((dqp->dq_flags & dqtype) == 0)
continue; continue;
}
xfs_dqunlock(dqp);
if (!mutex_trylock(&dqp->q_hash->qh_lock)) { if (!mutex_trylock(&dqp->q_hash->qh_lock)) {
nrecl = q->qi_dqreclaims; nrecl = q->qi_dqreclaims;
...@@ -1692,14 +1691,15 @@ xfs_qm_dqreclaim_one(void) ...@@ -1692,14 +1691,15 @@ xfs_qm_dqreclaim_one(void)
xfs_dqlock(dqp); xfs_dqlock(dqp);
/* /*
* We are racing with dqlookup here. Naturally we don't * This dquot has already been grabbed by dqlookup.
* want to reclaim a dquot that lookup wants. We release the * Remove it from the freelist and try again.
* freelist lock and start over, so that lookup will grab
* both the dquot and the freelistlock.
*/ */
if (dqp->dq_flags & XFS_DQ_WANT) { if (dqp->q_nrefs) {
trace_xfs_dqreclaim_want(dqp); trace_xfs_dqreclaim_want(dqp);
XQM_STATS_INC(xqmstats.xs_qm_dqwants); XQM_STATS_INC(xqmstats.xs_qm_dqwants);
list_del_init(&dqp->q_freelist);
xfs_Gqm->qm_dqfrlist_cnt--;
restarts++; restarts++;
startagain = 1; startagain = 1;
goto dqunlock; goto dqunlock;
......
...@@ -87,7 +87,6 @@ typedef struct xfs_dqblk { ...@@ -87,7 +87,6 @@ typedef struct xfs_dqblk {
#define XFS_DQ_PROJ 0x0002 /* project quota */ #define XFS_DQ_PROJ 0x0002 /* project quota */
#define XFS_DQ_GROUP 0x0004 /* a group quota */ #define XFS_DQ_GROUP 0x0004 /* a group quota */
#define XFS_DQ_DIRTY 0x0008 /* dquot is dirty */ #define XFS_DQ_DIRTY 0x0008 /* dquot is dirty */
#define XFS_DQ_WANT 0x0010 /* for lookup/reclaim race */
#define XFS_DQ_ALLTYPES (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP) #define XFS_DQ_ALLTYPES (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP)
...@@ -95,8 +94,7 @@ typedef struct xfs_dqblk { ...@@ -95,8 +94,7 @@ typedef struct xfs_dqblk {
{ XFS_DQ_USER, "USER" }, \ { XFS_DQ_USER, "USER" }, \
{ XFS_DQ_PROJ, "PROJ" }, \ { XFS_DQ_PROJ, "PROJ" }, \
{ XFS_DQ_GROUP, "GROUP" }, \ { XFS_DQ_GROUP, "GROUP" }, \
{ XFS_DQ_DIRTY, "DIRTY" }, \ { XFS_DQ_DIRTY, "DIRTY" }
{ XFS_DQ_WANT, "WANT" }
/* /*
* In the worst case, when both user and group quotas are on, * In the worst case, when both user and group quotas are on,
......
...@@ -743,8 +743,6 @@ DEFINE_DQUOT_EVENT(xfs_dqtobp_read); ...@@ -743,8 +743,6 @@ DEFINE_DQUOT_EVENT(xfs_dqtobp_read);
DEFINE_DQUOT_EVENT(xfs_dqread); DEFINE_DQUOT_EVENT(xfs_dqread);
DEFINE_DQUOT_EVENT(xfs_dqread_fail); DEFINE_DQUOT_EVENT(xfs_dqread_fail);
DEFINE_DQUOT_EVENT(xfs_dqlookup_found); DEFINE_DQUOT_EVENT(xfs_dqlookup_found);
DEFINE_DQUOT_EVENT(xfs_dqlookup_want);
DEFINE_DQUOT_EVENT(xfs_dqlookup_freelist);
DEFINE_DQUOT_EVENT(xfs_dqlookup_done); DEFINE_DQUOT_EVENT(xfs_dqlookup_done);
DEFINE_DQUOT_EVENT(xfs_dqget_hit); DEFINE_DQUOT_EVENT(xfs_dqget_hit);
DEFINE_DQUOT_EVENT(xfs_dqget_miss); DEFINE_DQUOT_EVENT(xfs_dqget_miss);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册