Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+17 −11
Original line number Diff line number Diff line
@@ -1302,6 +1302,14 @@ xfs_qm_dqpurge(
	ASSERT(mutex_is_locked(&mp->m_quotainfo->qi_dqlist_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);
	/*
	 * We really can't afford to purge a dquot that is
@@ -1364,25 +1372,23 @@ xfs_qm_dqpurge(

	list_del_init(&dqp->q_hashlist);
	qh->qh_version++;

	list_del_init(&dqp->q_mplist);
	mp->m_quotainfo->qi_dqreclaims++;
	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;
	dqp->q_hash = NULL;
	dqp->dq_flags = XFS_DQ_INACTIVE;
	memset(&dqp->q_core, 0, sizeof(dqp->q_core));
	list_del_init(&dqp->q_freelist);
	xfs_Gqm->qm_dqfrlist_cnt--;

	xfs_dqfunlock(dqp);
	xfs_dqunlock(dqp);

	mutex_unlock(&xfs_Gqm->qm_dqfrlist_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
+6 −55
Original line number Diff line number Diff line
@@ -154,12 +154,17 @@ STATIC void
xfs_qm_destroy(
	struct xfs_qm	*xqm)
{
	struct xfs_dquot *dqp, *n;
	int		hsize, i;

	ASSERT(xqm != NULL);
	ASSERT(xqm->qm_nrefs == 0);

	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;
	for (i = 0; i < hsize; i++) {
		xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i]));
@@ -171,17 +176,6 @@ xfs_qm_destroy(
	xqm->qm_grp_dqhtable = NULL;
	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);
}

@@ -232,33 +226,9 @@ STATIC void
xfs_qm_rele_quotafs_ref(
	struct xfs_mount *mp)
{
	xfs_dquot_t	*dqp, *n;

	ASSERT(xfs_Gqm);
	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
	 * be restarted.
@@ -1728,8 +1698,6 @@ xfs_qm_dqreclaim_one(void)
		 * both the dquot and the freelistlock.
		 */
		if (dqp->dq_flags & XFS_DQ_WANT) {
			ASSERT(! (dqp->dq_flags & XFS_DQ_INACTIVE));

			trace_xfs_dqreclaim_want(dqp);
			XQM_STATS_INC(xqmstats.xs_qm_dqwants);
			restarts++;
@@ -1737,23 +1705,6 @@ xfs_qm_dqreclaim_one(void)
			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(!list_empty(&dqp->q_mplist));

+1 −3
Original line number Diff line number Diff line
@@ -88,7 +88,6 @@ typedef struct xfs_dqblk {
#define XFS_DQ_GROUP		0x0004		/* a group quota */
#define XFS_DQ_DIRTY		0x0008		/* dquot is dirty */
#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)

@@ -97,8 +96,7 @@ typedef struct xfs_dqblk {
	{ XFS_DQ_PROJ,		"PROJ" }, \
	{ XFS_DQ_GROUP,		"GROUP" }, \
	{ XFS_DQ_DIRTY,		"DIRTY" }, \
	{ XFS_DQ_WANT,		"WANT" }, \
	{ XFS_DQ_INACTIVE,	"INACTIVE" }
	{ XFS_DQ_WANT,		"WANT" }

/*
 * In the worst case, when both user and group quotas are on,