aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2010-04-13 01:06:51 -0400
committerAlex Elder <aelder@sgi.com>2010-05-19 10:58:11 -0400
commite6a81f13aa9aa20ef03174210aed24791865b05e (patch)
tree727202721a225004e2522f32278de294c3748e70 /fs/xfs
parent368e136174344c417bad6ff0380b7b3f574bf120 (diff)
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>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/linux-2.6/xfs_trace.h1
-rw-r--r--fs/xfs/quota/xfs_dquot.c32
-rw-r--r--fs/xfs/quota/xfs_dquot.h9
-rw-r--r--fs/xfs/quota/xfs_qm.c9
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c34
-rw-r--r--fs/xfs/quota/xfs_quota_priv.h33
6 files changed, 30 insertions, 88 deletions
diff --git a/fs/xfs/linux-2.6/xfs_trace.h b/fs/xfs/linux-2.6/xfs_trace.h
index ce6a968a8f40..8a319cfd2901 100644
--- a/fs/xfs/linux-2.6/xfs_trace.h
+++ b/fs/xfs/linux-2.6/xfs_trace.h
@@ -667,7 +667,6 @@ DEFINE_DQUOT_EVENT(xfs_dqread_fail);
667DEFINE_DQUOT_EVENT(xfs_dqlookup_found); 667DEFINE_DQUOT_EVENT(xfs_dqlookup_found);
668DEFINE_DQUOT_EVENT(xfs_dqlookup_want); 668DEFINE_DQUOT_EVENT(xfs_dqlookup_want);
669DEFINE_DQUOT_EVENT(xfs_dqlookup_freelist); 669DEFINE_DQUOT_EVENT(xfs_dqlookup_freelist);
670DEFINE_DQUOT_EVENT(xfs_dqlookup_move);
671DEFINE_DQUOT_EVENT(xfs_dqlookup_done); 670DEFINE_DQUOT_EVENT(xfs_dqlookup_done);
672DEFINE_DQUOT_EVENT(xfs_dqget_hit); 671DEFINE_DQUOT_EVENT(xfs_dqget_hit);
673DEFINE_DQUOT_EVENT(xfs_dqget_miss); 672DEFINE_DQUOT_EVENT(xfs_dqget_miss);
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index 838289b92bb9..ad64ab62d9c5 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -122,8 +122,7 @@ xfs_qm_dqinit(
122 dqp->q_nrefs = 0; 122 dqp->q_nrefs = 0;
123 dqp->q_blkno = 0; 123 dqp->q_blkno = 0;
124 INIT_LIST_HEAD(&dqp->q_mplist); 124 INIT_LIST_HEAD(&dqp->q_mplist);
125 dqp->HL_NEXT = NULL; 125 INIT_LIST_HEAD(&dqp->q_hashlist);
126 dqp->HL_PREVP = NULL;
127 dqp->q_bufoffset = 0; 126 dqp->q_bufoffset = 0;
128 dqp->q_fileoffset = 0; 127 dqp->q_fileoffset = 0;
129 dqp->q_transp = NULL; 128 dqp->q_transp = NULL;
@@ -752,7 +751,6 @@ xfs_qm_dqlookup(
752{ 751{
753 xfs_dquot_t *dqp; 752 xfs_dquot_t *dqp;
754 uint flist_locked; 753 uint flist_locked;
755 xfs_dquot_t *d;
756 754
757 ASSERT(mutex_is_locked(&qh->qh_lock)); 755 ASSERT(mutex_is_locked(&qh->qh_lock));
758 756
@@ -761,7 +759,7 @@ xfs_qm_dqlookup(
761 /* 759 /*
762 * Traverse the hashchain looking for a match 760 * Traverse the hashchain looking for a match
763 */ 761 */
764 for (dqp = qh->qh_next; dqp != NULL; dqp = dqp->HL_NEXT) { 762 list_for_each_entry(dqp, &qh->qh_list, q_hashlist) {
765 /* 763 /*
766 * We already have the hashlock. We don't need the 764 * We already have the hashlock. We don't need the
767 * dqlock to look at the id field of the dquot, since the 765 * dqlock to look at the id field of the dquot, since the
@@ -828,21 +826,10 @@ xfs_qm_dqlookup(
828 * move the dquot to the front of the hashchain 826 * move the dquot to the front of the hashchain
829 */ 827 */
830 ASSERT(mutex_is_locked(&qh->qh_lock)); 828 ASSERT(mutex_is_locked(&qh->qh_lock));
831 if (dqp->HL_PREVP != &qh->qh_next) { 829 list_move(&dqp->q_hashlist, &qh->qh_list);
832 trace_xfs_dqlookup_move(dqp);
833 if ((d = dqp->HL_NEXT))
834 d->HL_PREVP = dqp->HL_PREVP;
835 *(dqp->HL_PREVP) = d;
836 d = qh->qh_next;
837 d->HL_PREVP = &dqp->HL_NEXT;
838 dqp->HL_NEXT = d;
839 dqp->HL_PREVP = &qh->qh_next;
840 qh->qh_next = dqp;
841 }
842 trace_xfs_dqlookup_done(dqp); 830 trace_xfs_dqlookup_done(dqp);
843 *O_dqpp = dqp; 831 *O_dqpp = dqp;
844 ASSERT(mutex_is_locked(&qh->qh_lock)); 832 return 0;
845 return (0);
846 } 833 }
847 } 834 }
848 835
@@ -1034,7 +1021,8 @@ xfs_qm_dqget(
1034 */ 1021 */
1035 ASSERT(mutex_is_locked(&h->qh_lock)); 1022 ASSERT(mutex_is_locked(&h->qh_lock));
1036 dqp->q_hash = h; 1023 dqp->q_hash = h;
1037 XQM_HASHLIST_INSERT(h, dqp); 1024 list_add(&dqp->q_hashlist, &h->qh_list);
1025 h->qh_version++;
1038 1026
1039 /* 1027 /*
1040 * Attach this dquot to this filesystem's list of all dquots, 1028 * Attach this dquot to this filesystem's list of all dquots,
@@ -1387,7 +1375,7 @@ int
1387xfs_qm_dqpurge( 1375xfs_qm_dqpurge(
1388 xfs_dquot_t *dqp) 1376 xfs_dquot_t *dqp)
1389{ 1377{
1390 xfs_dqhash_t *thishash; 1378 xfs_dqhash_t *qh = dqp->q_hash;
1391 xfs_mount_t *mp = dqp->q_mount; 1379 xfs_mount_t *mp = dqp->q_mount;
1392 1380
1393 ASSERT(mutex_is_locked(&mp->m_quotainfo->qi_dqlist_lock)); 1381 ASSERT(mutex_is_locked(&mp->m_quotainfo->qi_dqlist_lock));
@@ -1453,8 +1441,8 @@ xfs_qm_dqpurge(
1453 ASSERT(XFS_FORCED_SHUTDOWN(mp) || 1441 ASSERT(XFS_FORCED_SHUTDOWN(mp) ||
1454 !(dqp->q_logitem.qli_item.li_flags & XFS_LI_IN_AIL)); 1442 !(dqp->q_logitem.qli_item.li_flags & XFS_LI_IN_AIL));
1455 1443
1456 thishash = dqp->q_hash; 1444 list_del_init(&dqp->q_hashlist);
1457 XQM_HASHLIST_REMOVE(thishash, dqp); 1445 qh->qh_version++;
1458 list_del_init(&dqp->q_mplist); 1446 list_del_init(&dqp->q_mplist);
1459 mp->m_quotainfo->qi_dqreclaims++; 1447 mp->m_quotainfo->qi_dqreclaims++;
1460 mp->m_quotainfo->qi_dquots--; 1448 mp->m_quotainfo->qi_dquots--;
@@ -1470,7 +1458,7 @@ xfs_qm_dqpurge(
1470 memset(&dqp->q_core, 0, sizeof(dqp->q_core)); 1458 memset(&dqp->q_core, 0, sizeof(dqp->q_core));
1471 xfs_dqfunlock(dqp); 1459 xfs_dqfunlock(dqp);
1472 xfs_dqunlock(dqp); 1460 xfs_dqunlock(dqp);
1473 mutex_unlock(&thishash->qh_lock); 1461 mutex_unlock(&qh->qh_lock);
1474 return (0); 1462 return (0);
1475} 1463}
1476 1464
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h
index 6992a67c165a..169b3c24af79 100644
--- a/fs/xfs/quota/xfs_dquot.h
+++ b/fs/xfs/quota/xfs_dquot.h
@@ -33,17 +33,12 @@
33 * The hash chain headers (hash buckets) 33 * The hash chain headers (hash buckets)
34 */ 34 */
35typedef struct xfs_dqhash { 35typedef struct xfs_dqhash {
36 struct xfs_dquot *qh_next; 36 struct list_head qh_list;
37 struct mutex qh_lock; 37 struct mutex qh_lock;
38 uint qh_version; /* ever increasing version */ 38 uint qh_version; /* ever increasing version */
39 uint qh_nelems; /* number of dquots on the list */ 39 uint qh_nelems; /* number of dquots on the list */
40} xfs_dqhash_t; 40} xfs_dqhash_t;
41 41
42typedef struct xfs_dqlink {
43 struct xfs_dquot *ql_next; /* forward link */
44 struct xfs_dquot **ql_prevp; /* pointer to prev ql_next */
45} xfs_dqlink_t;
46
47struct xfs_mount; 42struct xfs_mount;
48struct xfs_trans; 43struct xfs_trans;
49 44
@@ -57,7 +52,6 @@ struct xfs_trans;
57typedef struct xfs_dqmarker { 52typedef struct xfs_dqmarker {
58 struct xfs_dquot*dqm_flnext; /* link to freelist: must be first */ 53 struct xfs_dquot*dqm_flnext; /* link to freelist: must be first */
59 struct xfs_dquot*dqm_flprev; 54 struct xfs_dquot*dqm_flprev;
60 xfs_dqlink_t dqm_hashlist; /* link to the hash chain */
61 uint dqm_flags; /* various flags (XFS_DQ_*) */ 55 uint dqm_flags; /* various flags (XFS_DQ_*) */
62} xfs_dqmarker_t; 56} xfs_dqmarker_t;
63 57
@@ -67,6 +61,7 @@ typedef struct xfs_dqmarker {
67typedef struct xfs_dquot { 61typedef struct xfs_dquot {
68 xfs_dqmarker_t q_lists; /* list ptrs, q_flags (marker) */ 62 xfs_dqmarker_t q_lists; /* list ptrs, q_flags (marker) */
69 struct list_head q_mplist; /* mount's list of dquots */ 63 struct list_head q_mplist; /* mount's list of dquots */
64 struct list_head q_hashlist; /* mount's list of dquots */
70 xfs_dqhash_t *q_hash; /* the hashchain header */ 65 xfs_dqhash_t *q_hash; /* the hashchain header */
71 struct xfs_mount*q_mount; /* filesystem this relates to */ 66 struct xfs_mount*q_mount; /* filesystem this relates to */
72 struct xfs_trans*q_transp; /* trans this belongs to currently */ 67 struct xfs_trans*q_transp; /* trans this belongs to currently */
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 5ca65c834bbd..08e97f1ef653 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -277,7 +277,7 @@ xfs_qm_rele_quotafs_ref(
277 if (dqp->dq_flags & XFS_DQ_INACTIVE) { 277 if (dqp->dq_flags & XFS_DQ_INACTIVE) {
278 ASSERT(dqp->q_mount == NULL); 278 ASSERT(dqp->q_mount == NULL);
279 ASSERT(! XFS_DQ_IS_DIRTY(dqp)); 279 ASSERT(! XFS_DQ_IS_DIRTY(dqp));
280 ASSERT(dqp->HL_PREVP == NULL); 280 ASSERT(list_empty(&dqp->q_hashlist));
281 ASSERT(list_empty(&dqp->q_mplist)); 281 ASSERT(list_empty(&dqp->q_mplist));
282 XQM_FREELIST_REMOVE(dqp); 282 XQM_FREELIST_REMOVE(dqp);
283 xfs_dqunlock(dqp); 283 xfs_dqunlock(dqp);
@@ -1176,7 +1176,7 @@ xfs_qm_list_init(
1176 int n) 1176 int n)
1177{ 1177{
1178 mutex_init(&list->qh_lock); 1178 mutex_init(&list->qh_lock);
1179 list->qh_next = NULL; 1179 INIT_LIST_HEAD(&list->qh_list);
1180 list->qh_version = 0; 1180 list->qh_version = 0;
1181 list->qh_nelems = 0; 1181 list->qh_nelems = 0;
1182} 1182}
@@ -1976,7 +1976,7 @@ startagain:
1976 if (dqp->dq_flags & XFS_DQ_INACTIVE) { 1976 if (dqp->dq_flags & XFS_DQ_INACTIVE) {
1977 ASSERT(mp == NULL); 1977 ASSERT(mp == NULL);
1978 ASSERT(! XFS_DQ_IS_DIRTY(dqp)); 1978 ASSERT(! XFS_DQ_IS_DIRTY(dqp));
1979 ASSERT(dqp->HL_PREVP == NULL); 1979 ASSERT(list_empty(&dqp->q_hashlist));
1980 ASSERT(list_empty(&dqp->q_mplist)); 1980 ASSERT(list_empty(&dqp->q_mplist));
1981 XQM_FREELIST_REMOVE(dqp); 1981 XQM_FREELIST_REMOVE(dqp);
1982 xfs_dqunlock(dqp); 1982 xfs_dqunlock(dqp);
@@ -2053,7 +2053,8 @@ startagain:
2053 list_del_init(&dqp->q_mplist); 2053 list_del_init(&dqp->q_mplist);
2054 mp->m_quotainfo->qi_dquots--; 2054 mp->m_quotainfo->qi_dquots--;
2055 mp->m_quotainfo->qi_dqreclaims++; 2055 mp->m_quotainfo->qi_dqreclaims++;
2056 XQM_HASHLIST_REMOVE(dqp->q_hash, dqp); 2056 list_del_init(&dqp->q_hashlist);
2057 dqp->q_hash->qh_version++;
2057 XQM_FREELIST_REMOVE(dqp); 2058 XQM_FREELIST_REMOVE(dqp);
2058 dqpout = dqp; 2059 dqpout = dqp;
2059 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock); 2060 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index c54fa7790bd8..c82e319f9df4 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -932,6 +932,7 @@ struct mutex qcheck_lock;
932 932
933typedef struct dqtest { 933typedef struct dqtest {
934 xfs_dqmarker_t q_lists; 934 xfs_dqmarker_t q_lists;
935 struct list_head q_hashlist;
935 xfs_dqhash_t *q_hash; /* the hashchain header */ 936 xfs_dqhash_t *q_hash; /* the hashchain header */
936 xfs_mount_t *q_mount; /* filesystem this relates to */ 937 xfs_mount_t *q_mount; /* filesystem this relates to */
937 xfs_dqid_t d_id; /* user id or group id */ 938 xfs_dqid_t d_id; /* user id or group id */
@@ -942,14 +943,9 @@ typedef struct dqtest {
942STATIC void 943STATIC void
943xfs_qm_hashinsert(xfs_dqhash_t *h, xfs_dqtest_t *dqp) 944xfs_qm_hashinsert(xfs_dqhash_t *h, xfs_dqtest_t *dqp)
944{ 945{
945 xfs_dquot_t *d; 946 list_add(&dqp->q_hashlist, &h->qh_list);
946 if (((d) = (h)->qh_next)) 947 h->qh_version++;
947 (d)->HL_PREVP = &((dqp)->HL_NEXT); 948 h->qh_nelems++;
948 (dqp)->HL_NEXT = d;
949 (dqp)->HL_PREVP = &((h)->qh_next);
950 (h)->qh_next = (xfs_dquot_t *)dqp;
951 (h)->qh_version++;
952 (h)->qh_nelems++;
953} 949}
954STATIC void 950STATIC void
955xfs_qm_dqtest_print( 951xfs_qm_dqtest_print(
@@ -1061,9 +1057,7 @@ xfs_qm_internalqcheck_dqget(
1061 xfs_dqhash_t *h; 1057 xfs_dqhash_t *h;
1062 1058
1063 h = DQTEST_HASH(mp, id, type); 1059 h = DQTEST_HASH(mp, id, type);
1064 for (d = (xfs_dqtest_t *) h->qh_next; d != NULL; 1060 list_for_each_entry(d, &h->qh_list, q_hashlist) {
1065 d = (xfs_dqtest_t *) d->HL_NEXT) {
1066 /* DQTEST_LIST_PRINT(h, HL_NEXT, "@@@@@ dqtestlist @@@@@"); */
1067 if (d->d_id == id && mp == d->q_mount) { 1061 if (d->d_id == id && mp == d->q_mount) {
1068 *O_dq = d; 1062 *O_dq = d;
1069 return (0); 1063 return (0);
@@ -1074,6 +1068,7 @@ xfs_qm_internalqcheck_dqget(
1074 d->d_id = id; 1068 d->d_id = id;
1075 d->q_mount = mp; 1069 d->q_mount = mp;
1076 d->q_hash = h; 1070 d->q_hash = h;
1071 INIT_LIST_HEAD(&d->q_hashlist);
1077 xfs_qm_hashinsert(h, d); 1072 xfs_qm_hashinsert(h, d);
1078 *O_dq = d; 1073 *O_dq = d;
1079 return (0); 1074 return (0);
@@ -1180,8 +1175,6 @@ xfs_qm_internalqcheck(
1180 xfs_ino_t lastino; 1175 xfs_ino_t lastino;
1181 int done, count; 1176 int done, count;
1182 int i; 1177 int i;
1183 xfs_dqtest_t *d, *e;
1184 xfs_dqhash_t *h1;
1185 int error; 1178 int error;
1186 1179
1187 lastino = 0; 1180 lastino = 0;
@@ -1221,19 +1214,18 @@ xfs_qm_internalqcheck(
1221 } 1214 }
1222 cmn_err(CE_DEBUG, "Checking results against system dquots"); 1215 cmn_err(CE_DEBUG, "Checking results against system dquots");
1223 for (i = 0; i < qmtest_hashmask; i++) { 1216 for (i = 0; i < qmtest_hashmask; i++) {
1224 h1 = &qmtest_udqtab[i]; 1217 xfs_dqtest_t *d, *n;
1225 for (d = (xfs_dqtest_t *) h1->qh_next; d != NULL; ) { 1218 xfs_dqhash_t *h;
1219
1220 h = &qmtest_udqtab[i];
1221 list_for_each_entry_safe(d, n, &h->qh_list, q_hashlist) {
1226 xfs_dqtest_cmp(d); 1222 xfs_dqtest_cmp(d);
1227 e = (xfs_dqtest_t *) d->HL_NEXT;
1228 kmem_free(d); 1223 kmem_free(d);
1229 d = e;
1230 } 1224 }
1231 h1 = &qmtest_gdqtab[i]; 1225 h = &qmtest_gdqtab[i];
1232 for (d = (xfs_dqtest_t *) h1->qh_next; d != NULL; ) { 1226 list_for_each_entry_safe(d, n, &h->qh_list, q_hashlist) {
1233 xfs_dqtest_cmp(d); 1227 xfs_dqtest_cmp(d);
1234 e = (xfs_dqtest_t *) d->HL_NEXT;
1235 kmem_free(d); 1228 kmem_free(d);
1236 d = e;
1237 } 1229 }
1238 } 1230 }
1239 1231
diff --git a/fs/xfs/quota/xfs_quota_priv.h b/fs/xfs/quota/xfs_quota_priv.h
index 6f4bbae51aca..3a1b9aa763fc 100644
--- a/fs/xfs/quota/xfs_quota_priv.h
+++ b/fs/xfs/quota/xfs_quota_priv.h
@@ -72,46 +72,13 @@
72 !dqp->q_core.d_rtbcount && \ 72 !dqp->q_core.d_rtbcount && \
73 !dqp->q_core.d_icount) 73 !dqp->q_core.d_icount)
74 74
75#define HL_PREVP dq_hashlist.ql_prevp
76#define HL_NEXT dq_hashlist.ql_next
77
78
79#define _LIST_REMOVE(h, dqp, PVP, NXT) \
80 { \
81 xfs_dquot_t *d; \
82 if (((d) = (dqp)->NXT)) \
83 (d)->PVP = (dqp)->PVP; \
84 *((dqp)->PVP) = d; \
85 (dqp)->NXT = NULL; \
86 (dqp)->PVP = NULL; \
87 (h)->qh_version++; \
88 (h)->qh_nelems--; \
89 }
90
91#define _LIST_INSERT(h, dqp, PVP, NXT) \
92 { \
93 xfs_dquot_t *d; \
94 if (((d) = (h)->qh_next)) \
95 (d)->PVP = &((dqp)->NXT); \
96 (dqp)->NXT = d; \
97 (dqp)->PVP = &((h)->qh_next); \
98 (h)->qh_next = dqp; \
99 (h)->qh_version++; \
100 (h)->qh_nelems++; \
101 }
102
103#define FOREACH_DQUOT_IN_FREELIST(dqp, qlist) \ 75#define FOREACH_DQUOT_IN_FREELIST(dqp, qlist) \
104for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \ 76for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \
105 (dqp) = (dqp)->dq_flnext) 77 (dqp) = (dqp)->dq_flnext)
106 78
107#define XQM_HASHLIST_INSERT(h, dqp) \
108 _LIST_INSERT(h, dqp, HL_PREVP, HL_NEXT)
109
110#define XQM_FREELIST_INSERT(h, dqp) \ 79#define XQM_FREELIST_INSERT(h, dqp) \
111 xfs_qm_freelist_append(h, dqp) 80 xfs_qm_freelist_append(h, dqp)
112 81
113#define XQM_HASHLIST_REMOVE(h, dqp) \
114 _LIST_REMOVE(h, dqp, HL_PREVP, HL_NEXT)
115#define XQM_FREELIST_REMOVE(dqp) \ 82#define XQM_FREELIST_REMOVE(dqp) \
116 xfs_qm_freelist_unlink(dqp) 83 xfs_qm_freelist_unlink(dqp)
117 84