xfs: convert the dquot hash list to use list heads
authorDave Chinner <dchinner@redhat.com>
Tue, 13 Apr 2010 05:06:51 +0000 (15:06 +1000)
committerAlex Elder <aelder@sgi.com>
Wed, 19 May 2010 14:58:11 +0000 (09:58 -0500)
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>
fs/xfs/linux-2.6/xfs_trace.h
fs/xfs/quota/xfs_dquot.c
fs/xfs/quota/xfs_dquot.h
fs/xfs/quota/xfs_qm.c
fs/xfs/quota/xfs_qm_syscalls.c
fs/xfs/quota/xfs_quota_priv.h

index ce6a968..8a319cf 100644 (file)
@@ -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);
index 838289b..ad64ab6 100644 (file)
@@ -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;
@@ -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));
 
@@ -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
@@ -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;
                }
        }
 
@@ -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,
@@ -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));
@@ -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--;
@@ -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);
 }
 
index 6992a67..169b3c2 100644 (file)
  * 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;
 
@@ -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;
 
@@ -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 */
index 5ca65c8..08e97f1 100644 (file)
@@ -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);
@@ -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;
 }
@@ -1976,7 +1976,7 @@ startagain:
                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);
@@ -2053,7 +2053,8 @@ startagain:
                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);
index c54fa77..c82e319 100644 (file)
@@ -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 */
@@ -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(
@@ -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);
@@ -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);
@@ -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;
@@ -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;
                }
        }
 
index 6f4bbae..3a1b9aa 100644 (file)
        !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)