Commit 80a376bf authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Ben Myers

xfs: remove XFS_DQ_INACTIVE

Free dquots when purging them during umount instead of keeping them around
on the freelist in a degraded state.  The out of order locking in
xfs_qm_dqpurge will be removed again later in this series.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarBen Myers <bpm@sgi.com>
parent 497507b9
...@@ -1302,6 +1302,14 @@ xfs_qm_dqpurge( ...@@ -1302,6 +1302,14 @@ xfs_qm_dqpurge(
ASSERT(mutex_is_locked(&mp->m_quotainfo->qi_dqlist_lock)); ASSERT(mutex_is_locked(&mp->m_quotainfo->qi_dqlist_lock));
ASSERT(mutex_is_locked(&dqp->q_hash->qh_lock)); ASSERT(mutex_is_locked(&dqp->q_hash->qh_lock));
/*
* XXX(hch): horrible locking order, will get cleaned up ASAP.
*/
if (!mutex_trylock(&xfs_Gqm->qm_dqfrlist_lock)) {
mutex_unlock(&dqp->q_hash->qh_lock);
return 1;
}
xfs_dqlock(dqp); xfs_dqlock(dqp);
/* /*
* We really can't afford to purge a dquot that is * We really can't afford to purge a dquot that is
...@@ -1364,25 +1372,23 @@ xfs_qm_dqpurge( ...@@ -1364,25 +1372,23 @@ xfs_qm_dqpurge(
list_del_init(&dqp->q_hashlist); list_del_init(&dqp->q_hashlist);
qh->qh_version++; qh->qh_version++;
list_del_init(&dqp->q_mplist); list_del_init(&dqp->q_mplist);
mp->m_quotainfo->qi_dqreclaims++; mp->m_quotainfo->qi_dqreclaims++;
mp->m_quotainfo->qi_dquots--; mp->m_quotainfo->qi_dquots--;
/*
* XXX Move this to the front of the freelist, if we can get the
* freelist lock.
*/
ASSERT(!list_empty(&dqp->q_freelist));
dqp->q_mount = NULL; list_del_init(&dqp->q_freelist);
dqp->q_hash = NULL; xfs_Gqm->qm_dqfrlist_cnt--;
dqp->dq_flags = XFS_DQ_INACTIVE;
memset(&dqp->q_core, 0, sizeof(dqp->q_core));
xfs_dqfunlock(dqp); xfs_dqfunlock(dqp);
xfs_dqunlock(dqp); xfs_dqunlock(dqp);
mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
mutex_unlock(&qh->qh_lock); mutex_unlock(&qh->qh_lock);
return (0);
}
xfs_qm_dqdestroy(dqp);
return 0;
}
/* /*
* Give the buffer a little push if it is incore and * Give the buffer a little push if it is incore and
......
...@@ -154,12 +154,17 @@ STATIC void ...@@ -154,12 +154,17 @@ STATIC void
xfs_qm_destroy( xfs_qm_destroy(
struct xfs_qm *xqm) struct xfs_qm *xqm)
{ {
struct xfs_dquot *dqp, *n;
int hsize, i; int hsize, i;
ASSERT(xqm != NULL); ASSERT(xqm != NULL);
ASSERT(xqm->qm_nrefs == 0); ASSERT(xqm->qm_nrefs == 0);
unregister_shrinker(&xfs_qm_shaker); unregister_shrinker(&xfs_qm_shaker);
mutex_lock(&xqm->qm_dqfrlist_lock);
ASSERT(list_empty(&xqm->qm_dqfrlist));
mutex_unlock(&xqm->qm_dqfrlist_lock);
hsize = xqm->qm_dqhashmask + 1; hsize = xqm->qm_dqhashmask + 1;
for (i = 0; i < hsize; i++) { for (i = 0; i < hsize; i++) {
xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i])); xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i]));
...@@ -171,17 +176,6 @@ xfs_qm_destroy( ...@@ -171,17 +176,6 @@ xfs_qm_destroy(
xqm->qm_grp_dqhtable = NULL; xqm->qm_grp_dqhtable = NULL;
xqm->qm_dqhashmask = 0; xqm->qm_dqhashmask = 0;
/* frlist cleanup */
mutex_lock(&xqm->qm_dqfrlist_lock);
list_for_each_entry_safe(dqp, n, &xqm->qm_dqfrlist, q_freelist) {
xfs_dqlock(dqp);
list_del_init(&dqp->q_freelist);
xfs_Gqm->qm_dqfrlist_cnt--;
xfs_dqunlock(dqp);
xfs_qm_dqdestroy(dqp);
}
mutex_unlock(&xqm->qm_dqfrlist_lock);
mutex_destroy(&xqm->qm_dqfrlist_lock);
kmem_free(xqm); kmem_free(xqm);
} }
...@@ -232,33 +226,9 @@ STATIC void ...@@ -232,33 +226,9 @@ STATIC void
xfs_qm_rele_quotafs_ref( xfs_qm_rele_quotafs_ref(
struct xfs_mount *mp) struct xfs_mount *mp)
{ {
xfs_dquot_t *dqp, *n;
ASSERT(xfs_Gqm); ASSERT(xfs_Gqm);
ASSERT(xfs_Gqm->qm_nrefs > 0); ASSERT(xfs_Gqm->qm_nrefs > 0);
/*
* Go thru the freelist and destroy all inactive dquots.
*/
mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
list_for_each_entry_safe(dqp, n, &xfs_Gqm->qm_dqfrlist, q_freelist) {
xfs_dqlock(dqp);
if (dqp->dq_flags & XFS_DQ_INACTIVE) {
ASSERT(dqp->q_mount == NULL);
ASSERT(! XFS_DQ_IS_DIRTY(dqp));
ASSERT(list_empty(&dqp->q_hashlist));
ASSERT(list_empty(&dqp->q_mplist));
list_del_init(&dqp->q_freelist);
xfs_Gqm->qm_dqfrlist_cnt--;
xfs_dqunlock(dqp);
xfs_qm_dqdestroy(dqp);
} else {
xfs_dqunlock(dqp);
}
}
mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
/* /*
* Destroy the entire XQM. If somebody mounts with quotaon, this'll * Destroy the entire XQM. If somebody mounts with quotaon, this'll
* be restarted. * be restarted.
...@@ -1728,8 +1698,6 @@ xfs_qm_dqreclaim_one(void) ...@@ -1728,8 +1698,6 @@ xfs_qm_dqreclaim_one(void)
* both the dquot and the freelistlock. * both the dquot and the freelistlock.
*/ */
if (dqp->dq_flags & XFS_DQ_WANT) { if (dqp->dq_flags & XFS_DQ_WANT) {
ASSERT(! (dqp->dq_flags & XFS_DQ_INACTIVE));
trace_xfs_dqreclaim_want(dqp); trace_xfs_dqreclaim_want(dqp);
XQM_STATS_INC(xqmstats.xs_qm_dqwants); XQM_STATS_INC(xqmstats.xs_qm_dqwants);
restarts++; restarts++;
...@@ -1737,23 +1705,6 @@ xfs_qm_dqreclaim_one(void) ...@@ -1737,23 +1705,6 @@ xfs_qm_dqreclaim_one(void)
goto dqunlock; goto dqunlock;
} }
/*
* If the dquot is inactive, we are assured that it is
* not on the mplist or the hashlist, and that makes our
* life easier.
*/
if (dqp->dq_flags & XFS_DQ_INACTIVE) {
ASSERT(mp == NULL);
ASSERT(! XFS_DQ_IS_DIRTY(dqp));
ASSERT(list_empty(&dqp->q_hashlist));
ASSERT(list_empty(&dqp->q_mplist));
list_del_init(&dqp->q_freelist);
xfs_Gqm->qm_dqfrlist_cnt--;
dqpout = dqp;
XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims);
goto dqunlock;
}
ASSERT(dqp->q_hash); ASSERT(dqp->q_hash);
ASSERT(!list_empty(&dqp->q_mplist)); ASSERT(!list_empty(&dqp->q_mplist));
......
...@@ -88,7 +88,6 @@ typedef struct xfs_dqblk { ...@@ -88,7 +88,6 @@ typedef struct xfs_dqblk {
#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_WANT 0x0010 /* for lookup/reclaim race */
#define XFS_DQ_INACTIVE 0x0020 /* dq off mplist & hashlist */
#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)
...@@ -97,8 +96,7 @@ typedef struct xfs_dqblk { ...@@ -97,8 +96,7 @@ typedef struct xfs_dqblk {
{ 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" }, \ { XFS_DQ_WANT, "WANT" }
{ XFS_DQ_INACTIVE, "INACTIVE" }
/* /*
* In the worst case, when both user and group quotas are on, * In the worst case, when both user and group quotas are on,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment