Skip to content

Commit

Permalink
xfs: convert the dquot hash list to use list heads
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dave Chinner authored and Alex Elder committed May 19, 2010
1 parent 368e136 commit e6a81f1
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 88 deletions.
1 change: 0 additions & 1 deletion fs/xfs/linux-2.6/xfs_trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,6 @@ DEFINE_DQUOT_EVENT(xfs_dqread_fail);
DEFINE_DQUOT_EVENT(xfs_dqlookup_found);
DEFINE_DQUOT_EVENT(xfs_dqlookup_want);
DEFINE_DQUOT_EVENT(xfs_dqlookup_freelist);
DEFINE_DQUOT_EVENT(xfs_dqlookup_move);
DEFINE_DQUOT_EVENT(xfs_dqlookup_done);
DEFINE_DQUOT_EVENT(xfs_dqget_hit);
DEFINE_DQUOT_EVENT(xfs_dqget_miss);
Expand Down
32 changes: 10 additions & 22 deletions fs/xfs/quota/xfs_dquot.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,7 @@ xfs_qm_dqinit(
dqp->q_nrefs = 0;
dqp->q_blkno = 0;
INIT_LIST_HEAD(&dqp->q_mplist);
dqp->HL_NEXT = NULL;
dqp->HL_PREVP = NULL;
INIT_LIST_HEAD(&dqp->q_hashlist);
dqp->q_bufoffset = 0;
dqp->q_fileoffset = 0;
dqp->q_transp = NULL;
Expand Down Expand Up @@ -752,7 +751,6 @@ xfs_qm_dqlookup(
{
xfs_dquot_t *dqp;
uint flist_locked;
xfs_dquot_t *d;

ASSERT(mutex_is_locked(&qh->qh_lock));

Expand All @@ -761,7 +759,7 @@ xfs_qm_dqlookup(
/*
* 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
* dqlock to look at the id field of the dquot, since the
Expand Down Expand Up @@ -828,21 +826,10 @@ xfs_qm_dqlookup(
* move the dquot to the front of the hashchain
*/
ASSERT(mutex_is_locked(&qh->qh_lock));
if (dqp->HL_PREVP != &qh->qh_next) {
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;
}
list_move(&dqp->q_hashlist, &qh->qh_list);
trace_xfs_dqlookup_done(dqp);
*O_dqpp = dqp;
ASSERT(mutex_is_locked(&qh->qh_lock));
return (0);
return 0;
}
}

Expand Down Expand Up @@ -1034,7 +1021,8 @@ xfs_qm_dqget(
*/
ASSERT(mutex_is_locked(&h->qh_lock));
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,
Expand Down Expand Up @@ -1387,7 +1375,7 @@ int
xfs_qm_dqpurge(
xfs_dquot_t *dqp)
{
xfs_dqhash_t *thishash;
xfs_dqhash_t *qh = dqp->q_hash;
xfs_mount_t *mp = dqp->q_mount;

ASSERT(mutex_is_locked(&mp->m_quotainfo->qi_dqlist_lock));
Expand Down Expand Up @@ -1453,8 +1441,8 @@ xfs_qm_dqpurge(
ASSERT(XFS_FORCED_SHUTDOWN(mp) ||
!(dqp->q_logitem.qli_item.li_flags & XFS_LI_IN_AIL));

thishash = dqp->q_hash;
XQM_HASHLIST_REMOVE(thishash, dqp);
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--;
Expand All @@ -1470,7 +1458,7 @@ xfs_qm_dqpurge(
memset(&dqp->q_core, 0, sizeof(dqp->q_core));
xfs_dqfunlock(dqp);
xfs_dqunlock(dqp);
mutex_unlock(&thishash->qh_lock);
mutex_unlock(&qh->qh_lock);
return (0);
}

Expand Down
9 changes: 2 additions & 7 deletions fs/xfs/quota/xfs_dquot.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,12 @@
* The hash chain headers (hash buckets)
*/
typedef struct xfs_dqhash {
struct xfs_dquot *qh_next;
struct list_head qh_list;
struct mutex qh_lock;
uint qh_version; /* ever increasing version */
uint qh_nelems; /* number of dquots on the list */
} 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_trans;

Expand All @@ -57,7 +52,6 @@ struct xfs_trans;
typedef struct xfs_dqmarker {
struct xfs_dquot*dqm_flnext; /* link to freelist: must be first */
struct xfs_dquot*dqm_flprev;
xfs_dqlink_t dqm_hashlist; /* link to the hash chain */
uint dqm_flags; /* various flags (XFS_DQ_*) */
} xfs_dqmarker_t;

Expand All @@ -67,6 +61,7 @@ typedef struct xfs_dqmarker {
typedef struct xfs_dquot {
xfs_dqmarker_t q_lists; /* list ptrs, q_flags (marker) */
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 */
struct xfs_mount*q_mount; /* filesystem this relates to */
struct xfs_trans*q_transp; /* trans this belongs to currently */
Expand Down
9 changes: 5 additions & 4 deletions fs/xfs/quota/xfs_qm.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ xfs_qm_rele_quotafs_ref(
if (dqp->dq_flags & XFS_DQ_INACTIVE) {
ASSERT(dqp->q_mount == NULL);
ASSERT(! XFS_DQ_IS_DIRTY(dqp));
ASSERT(dqp->HL_PREVP == NULL);
ASSERT(list_empty(&dqp->q_hashlist));
ASSERT(list_empty(&dqp->q_mplist));
XQM_FREELIST_REMOVE(dqp);
xfs_dqunlock(dqp);
Expand Down Expand Up @@ -1176,7 +1176,7 @@ xfs_qm_list_init(
int n)
{
mutex_init(&list->qh_lock);
list->qh_next = NULL;
INIT_LIST_HEAD(&list->qh_list);
list->qh_version = 0;
list->qh_nelems = 0;
}
Expand Down Expand Up @@ -1976,7 +1976,7 @@ xfs_qm_dqreclaim_one(void)
if (dqp->dq_flags & XFS_DQ_INACTIVE) {
ASSERT(mp == NULL);
ASSERT(! XFS_DQ_IS_DIRTY(dqp));
ASSERT(dqp->HL_PREVP == NULL);
ASSERT(list_empty(&dqp->q_hashlist));
ASSERT(list_empty(&dqp->q_mplist));
XQM_FREELIST_REMOVE(dqp);
xfs_dqunlock(dqp);
Expand Down Expand Up @@ -2053,7 +2053,8 @@ xfs_qm_dqreclaim_one(void)
list_del_init(&dqp->q_mplist);
mp->m_quotainfo->qi_dquots--;
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);
dqpout = dqp;
mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
Expand Down
34 changes: 13 additions & 21 deletions fs/xfs/quota/xfs_qm_syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,7 @@ struct mutex qcheck_lock;

typedef struct dqtest {
xfs_dqmarker_t q_lists;
struct list_head q_hashlist;
xfs_dqhash_t *q_hash; /* the hashchain header */
xfs_mount_t *q_mount; /* filesystem this relates to */
xfs_dqid_t d_id; /* user id or group id */
Expand All @@ -942,14 +943,9 @@ typedef struct dqtest {
STATIC void
xfs_qm_hashinsert(xfs_dqhash_t *h, xfs_dqtest_t *dqp)
{
xfs_dquot_t *d;
if (((d) = (h)->qh_next))
(d)->HL_PREVP = &((dqp)->HL_NEXT);
(dqp)->HL_NEXT = d;
(dqp)->HL_PREVP = &((h)->qh_next);
(h)->qh_next = (xfs_dquot_t *)dqp;
(h)->qh_version++;
(h)->qh_nelems++;
list_add(&dqp->q_hashlist, &h->qh_list);
h->qh_version++;
h->qh_nelems++;
}
STATIC void
xfs_qm_dqtest_print(
Expand Down Expand Up @@ -1061,9 +1057,7 @@ xfs_qm_internalqcheck_dqget(
xfs_dqhash_t *h;

h = DQTEST_HASH(mp, id, type);
for (d = (xfs_dqtest_t *) h->qh_next; d != NULL;
d = (xfs_dqtest_t *) d->HL_NEXT) {
/* DQTEST_LIST_PRINT(h, HL_NEXT, "@@@@@ dqtestlist @@@@@"); */
list_for_each_entry(d, &h->qh_list, q_hashlist) {
if (d->d_id == id && mp == d->q_mount) {
*O_dq = d;
return (0);
Expand All @@ -1074,6 +1068,7 @@ xfs_qm_internalqcheck_dqget(
d->d_id = id;
d->q_mount = mp;
d->q_hash = h;
INIT_LIST_HEAD(&d->q_hashlist);
xfs_qm_hashinsert(h, d);
*O_dq = d;
return (0);
Expand Down Expand Up @@ -1180,8 +1175,6 @@ xfs_qm_internalqcheck(
xfs_ino_t lastino;
int done, count;
int i;
xfs_dqtest_t *d, *e;
xfs_dqhash_t *h1;
int error;

lastino = 0;
Expand Down Expand Up @@ -1221,19 +1214,18 @@ xfs_qm_internalqcheck(
}
cmn_err(CE_DEBUG, "Checking results against system dquots");
for (i = 0; i < qmtest_hashmask; i++) {
h1 = &qmtest_udqtab[i];
for (d = (xfs_dqtest_t *) h1->qh_next; d != NULL; ) {
xfs_dqtest_t *d, *n;
xfs_dqhash_t *h;

h = &qmtest_udqtab[i];
list_for_each_entry_safe(d, n, &h->qh_list, q_hashlist) {
xfs_dqtest_cmp(d);
e = (xfs_dqtest_t *) d->HL_NEXT;
kmem_free(d);
d = e;
}
h1 = &qmtest_gdqtab[i];
for (d = (xfs_dqtest_t *) h1->qh_next; d != NULL; ) {
h = &qmtest_gdqtab[i];
list_for_each_entry_safe(d, n, &h->qh_list, q_hashlist) {
xfs_dqtest_cmp(d);
e = (xfs_dqtest_t *) d->HL_NEXT;
kmem_free(d);
d = e;
}
}

Expand Down
33 changes: 0 additions & 33 deletions fs/xfs/quota/xfs_quota_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,46 +72,13 @@
!dqp->q_core.d_rtbcount && \
!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) \
for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \
(dqp) = (dqp)->dq_flnext)

#define XQM_HASHLIST_INSERT(h, dqp) \
_LIST_INSERT(h, dqp, HL_PREVP, HL_NEXT)

#define XQM_FREELIST_INSERT(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) \
xfs_qm_freelist_unlink(dqp)

Expand Down

0 comments on commit e6a81f1

Please sign in to comment.