xfs: convert the dquot free list to use list heads
Convert the dquot free list on the filesystem to use listhead infrastructure rather than the roll-your-own in the quota code. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
e6a81f13aa
commit
3a8406f6d6
6 changed files with 72 additions and 165 deletions
|
@ -101,7 +101,7 @@ xfs_qm_dqinit(
|
||||||
* No need to re-initialize these if this is a reclaimed dquot.
|
* No need to re-initialize these if this is a reclaimed dquot.
|
||||||
*/
|
*/
|
||||||
if (brandnewdquot) {
|
if (brandnewdquot) {
|
||||||
dqp->dq_flnext = dqp->dq_flprev = dqp;
|
INIT_LIST_HEAD(&dqp->q_freelist);
|
||||||
mutex_init(&dqp->q_qlock);
|
mutex_init(&dqp->q_qlock);
|
||||||
init_waitqueue_head(&dqp->q_pinwait);
|
init_waitqueue_head(&dqp->q_pinwait);
|
||||||
|
|
||||||
|
@ -119,20 +119,20 @@ xfs_qm_dqinit(
|
||||||
* Only the q_core portion was zeroed in dqreclaim_one().
|
* Only the q_core portion was zeroed in dqreclaim_one().
|
||||||
* So, we need to reset others.
|
* So, we need to reset others.
|
||||||
*/
|
*/
|
||||||
dqp->q_nrefs = 0;
|
dqp->q_nrefs = 0;
|
||||||
dqp->q_blkno = 0;
|
dqp->q_blkno = 0;
|
||||||
INIT_LIST_HEAD(&dqp->q_mplist);
|
INIT_LIST_HEAD(&dqp->q_mplist);
|
||||||
INIT_LIST_HEAD(&dqp->q_hashlist);
|
INIT_LIST_HEAD(&dqp->q_hashlist);
|
||||||
dqp->q_bufoffset = 0;
|
dqp->q_bufoffset = 0;
|
||||||
dqp->q_fileoffset = 0;
|
dqp->q_fileoffset = 0;
|
||||||
dqp->q_transp = NULL;
|
dqp->q_transp = NULL;
|
||||||
dqp->q_gdquot = NULL;
|
dqp->q_gdquot = NULL;
|
||||||
dqp->q_res_bcount = 0;
|
dqp->q_res_bcount = 0;
|
||||||
dqp->q_res_icount = 0;
|
dqp->q_res_icount = 0;
|
||||||
dqp->q_res_rtbcount = 0;
|
dqp->q_res_rtbcount = 0;
|
||||||
atomic_set(&dqp->q_pincount, 0);
|
atomic_set(&dqp->q_pincount, 0);
|
||||||
dqp->q_hash = NULL;
|
dqp->q_hash = NULL;
|
||||||
ASSERT(dqp->dq_flnext == dqp->dq_flprev);
|
ASSERT(list_empty(&dqp->q_freelist));
|
||||||
|
|
||||||
trace_xfs_dqreuse(dqp);
|
trace_xfs_dqreuse(dqp);
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ void
|
||||||
xfs_qm_dqdestroy(
|
xfs_qm_dqdestroy(
|
||||||
xfs_dquot_t *dqp)
|
xfs_dquot_t *dqp)
|
||||||
{
|
{
|
||||||
ASSERT(! XFS_DQ_IS_ON_FREELIST(dqp));
|
ASSERT(list_empty(&dqp->q_freelist));
|
||||||
|
|
||||||
mutex_destroy(&dqp->q_qlock);
|
mutex_destroy(&dqp->q_qlock);
|
||||||
sv_destroy(&dqp->q_pinwait);
|
sv_destroy(&dqp->q_pinwait);
|
||||||
|
@ -775,8 +775,8 @@ xfs_qm_dqlookup(
|
||||||
|
|
||||||
xfs_dqlock(dqp);
|
xfs_dqlock(dqp);
|
||||||
if (dqp->q_nrefs == 0) {
|
if (dqp->q_nrefs == 0) {
|
||||||
ASSERT (XFS_DQ_IS_ON_FREELIST(dqp));
|
ASSERT(!list_empty(&dqp->q_freelist));
|
||||||
if (! xfs_qm_freelist_lock_nowait(xfs_Gqm)) {
|
if (!mutex_trylock(&xfs_Gqm->qm_dqfrlist_lock)) {
|
||||||
trace_xfs_dqlookup_want(dqp);
|
trace_xfs_dqlookup_want(dqp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -786,7 +786,7 @@ xfs_qm_dqlookup(
|
||||||
*/
|
*/
|
||||||
dqp->dq_flags |= XFS_DQ_WANT;
|
dqp->dq_flags |= XFS_DQ_WANT;
|
||||||
xfs_dqunlock(dqp);
|
xfs_dqunlock(dqp);
|
||||||
xfs_qm_freelist_lock(xfs_Gqm);
|
mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
|
||||||
xfs_dqlock(dqp);
|
xfs_dqlock(dqp);
|
||||||
dqp->dq_flags &= ~(XFS_DQ_WANT);
|
dqp->dq_flags &= ~(XFS_DQ_WANT);
|
||||||
}
|
}
|
||||||
|
@ -801,27 +801,20 @@ xfs_qm_dqlookup(
|
||||||
|
|
||||||
if (flist_locked) {
|
if (flist_locked) {
|
||||||
if (dqp->q_nrefs != 0) {
|
if (dqp->q_nrefs != 0) {
|
||||||
xfs_qm_freelist_unlock(xfs_Gqm);
|
mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
|
||||||
flist_locked = B_FALSE;
|
flist_locked = B_FALSE;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/* take it off the freelist */
|
||||||
* take it off the freelist
|
|
||||||
*/
|
|
||||||
trace_xfs_dqlookup_freelist(dqp);
|
trace_xfs_dqlookup_freelist(dqp);
|
||||||
XQM_FREELIST_REMOVE(dqp);
|
list_del_init(&dqp->q_freelist);
|
||||||
/* xfs_qm_freelist_print(&(xfs_Gqm->
|
xfs_Gqm->qm_dqfrlist_cnt--;
|
||||||
qm_dqfreelist),
|
|
||||||
"after removal"); */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* grab a reference
|
|
||||||
*/
|
|
||||||
XFS_DQHOLD(dqp);
|
XFS_DQHOLD(dqp);
|
||||||
|
|
||||||
if (flist_locked)
|
if (flist_locked)
|
||||||
xfs_qm_freelist_unlock(xfs_Gqm);
|
mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
|
||||||
/*
|
/*
|
||||||
* move the dquot to the front of the hashchain
|
* move the dquot to the front of the hashchain
|
||||||
*/
|
*/
|
||||||
|
@ -1075,10 +1068,10 @@ xfs_qm_dqput(
|
||||||
* drop the dqlock and acquire the freelist and dqlock
|
* drop the dqlock and acquire the freelist and dqlock
|
||||||
* in the right order; but try to get it out-of-order first
|
* in the right order; but try to get it out-of-order first
|
||||||
*/
|
*/
|
||||||
if (! xfs_qm_freelist_lock_nowait(xfs_Gqm)) {
|
if (!mutex_trylock(&xfs_Gqm->qm_dqfrlist_lock)) {
|
||||||
trace_xfs_dqput_wait(dqp);
|
trace_xfs_dqput_wait(dqp);
|
||||||
xfs_dqunlock(dqp);
|
xfs_dqunlock(dqp);
|
||||||
xfs_qm_freelist_lock(xfs_Gqm);
|
mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
|
||||||
xfs_dqlock(dqp);
|
xfs_dqlock(dqp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1089,10 +1082,8 @@ 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);
|
||||||
* insert at end of the freelist.
|
xfs_Gqm->qm_dqfrlist_cnt++;
|
||||||
*/
|
|
||||||
XQM_FREELIST_INSERT(&(xfs_Gqm->qm_dqfreelist), dqp);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we just added a udquot to the freelist, then
|
* If we just added a udquot to the freelist, then
|
||||||
|
@ -1107,10 +1098,6 @@ xfs_qm_dqput(
|
||||||
xfs_dqlock(gdqp);
|
xfs_dqlock(gdqp);
|
||||||
dqp->q_gdquot = NULL;
|
dqp->q_gdquot = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* xfs_qm_freelist_print(&(xfs_Gqm->qm_dqfreelist),
|
|
||||||
"@@@@@++ Free list (after append) @@@@@+");
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
xfs_dqunlock(dqp);
|
xfs_dqunlock(dqp);
|
||||||
|
|
||||||
|
@ -1122,7 +1109,7 @@ xfs_qm_dqput(
|
||||||
break;
|
break;
|
||||||
dqp = gdqp;
|
dqp = gdqp;
|
||||||
}
|
}
|
||||||
xfs_qm_freelist_unlock(xfs_Gqm);
|
mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1396,7 +1383,7 @@ xfs_qm_dqpurge(
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(XFS_DQ_IS_ON_FREELIST(dqp));
|
ASSERT(!list_empty(&dqp->q_freelist));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we're turning off quotas, we have to make sure that, for
|
* If we're turning off quotas, we have to make sure that, for
|
||||||
|
@ -1450,7 +1437,7 @@ xfs_qm_dqpurge(
|
||||||
* XXX Move this to the front of the freelist, if we can get the
|
* XXX Move this to the front of the freelist, if we can get the
|
||||||
* freelist lock.
|
* freelist lock.
|
||||||
*/
|
*/
|
||||||
ASSERT(XFS_DQ_IS_ON_FREELIST(dqp));
|
ASSERT(!list_empty(&dqp->q_freelist));
|
||||||
|
|
||||||
dqp->q_mount = NULL;
|
dqp->q_mount = NULL;
|
||||||
dqp->q_hash = NULL;
|
dqp->q_hash = NULL;
|
||||||
|
|
|
@ -50,8 +50,6 @@ struct xfs_trans;
|
||||||
* iterations because of locking considerations.
|
* iterations because of locking considerations.
|
||||||
*/
|
*/
|
||||||
typedef struct xfs_dqmarker {
|
typedef struct xfs_dqmarker {
|
||||||
struct xfs_dquot*dqm_flnext; /* link to freelist: must be first */
|
|
||||||
struct xfs_dquot*dqm_flprev;
|
|
||||||
uint dqm_flags; /* various flags (XFS_DQ_*) */
|
uint dqm_flags; /* various flags (XFS_DQ_*) */
|
||||||
} xfs_dqmarker_t;
|
} xfs_dqmarker_t;
|
||||||
|
|
||||||
|
@ -60,8 +58,9 @@ typedef struct xfs_dqmarker {
|
||||||
*/
|
*/
|
||||||
typedef struct xfs_dquot {
|
typedef struct xfs_dquot {
|
||||||
xfs_dqmarker_t q_lists; /* list ptrs, q_flags (marker) */
|
xfs_dqmarker_t q_lists; /* list ptrs, q_flags (marker) */
|
||||||
|
struct list_head q_freelist; /* global free list of dquots */
|
||||||
struct list_head q_mplist; /* mount's list of dquots */
|
struct list_head q_mplist; /* mount's list of dquots */
|
||||||
struct list_head q_hashlist; /* mount's list of dquots */
|
struct list_head q_hashlist; /* gloabl hash list of dquots */
|
||||||
xfs_dqhash_t *q_hash; /* the hashchain header */
|
xfs_dqhash_t *q_hash; /* the hashchain header */
|
||||||
struct xfs_mount*q_mount; /* filesystem this relates to */
|
struct xfs_mount*q_mount; /* filesystem this relates to */
|
||||||
struct xfs_trans*q_transp; /* trans this belongs to currently */
|
struct xfs_trans*q_transp; /* trans this belongs to currently */
|
||||||
|
|
|
@ -67,9 +67,6 @@ static cred_t xfs_zerocr;
|
||||||
STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int);
|
STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int);
|
||||||
STATIC void xfs_qm_list_destroy(xfs_dqlist_t *);
|
STATIC void xfs_qm_list_destroy(xfs_dqlist_t *);
|
||||||
|
|
||||||
STATIC void xfs_qm_freelist_init(xfs_frlist_t *);
|
|
||||||
STATIC void xfs_qm_freelist_destroy(xfs_frlist_t *);
|
|
||||||
|
|
||||||
STATIC int xfs_qm_init_quotainos(xfs_mount_t *);
|
STATIC int xfs_qm_init_quotainos(xfs_mount_t *);
|
||||||
STATIC int xfs_qm_init_quotainfo(xfs_mount_t *);
|
STATIC int xfs_qm_init_quotainfo(xfs_mount_t *);
|
||||||
STATIC int xfs_qm_shake(int, gfp_t);
|
STATIC int xfs_qm_shake(int, gfp_t);
|
||||||
|
@ -148,7 +145,9 @@ xfs_Gqm_init(void)
|
||||||
/*
|
/*
|
||||||
* Freelist of all dquots of all file systems
|
* Freelist of all dquots of all file systems
|
||||||
*/
|
*/
|
||||||
xfs_qm_freelist_init(&(xqm->qm_dqfreelist));
|
INIT_LIST_HEAD(&xqm->qm_dqfrlist);
|
||||||
|
xqm->qm_dqfrlist_cnt = 0;
|
||||||
|
mutex_init(&xqm->qm_dqfrlist_lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* dquot zone. we register our own low-memory callback.
|
* dquot zone. we register our own low-memory callback.
|
||||||
|
@ -193,6 +192,7 @@ 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);
|
||||||
|
@ -208,7 +208,21 @@ xfs_qm_destroy(
|
||||||
xqm->qm_usr_dqhtable = NULL;
|
xqm->qm_usr_dqhtable = NULL;
|
||||||
xqm->qm_grp_dqhtable = NULL;
|
xqm->qm_grp_dqhtable = NULL;
|
||||||
xqm->qm_dqhashmask = 0;
|
xqm->qm_dqhashmask = 0;
|
||||||
xfs_qm_freelist_destroy(&(xqm->qm_dqfreelist));
|
|
||||||
|
/* frlist cleanup */
|
||||||
|
mutex_lock(&xqm->qm_dqfrlist_lock);
|
||||||
|
list_for_each_entry_safe(dqp, n, &xqm->qm_dqfrlist, q_freelist) {
|
||||||
|
xfs_dqlock(dqp);
|
||||||
|
#ifdef QUOTADEBUG
|
||||||
|
cmn_err(CE_DEBUG, "FREELIST destroy 0x%p", dqp);
|
||||||
|
#endif
|
||||||
|
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);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
mutex_destroy(&qcheck_lock);
|
mutex_destroy(&qcheck_lock);
|
||||||
#endif
|
#endif
|
||||||
|
@ -260,7 +274,7 @@ STATIC void
|
||||||
xfs_qm_rele_quotafs_ref(
|
xfs_qm_rele_quotafs_ref(
|
||||||
struct xfs_mount *mp)
|
struct xfs_mount *mp)
|
||||||
{
|
{
|
||||||
xfs_dquot_t *dqp, *nextdqp;
|
xfs_dquot_t *dqp, *n;
|
||||||
|
|
||||||
ASSERT(xfs_Gqm);
|
ASSERT(xfs_Gqm);
|
||||||
ASSERT(xfs_Gqm->qm_nrefs > 0);
|
ASSERT(xfs_Gqm->qm_nrefs > 0);
|
||||||
|
@ -268,26 +282,24 @@ xfs_qm_rele_quotafs_ref(
|
||||||
/*
|
/*
|
||||||
* Go thru the freelist and destroy all inactive dquots.
|
* Go thru the freelist and destroy all inactive dquots.
|
||||||
*/
|
*/
|
||||||
xfs_qm_freelist_lock(xfs_Gqm);
|
mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
|
||||||
|
|
||||||
for (dqp = xfs_Gqm->qm_dqfreelist.qh_next;
|
list_for_each_entry_safe(dqp, n, &xfs_Gqm->qm_dqfrlist, q_freelist) {
|
||||||
dqp != (xfs_dquot_t *)&(xfs_Gqm->qm_dqfreelist); ) {
|
|
||||||
xfs_dqlock(dqp);
|
xfs_dqlock(dqp);
|
||||||
nextdqp = dqp->dq_flnext;
|
|
||||||
if (dqp->dq_flags & XFS_DQ_INACTIVE) {
|
if (dqp->dq_flags & XFS_DQ_INACTIVE) {
|
||||||
ASSERT(dqp->q_mount == NULL);
|
ASSERT(dqp->q_mount == NULL);
|
||||||
ASSERT(! XFS_DQ_IS_DIRTY(dqp));
|
ASSERT(! XFS_DQ_IS_DIRTY(dqp));
|
||||||
ASSERT(list_empty(&dqp->q_hashlist));
|
ASSERT(list_empty(&dqp->q_hashlist));
|
||||||
ASSERT(list_empty(&dqp->q_mplist));
|
ASSERT(list_empty(&dqp->q_mplist));
|
||||||
XQM_FREELIST_REMOVE(dqp);
|
list_del_init(&dqp->q_freelist);
|
||||||
|
xfs_Gqm->qm_dqfrlist_cnt--;
|
||||||
xfs_dqunlock(dqp);
|
xfs_dqunlock(dqp);
|
||||||
xfs_qm_dqdestroy(dqp);
|
xfs_qm_dqdestroy(dqp);
|
||||||
} else {
|
} else {
|
||||||
xfs_dqunlock(dqp);
|
xfs_dqunlock(dqp);
|
||||||
}
|
}
|
||||||
dqp = nextdqp;
|
|
||||||
}
|
}
|
||||||
xfs_qm_freelist_unlock(xfs_Gqm);
|
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
|
||||||
|
@ -1943,9 +1955,9 @@ xfs_qm_dqreclaim_one(void)
|
||||||
|
|
||||||
/* lockorder: hashchainlock, freelistlock, mplistlock, dqlock, dqflock */
|
/* lockorder: hashchainlock, freelistlock, mplistlock, dqlock, dqflock */
|
||||||
startagain:
|
startagain:
|
||||||
xfs_qm_freelist_lock(xfs_Gqm);
|
mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
|
||||||
|
|
||||||
FOREACH_DQUOT_IN_FREELIST(dqp, &(xfs_Gqm->qm_dqfreelist)) {
|
list_for_each_entry(dqp, &xfs_Gqm->qm_dqfrlist, q_freelist) {
|
||||||
struct xfs_mount *mp = dqp->q_mount;
|
struct xfs_mount *mp = dqp->q_mount;
|
||||||
xfs_dqlock(dqp);
|
xfs_dqlock(dqp);
|
||||||
|
|
||||||
|
@ -1961,7 +1973,7 @@ startagain:
|
||||||
trace_xfs_dqreclaim_want(dqp);
|
trace_xfs_dqreclaim_want(dqp);
|
||||||
|
|
||||||
xfs_dqunlock(dqp);
|
xfs_dqunlock(dqp);
|
||||||
xfs_qm_freelist_unlock(xfs_Gqm);
|
mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
|
||||||
if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
|
if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
|
||||||
return NULL;
|
return NULL;
|
||||||
XQM_STATS_INC(xqmstats.xs_qm_dqwants);
|
XQM_STATS_INC(xqmstats.xs_qm_dqwants);
|
||||||
|
@ -1978,7 +1990,8 @@ startagain:
|
||||||
ASSERT(! XFS_DQ_IS_DIRTY(dqp));
|
ASSERT(! XFS_DQ_IS_DIRTY(dqp));
|
||||||
ASSERT(list_empty(&dqp->q_hashlist));
|
ASSERT(list_empty(&dqp->q_hashlist));
|
||||||
ASSERT(list_empty(&dqp->q_mplist));
|
ASSERT(list_empty(&dqp->q_mplist));
|
||||||
XQM_FREELIST_REMOVE(dqp);
|
list_del_init(&dqp->q_freelist);
|
||||||
|
xfs_Gqm->qm_dqfrlist_cnt--;
|
||||||
xfs_dqunlock(dqp);
|
xfs_dqunlock(dqp);
|
||||||
dqpout = dqp;
|
dqpout = dqp;
|
||||||
XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims);
|
XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims);
|
||||||
|
@ -2043,7 +2056,7 @@ startagain:
|
||||||
mutex_unlock(&dqp->q_hash->qh_lock);
|
mutex_unlock(&dqp->q_hash->qh_lock);
|
||||||
xfs_dqfunlock(dqp);
|
xfs_dqfunlock(dqp);
|
||||||
xfs_dqunlock(dqp);
|
xfs_dqunlock(dqp);
|
||||||
xfs_qm_freelist_unlock(xfs_Gqm);
|
mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
|
||||||
if (restarts++ >= XFS_QM_RECLAIM_MAX_RESTARTS)
|
if (restarts++ >= XFS_QM_RECLAIM_MAX_RESTARTS)
|
||||||
return NULL;
|
return NULL;
|
||||||
goto startagain;
|
goto startagain;
|
||||||
|
@ -2055,7 +2068,8 @@ startagain:
|
||||||
mp->m_quotainfo->qi_dqreclaims++;
|
mp->m_quotainfo->qi_dqreclaims++;
|
||||||
list_del_init(&dqp->q_hashlist);
|
list_del_init(&dqp->q_hashlist);
|
||||||
dqp->q_hash->qh_version++;
|
dqp->q_hash->qh_version++;
|
||||||
XQM_FREELIST_REMOVE(dqp);
|
list_del_init(&dqp->q_freelist);
|
||||||
|
xfs_Gqm->qm_dqfrlist_cnt--;
|
||||||
dqpout = dqp;
|
dqpout = dqp;
|
||||||
mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
|
mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
|
||||||
mutex_unlock(&dqp->q_hash->qh_lock);
|
mutex_unlock(&dqp->q_hash->qh_lock);
|
||||||
|
@ -2067,7 +2081,7 @@ dqfunlock:
|
||||||
if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
|
if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
xfs_qm_freelist_unlock(xfs_Gqm);
|
mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
|
||||||
return dqpout;
|
return dqpout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2110,7 +2124,7 @@ xfs_qm_shake(int nr_to_scan, gfp_t gfp_mask)
|
||||||
if (!xfs_Gqm)
|
if (!xfs_Gqm)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
nfree = xfs_Gqm->qm_dqfreelist.qh_nelems; /* free dquots */
|
nfree = xfs_Gqm->qm_dqfrlist_cnt; /* free dquots */
|
||||||
/* incore dquots in all f/s's */
|
/* incore dquots in all f/s's */
|
||||||
ndqused = atomic_read(&xfs_Gqm->qm_totaldquots) - nfree;
|
ndqused = atomic_read(&xfs_Gqm->qm_totaldquots) - nfree;
|
||||||
|
|
||||||
|
@ -2550,66 +2564,3 @@ xfs_qm_vop_create_dqattach(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------- list stuff -----------------*/
|
|
||||||
STATIC void
|
|
||||||
xfs_qm_freelist_init(xfs_frlist_t *ql)
|
|
||||||
{
|
|
||||||
ql->qh_next = ql->qh_prev = (xfs_dquot_t *) ql;
|
|
||||||
mutex_init(&ql->qh_lock);
|
|
||||||
ql->qh_version = 0;
|
|
||||||
ql->qh_nelems = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
xfs_qm_freelist_destroy(xfs_frlist_t *ql)
|
|
||||||
{
|
|
||||||
xfs_dquot_t *dqp, *nextdqp;
|
|
||||||
|
|
||||||
mutex_lock(&ql->qh_lock);
|
|
||||||
for (dqp = ql->qh_next;
|
|
||||||
dqp != (xfs_dquot_t *)ql; ) {
|
|
||||||
xfs_dqlock(dqp);
|
|
||||||
nextdqp = dqp->dq_flnext;
|
|
||||||
#ifdef QUOTADEBUG
|
|
||||||
cmn_err(CE_DEBUG, "FREELIST destroy 0x%p", dqp);
|
|
||||||
#endif
|
|
||||||
XQM_FREELIST_REMOVE(dqp);
|
|
||||||
xfs_dqunlock(dqp);
|
|
||||||
xfs_qm_dqdestroy(dqp);
|
|
||||||
dqp = nextdqp;
|
|
||||||
}
|
|
||||||
mutex_unlock(&ql->qh_lock);
|
|
||||||
mutex_destroy(&ql->qh_lock);
|
|
||||||
|
|
||||||
ASSERT(ql->qh_nelems == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void
|
|
||||||
xfs_qm_freelist_insert(xfs_frlist_t *ql, xfs_dquot_t *dq)
|
|
||||||
{
|
|
||||||
dq->dq_flnext = ql->qh_next;
|
|
||||||
dq->dq_flprev = (xfs_dquot_t *)ql;
|
|
||||||
ql->qh_next = dq;
|
|
||||||
dq->dq_flnext->dq_flprev = dq;
|
|
||||||
xfs_Gqm->qm_dqfreelist.qh_nelems++;
|
|
||||||
xfs_Gqm->qm_dqfreelist.qh_version++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
xfs_qm_freelist_unlink(xfs_dquot_t *dq)
|
|
||||||
{
|
|
||||||
xfs_dquot_t *next = dq->dq_flnext;
|
|
||||||
xfs_dquot_t *prev = dq->dq_flprev;
|
|
||||||
|
|
||||||
next->dq_flprev = prev;
|
|
||||||
prev->dq_flnext = next;
|
|
||||||
dq->dq_flnext = dq->dq_flprev = dq;
|
|
||||||
xfs_Gqm->qm_dqfreelist.qh_nelems--;
|
|
||||||
xfs_Gqm->qm_dqfreelist.qh_version++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
xfs_qm_freelist_append(xfs_frlist_t *ql, xfs_dquot_t *dq)
|
|
||||||
{
|
|
||||||
xfs_qm_freelist_insert((xfs_frlist_t *)ql->qh_prev, dq);
|
|
||||||
}
|
|
||||||
|
|
|
@ -72,17 +72,6 @@ extern kmem_zone_t *qm_dqtrxzone;
|
||||||
#define XFS_QM_MAX_DQCLUSTER_LOGSZ 3
|
#define XFS_QM_MAX_DQCLUSTER_LOGSZ 3
|
||||||
|
|
||||||
typedef xfs_dqhash_t xfs_dqlist_t;
|
typedef xfs_dqhash_t xfs_dqlist_t;
|
||||||
/*
|
|
||||||
* The freelist head. The first two fields match the first two in the
|
|
||||||
* xfs_dquot_t structure (in xfs_dqmarker_t)
|
|
||||||
*/
|
|
||||||
typedef struct xfs_frlist {
|
|
||||||
struct xfs_dquot *qh_next;
|
|
||||||
struct xfs_dquot *qh_prev;
|
|
||||||
struct mutex qh_lock;
|
|
||||||
uint qh_version;
|
|
||||||
uint qh_nelems;
|
|
||||||
} xfs_frlist_t;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Quota Manager (global) structure. Lives only in core.
|
* Quota Manager (global) structure. Lives only in core.
|
||||||
|
@ -91,7 +80,9 @@ typedef struct xfs_qm {
|
||||||
xfs_dqlist_t *qm_usr_dqhtable;/* udquot hash table */
|
xfs_dqlist_t *qm_usr_dqhtable;/* udquot hash table */
|
||||||
xfs_dqlist_t *qm_grp_dqhtable;/* gdquot hash table */
|
xfs_dqlist_t *qm_grp_dqhtable;/* gdquot hash table */
|
||||||
uint qm_dqhashmask; /* # buckets in dq hashtab - 1 */
|
uint qm_dqhashmask; /* # buckets in dq hashtab - 1 */
|
||||||
xfs_frlist_t qm_dqfreelist; /* freelist of dquots */
|
struct list_head qm_dqfrlist; /* freelist of dquots */
|
||||||
|
struct mutex qm_dqfrlist_lock;
|
||||||
|
int qm_dqfrlist_cnt;
|
||||||
atomic_t qm_totaldquots; /* total incore dquots */
|
atomic_t qm_totaldquots; /* total incore dquots */
|
||||||
uint qm_nrefs; /* file systems with quota on */
|
uint qm_nrefs; /* file systems with quota on */
|
||||||
int qm_dqfree_ratio;/* ratio of free to inuse dquots */
|
int qm_dqfree_ratio;/* ratio of free to inuse dquots */
|
||||||
|
@ -177,10 +168,6 @@ extern int xfs_qm_scall_getqstat(xfs_mount_t *, fs_quota_stat_t *);
|
||||||
extern int xfs_qm_scall_quotaon(xfs_mount_t *, uint);
|
extern int xfs_qm_scall_quotaon(xfs_mount_t *, uint);
|
||||||
extern int xfs_qm_scall_quotaoff(xfs_mount_t *, uint);
|
extern int xfs_qm_scall_quotaoff(xfs_mount_t *, uint);
|
||||||
|
|
||||||
/* list stuff */
|
|
||||||
extern void xfs_qm_freelist_append(xfs_frlist_t *, xfs_dquot_t *);
|
|
||||||
extern void xfs_qm_freelist_unlink(xfs_dquot_t *);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
extern int xfs_qm_internalqcheck(xfs_mount_t *);
|
extern int xfs_qm_internalqcheck(xfs_mount_t *);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -55,7 +55,7 @@ static int xqm_proc_show(struct seq_file *m, void *v)
|
||||||
ndquot,
|
ndquot,
|
||||||
xfs_Gqm? atomic_read(&xfs_Gqm->qm_totaldquots) : 0,
|
xfs_Gqm? atomic_read(&xfs_Gqm->qm_totaldquots) : 0,
|
||||||
xfs_Gqm? xfs_Gqm->qm_dqfree_ratio : 0,
|
xfs_Gqm? xfs_Gqm->qm_dqfree_ratio : 0,
|
||||||
xfs_Gqm? xfs_Gqm->qm_dqfreelist.qh_nelems : 0);
|
xfs_Gqm? xfs_Gqm->qm_dqfrlist_cnt : 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,13 +40,6 @@
|
||||||
#define XFS_QI_IWARNLIMIT(mp) ((mp)->m_quotainfo->qi_iwarnlimit)
|
#define XFS_QI_IWARNLIMIT(mp) ((mp)->m_quotainfo->qi_iwarnlimit)
|
||||||
#define XFS_QI_QOFFLOCK(mp) ((mp)->m_quotainfo->qi_quotaofflock)
|
#define XFS_QI_QOFFLOCK(mp) ((mp)->m_quotainfo->qi_quotaofflock)
|
||||||
|
|
||||||
#define xfs_qm_freelist_lock(qm) \
|
|
||||||
mutex_lock(&((qm)->qm_dqfreelist.qh_lock))
|
|
||||||
#define xfs_qm_freelist_lock_nowait(qm) \
|
|
||||||
mutex_trylock(&((qm)->qm_dqfreelist.qh_lock))
|
|
||||||
#define xfs_qm_freelist_unlock(qm) \
|
|
||||||
mutex_unlock(&((qm)->qm_dqfreelist.qh_lock))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hash into a bucket in the dquot hash table, based on <mp, id>.
|
* Hash into a bucket in the dquot hash table, based on <mp, id>.
|
||||||
*/
|
*/
|
||||||
|
@ -72,16 +65,6 @@
|
||||||
!dqp->q_core.d_rtbcount && \
|
!dqp->q_core.d_rtbcount && \
|
||||||
!dqp->q_core.d_icount)
|
!dqp->q_core.d_icount)
|
||||||
|
|
||||||
#define FOREACH_DQUOT_IN_FREELIST(dqp, qlist) \
|
|
||||||
for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \
|
|
||||||
(dqp) = (dqp)->dq_flnext)
|
|
||||||
|
|
||||||
#define XQM_FREELIST_INSERT(h, dqp) \
|
|
||||||
xfs_qm_freelist_append(h, dqp)
|
|
||||||
|
|
||||||
#define XQM_FREELIST_REMOVE(dqp) \
|
|
||||||
xfs_qm_freelist_unlink(dqp)
|
|
||||||
|
|
||||||
#define XFS_DQ_IS_LOGITEM_INITD(dqp) ((dqp)->q_logitem.qli_dquot == (dqp))
|
#define XFS_DQ_IS_LOGITEM_INITD(dqp) ((dqp)->q_logitem.qli_dquot == (dqp))
|
||||||
|
|
||||||
#define XFS_QM_DQP_TO_DQACCT(tp, dqp) (XFS_QM_ISUDQ(dqp) ? \
|
#define XFS_QM_DQP_TO_DQACCT(tp, dqp) (XFS_QM_ISUDQ(dqp) ? \
|
||||||
|
|
Loading…
Add table
Reference in a new issue