xfs: convert the dquot hash list to use list heads
Convert the dquot hash 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
368e136174
commit
e6a81f13aa
|
@ -667,7 +667,6 @@ 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_want);
|
||||||
DEFINE_DQUOT_EVENT(xfs_dqlookup_freelist);
|
DEFINE_DQUOT_EVENT(xfs_dqlookup_freelist);
|
||||||
DEFINE_DQUOT_EVENT(xfs_dqlookup_move);
|
|
||||||
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);
|
||||||
|
|
|
@ -122,8 +122,7 @@ xfs_qm_dqinit(
|
||||||
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);
|
||||||
dqp->HL_NEXT = NULL;
|
INIT_LIST_HEAD(&dqp->q_hashlist);
|
||||||
dqp->HL_PREVP = NULL;
|
|
||||||
dqp->q_bufoffset = 0;
|
dqp->q_bufoffset = 0;
|
||||||
dqp->q_fileoffset = 0;
|
dqp->q_fileoffset = 0;
|
||||||
dqp->q_transp = NULL;
|
dqp->q_transp = NULL;
|
||||||
|
@ -752,7 +751,6 @@ xfs_qm_dqlookup(
|
||||||
{
|
{
|
||||||
xfs_dquot_t *dqp;
|
xfs_dquot_t *dqp;
|
||||||
uint flist_locked;
|
uint flist_locked;
|
||||||
xfs_dquot_t *d;
|
|
||||||
|
|
||||||
ASSERT(mutex_is_locked(&qh->qh_lock));
|
ASSERT(mutex_is_locked(&qh->qh_lock));
|
||||||
|
|
||||||
|
@ -761,7 +759,7 @@ xfs_qm_dqlookup(
|
||||||
/*
|
/*
|
||||||
* Traverse the hashchain looking for a match
|
* Traverse the hashchain looking for a match
|
||||||
*/
|
*/
|
||||||
for (dqp = qh->qh_next; dqp != NULL; dqp = dqp->HL_NEXT) {
|
list_for_each_entry(dqp, &qh->qh_list, q_hashlist) {
|
||||||
/*
|
/*
|
||||||
* We already have the hashlock. We don't need the
|
* We already have the hashlock. We don't need the
|
||||||
* dqlock to look at the id field of the dquot, since the
|
* dqlock to look at the id field of the dquot, since the
|
||||||
|
@ -828,21 +826,10 @@ xfs_qm_dqlookup(
|
||||||
* move the dquot to the front of the hashchain
|
* move the dquot to the front of the hashchain
|
||||||
*/
|
*/
|
||||||
ASSERT(mutex_is_locked(&qh->qh_lock));
|
ASSERT(mutex_is_locked(&qh->qh_lock));
|
||||||
if (dqp->HL_PREVP != &qh->qh_next) {
|
list_move(&dqp->q_hashlist, &qh->qh_list);
|
||||||
trace_xfs_dqlookup_move(dqp);
|
|
||||||
if ((d = dqp->HL_NEXT))
|
|
||||||
d->HL_PREVP = dqp->HL_PREVP;
|
|
||||||
*(dqp->HL_PREVP) = d;
|
|
||||||
d = qh->qh_next;
|
|
||||||
d->HL_PREVP = &dqp->HL_NEXT;
|
|
||||||
dqp->HL_NEXT = d;
|
|
||||||
dqp->HL_PREVP = &qh->qh_next;
|
|
||||||
qh->qh_next = dqp;
|
|
||||||
}
|
|
||||||
trace_xfs_dqlookup_done(dqp);
|
trace_xfs_dqlookup_done(dqp);
|
||||||
*O_dqpp = dqp;
|
*O_dqpp = dqp;
|
||||||
ASSERT(mutex_is_locked(&qh->qh_lock));
|
return 0;
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1034,7 +1021,8 @@ xfs_qm_dqget(
|
||||||
*/
|
*/
|
||||||
ASSERT(mutex_is_locked(&h->qh_lock));
|
ASSERT(mutex_is_locked(&h->qh_lock));
|
||||||
dqp->q_hash = h;
|
dqp->q_hash = h;
|
||||||
XQM_HASHLIST_INSERT(h, dqp);
|
list_add(&dqp->q_hashlist, &h->qh_list);
|
||||||
|
h->qh_version++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attach this dquot to this filesystem's list of all dquots,
|
* Attach this dquot to this filesystem's list of all dquots,
|
||||||
|
@ -1387,7 +1375,7 @@ int
|
||||||
xfs_qm_dqpurge(
|
xfs_qm_dqpurge(
|
||||||
xfs_dquot_t *dqp)
|
xfs_dquot_t *dqp)
|
||||||
{
|
{
|
||||||
xfs_dqhash_t *thishash;
|
xfs_dqhash_t *qh = dqp->q_hash;
|
||||||
xfs_mount_t *mp = dqp->q_mount;
|
xfs_mount_t *mp = dqp->q_mount;
|
||||||
|
|
||||||
ASSERT(mutex_is_locked(&mp->m_quotainfo->qi_dqlist_lock));
|
ASSERT(mutex_is_locked(&mp->m_quotainfo->qi_dqlist_lock));
|
||||||
|
@ -1453,8 +1441,8 @@ xfs_qm_dqpurge(
|
||||||
ASSERT(XFS_FORCED_SHUTDOWN(mp) ||
|
ASSERT(XFS_FORCED_SHUTDOWN(mp) ||
|
||||||
!(dqp->q_logitem.qli_item.li_flags & XFS_LI_IN_AIL));
|
!(dqp->q_logitem.qli_item.li_flags & XFS_LI_IN_AIL));
|
||||||
|
|
||||||
thishash = dqp->q_hash;
|
list_del_init(&dqp->q_hashlist);
|
||||||
XQM_HASHLIST_REMOVE(thishash, dqp);
|
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--;
|
||||||
|
@ -1470,7 +1458,7 @@ xfs_qm_dqpurge(
|
||||||
memset(&dqp->q_core, 0, sizeof(dqp->q_core));
|
memset(&dqp->q_core, 0, sizeof(dqp->q_core));
|
||||||
xfs_dqfunlock(dqp);
|
xfs_dqfunlock(dqp);
|
||||||
xfs_dqunlock(dqp);
|
xfs_dqunlock(dqp);
|
||||||
mutex_unlock(&thishash->qh_lock);
|
mutex_unlock(&qh->qh_lock);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,17 +33,12 @@
|
||||||
* The hash chain headers (hash buckets)
|
* The hash chain headers (hash buckets)
|
||||||
*/
|
*/
|
||||||
typedef struct xfs_dqhash {
|
typedef struct xfs_dqhash {
|
||||||
struct xfs_dquot *qh_next;
|
struct list_head qh_list;
|
||||||
struct mutex qh_lock;
|
struct mutex qh_lock;
|
||||||
uint qh_version; /* ever increasing version */
|
uint qh_version; /* ever increasing version */
|
||||||
uint qh_nelems; /* number of dquots on the list */
|
uint qh_nelems; /* number of dquots on the list */
|
||||||
} xfs_dqhash_t;
|
} xfs_dqhash_t;
|
||||||
|
|
||||||
typedef struct xfs_dqlink {
|
|
||||||
struct xfs_dquot *ql_next; /* forward link */
|
|
||||||
struct xfs_dquot **ql_prevp; /* pointer to prev ql_next */
|
|
||||||
} xfs_dqlink_t;
|
|
||||||
|
|
||||||
struct xfs_mount;
|
struct xfs_mount;
|
||||||
struct xfs_trans;
|
struct xfs_trans;
|
||||||
|
|
||||||
|
@ -57,7 +52,6 @@ struct xfs_trans;
|
||||||
typedef struct xfs_dqmarker {
|
typedef struct xfs_dqmarker {
|
||||||
struct xfs_dquot*dqm_flnext; /* link to freelist: must be first */
|
struct xfs_dquot*dqm_flnext; /* link to freelist: must be first */
|
||||||
struct xfs_dquot*dqm_flprev;
|
struct xfs_dquot*dqm_flprev;
|
||||||
xfs_dqlink_t dqm_hashlist; /* link to the hash chain */
|
|
||||||
uint dqm_flags; /* various flags (XFS_DQ_*) */
|
uint dqm_flags; /* various flags (XFS_DQ_*) */
|
||||||
} xfs_dqmarker_t;
|
} xfs_dqmarker_t;
|
||||||
|
|
||||||
|
@ -67,6 +61,7 @@ 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_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 */
|
||||||
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 */
|
||||||
|
|
|
@ -277,7 +277,7 @@ xfs_qm_rele_quotafs_ref(
|
||||||
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(dqp->HL_PREVP == NULL);
|
ASSERT(list_empty(&dqp->q_hashlist));
|
||||||
ASSERT(list_empty(&dqp->q_mplist));
|
ASSERT(list_empty(&dqp->q_mplist));
|
||||||
XQM_FREELIST_REMOVE(dqp);
|
XQM_FREELIST_REMOVE(dqp);
|
||||||
xfs_dqunlock(dqp);
|
xfs_dqunlock(dqp);
|
||||||
|
@ -1176,7 +1176,7 @@ xfs_qm_list_init(
|
||||||
int n)
|
int n)
|
||||||
{
|
{
|
||||||
mutex_init(&list->qh_lock);
|
mutex_init(&list->qh_lock);
|
||||||
list->qh_next = NULL;
|
INIT_LIST_HEAD(&list->qh_list);
|
||||||
list->qh_version = 0;
|
list->qh_version = 0;
|
||||||
list->qh_nelems = 0;
|
list->qh_nelems = 0;
|
||||||
}
|
}
|
||||||
|
@ -1976,7 +1976,7 @@ startagain:
|
||||||
if (dqp->dq_flags & XFS_DQ_INACTIVE) {
|
if (dqp->dq_flags & XFS_DQ_INACTIVE) {
|
||||||
ASSERT(mp == NULL);
|
ASSERT(mp == NULL);
|
||||||
ASSERT(! XFS_DQ_IS_DIRTY(dqp));
|
ASSERT(! XFS_DQ_IS_DIRTY(dqp));
|
||||||
ASSERT(dqp->HL_PREVP == NULL);
|
ASSERT(list_empty(&dqp->q_hashlist));
|
||||||
ASSERT(list_empty(&dqp->q_mplist));
|
ASSERT(list_empty(&dqp->q_mplist));
|
||||||
XQM_FREELIST_REMOVE(dqp);
|
XQM_FREELIST_REMOVE(dqp);
|
||||||
xfs_dqunlock(dqp);
|
xfs_dqunlock(dqp);
|
||||||
|
@ -2053,7 +2053,8 @@ startagain:
|
||||||
list_del_init(&dqp->q_mplist);
|
list_del_init(&dqp->q_mplist);
|
||||||
mp->m_quotainfo->qi_dquots--;
|
mp->m_quotainfo->qi_dquots--;
|
||||||
mp->m_quotainfo->qi_dqreclaims++;
|
mp->m_quotainfo->qi_dqreclaims++;
|
||||||
XQM_HASHLIST_REMOVE(dqp->q_hash, dqp);
|
list_del_init(&dqp->q_hashlist);
|
||||||
|
dqp->q_hash->qh_version++;
|
||||||
XQM_FREELIST_REMOVE(dqp);
|
XQM_FREELIST_REMOVE(dqp);
|
||||||
dqpout = dqp;
|
dqpout = dqp;
|
||||||
mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
|
mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
|
||||||
|
|
|
@ -932,6 +932,7 @@ struct mutex qcheck_lock;
|
||||||
|
|
||||||
typedef struct dqtest {
|
typedef struct dqtest {
|
||||||
xfs_dqmarker_t q_lists;
|
xfs_dqmarker_t q_lists;
|
||||||
|
struct list_head q_hashlist;
|
||||||
xfs_dqhash_t *q_hash; /* the hashchain header */
|
xfs_dqhash_t *q_hash; /* the hashchain header */
|
||||||
xfs_mount_t *q_mount; /* filesystem this relates to */
|
xfs_mount_t *q_mount; /* filesystem this relates to */
|
||||||
xfs_dqid_t d_id; /* user id or group id */
|
xfs_dqid_t d_id; /* user id or group id */
|
||||||
|
@ -942,14 +943,9 @@ typedef struct dqtest {
|
||||||
STATIC void
|
STATIC void
|
||||||
xfs_qm_hashinsert(xfs_dqhash_t *h, xfs_dqtest_t *dqp)
|
xfs_qm_hashinsert(xfs_dqhash_t *h, xfs_dqtest_t *dqp)
|
||||||
{
|
{
|
||||||
xfs_dquot_t *d;
|
list_add(&dqp->q_hashlist, &h->qh_list);
|
||||||
if (((d) = (h)->qh_next))
|
h->qh_version++;
|
||||||
(d)->HL_PREVP = &((dqp)->HL_NEXT);
|
h->qh_nelems++;
|
||||||
(dqp)->HL_NEXT = d;
|
|
||||||
(dqp)->HL_PREVP = &((h)->qh_next);
|
|
||||||
(h)->qh_next = (xfs_dquot_t *)dqp;
|
|
||||||
(h)->qh_version++;
|
|
||||||
(h)->qh_nelems++;
|
|
||||||
}
|
}
|
||||||
STATIC void
|
STATIC void
|
||||||
xfs_qm_dqtest_print(
|
xfs_qm_dqtest_print(
|
||||||
|
@ -1061,9 +1057,7 @@ xfs_qm_internalqcheck_dqget(
|
||||||
xfs_dqhash_t *h;
|
xfs_dqhash_t *h;
|
||||||
|
|
||||||
h = DQTEST_HASH(mp, id, type);
|
h = DQTEST_HASH(mp, id, type);
|
||||||
for (d = (xfs_dqtest_t *) h->qh_next; d != NULL;
|
list_for_each_entry(d, &h->qh_list, q_hashlist) {
|
||||||
d = (xfs_dqtest_t *) d->HL_NEXT) {
|
|
||||||
/* DQTEST_LIST_PRINT(h, HL_NEXT, "@@@@@ dqtestlist @@@@@"); */
|
|
||||||
if (d->d_id == id && mp == d->q_mount) {
|
if (d->d_id == id && mp == d->q_mount) {
|
||||||
*O_dq = d;
|
*O_dq = d;
|
||||||
return (0);
|
return (0);
|
||||||
|
@ -1074,6 +1068,7 @@ xfs_qm_internalqcheck_dqget(
|
||||||
d->d_id = id;
|
d->d_id = id;
|
||||||
d->q_mount = mp;
|
d->q_mount = mp;
|
||||||
d->q_hash = h;
|
d->q_hash = h;
|
||||||
|
INIT_LIST_HEAD(&d->q_hashlist);
|
||||||
xfs_qm_hashinsert(h, d);
|
xfs_qm_hashinsert(h, d);
|
||||||
*O_dq = d;
|
*O_dq = d;
|
||||||
return (0);
|
return (0);
|
||||||
|
@ -1180,8 +1175,6 @@ xfs_qm_internalqcheck(
|
||||||
xfs_ino_t lastino;
|
xfs_ino_t lastino;
|
||||||
int done, count;
|
int done, count;
|
||||||
int i;
|
int i;
|
||||||
xfs_dqtest_t *d, *e;
|
|
||||||
xfs_dqhash_t *h1;
|
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
lastino = 0;
|
lastino = 0;
|
||||||
|
@ -1221,19 +1214,18 @@ xfs_qm_internalqcheck(
|
||||||
}
|
}
|
||||||
cmn_err(CE_DEBUG, "Checking results against system dquots");
|
cmn_err(CE_DEBUG, "Checking results against system dquots");
|
||||||
for (i = 0; i < qmtest_hashmask; i++) {
|
for (i = 0; i < qmtest_hashmask; i++) {
|
||||||
h1 = &qmtest_udqtab[i];
|
xfs_dqtest_t *d, *n;
|
||||||
for (d = (xfs_dqtest_t *) h1->qh_next; d != NULL; ) {
|
xfs_dqhash_t *h;
|
||||||
|
|
||||||
|
h = &qmtest_udqtab[i];
|
||||||
|
list_for_each_entry_safe(d, n, &h->qh_list, q_hashlist) {
|
||||||
xfs_dqtest_cmp(d);
|
xfs_dqtest_cmp(d);
|
||||||
e = (xfs_dqtest_t *) d->HL_NEXT;
|
|
||||||
kmem_free(d);
|
kmem_free(d);
|
||||||
d = e;
|
|
||||||
}
|
}
|
||||||
h1 = &qmtest_gdqtab[i];
|
h = &qmtest_gdqtab[i];
|
||||||
for (d = (xfs_dqtest_t *) h1->qh_next; d != NULL; ) {
|
list_for_each_entry_safe(d, n, &h->qh_list, q_hashlist) {
|
||||||
xfs_dqtest_cmp(d);
|
xfs_dqtest_cmp(d);
|
||||||
e = (xfs_dqtest_t *) d->HL_NEXT;
|
|
||||||
kmem_free(d);
|
kmem_free(d);
|
||||||
d = e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,46 +72,13 @@
|
||||||
!dqp->q_core.d_rtbcount && \
|
!dqp->q_core.d_rtbcount && \
|
||||||
!dqp->q_core.d_icount)
|
!dqp->q_core.d_icount)
|
||||||
|
|
||||||
#define HL_PREVP dq_hashlist.ql_prevp
|
|
||||||
#define HL_NEXT dq_hashlist.ql_next
|
|
||||||
|
|
||||||
|
|
||||||
#define _LIST_REMOVE(h, dqp, PVP, NXT) \
|
|
||||||
{ \
|
|
||||||
xfs_dquot_t *d; \
|
|
||||||
if (((d) = (dqp)->NXT)) \
|
|
||||||
(d)->PVP = (dqp)->PVP; \
|
|
||||||
*((dqp)->PVP) = d; \
|
|
||||||
(dqp)->NXT = NULL; \
|
|
||||||
(dqp)->PVP = NULL; \
|
|
||||||
(h)->qh_version++; \
|
|
||||||
(h)->qh_nelems--; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define _LIST_INSERT(h, dqp, PVP, NXT) \
|
|
||||||
{ \
|
|
||||||
xfs_dquot_t *d; \
|
|
||||||
if (((d) = (h)->qh_next)) \
|
|
||||||
(d)->PVP = &((dqp)->NXT); \
|
|
||||||
(dqp)->NXT = d; \
|
|
||||||
(dqp)->PVP = &((h)->qh_next); \
|
|
||||||
(h)->qh_next = dqp; \
|
|
||||||
(h)->qh_version++; \
|
|
||||||
(h)->qh_nelems++; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FOREACH_DQUOT_IN_FREELIST(dqp, qlist) \
|
#define FOREACH_DQUOT_IN_FREELIST(dqp, qlist) \
|
||||||
for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \
|
for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \
|
||||||
(dqp) = (dqp)->dq_flnext)
|
(dqp) = (dqp)->dq_flnext)
|
||||||
|
|
||||||
#define XQM_HASHLIST_INSERT(h, dqp) \
|
|
||||||
_LIST_INSERT(h, dqp, HL_PREVP, HL_NEXT)
|
|
||||||
|
|
||||||
#define XQM_FREELIST_INSERT(h, dqp) \
|
#define XQM_FREELIST_INSERT(h, dqp) \
|
||||||
xfs_qm_freelist_append(h, dqp)
|
xfs_qm_freelist_append(h, dqp)
|
||||||
|
|
||||||
#define XQM_HASHLIST_REMOVE(h, dqp) \
|
|
||||||
_LIST_REMOVE(h, dqp, HL_PREVP, HL_NEXT)
|
|
||||||
#define XQM_FREELIST_REMOVE(dqp) \
|
#define XQM_FREELIST_REMOVE(dqp) \
|
||||||
xfs_qm_freelist_unlink(dqp)
|
xfs_qm_freelist_unlink(dqp)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue