aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/quota
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2010-04-13 01:06:52 -0400
committerAlex Elder <aelder@sgi.com>2010-05-19 10:58:11 -0400
commit3a8406f6d6916e8211936edb9e1193123df2daab (patch)
tree53f490a433ef3bd2f430ef19cdfbbe5dc514e89d /fs/xfs/quota
parente6a81f13aa9aa20ef03174210aed24791865b05e (diff)
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>
Diffstat (limited to 'fs/xfs/quota')
-rw-r--r--fs/xfs/quota/xfs_dquot.c75
-rw-r--r--fs/xfs/quota/xfs_dquot.h5
-rw-r--r--fs/xfs/quota/xfs_qm.c119
-rw-r--r--fs/xfs/quota/xfs_qm.h19
-rw-r--r--fs/xfs/quota/xfs_qm_stats.c2
-rw-r--r--fs/xfs/quota/xfs_quota_priv.h17
6 files changed, 72 insertions, 165 deletions
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index ad64ab62d9c..02dac0a5f1e 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -101,7 +101,7 @@ xfs_qm_dqinit(
101 * No need to re-initialize these if this is a reclaimed dquot. 101 * No need to re-initialize these if this is a reclaimed dquot.
102 */ 102 */
103 if (brandnewdquot) { 103 if (brandnewdquot) {
104 dqp->dq_flnext = dqp->dq_flprev = dqp; 104 INIT_LIST_HEAD(&dqp->q_freelist);
105 mutex_init(&dqp->q_qlock); 105 mutex_init(&dqp->q_qlock);
106 init_waitqueue_head(&dqp->q_pinwait); 106 init_waitqueue_head(&dqp->q_pinwait);
107 107
@@ -119,20 +119,20 @@ xfs_qm_dqinit(
119 * Only the q_core portion was zeroed in dqreclaim_one(). 119 * Only the q_core portion was zeroed in dqreclaim_one().
120 * So, we need to reset others. 120 * So, we need to reset others.
121 */ 121 */
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 INIT_LIST_HEAD(&dqp->q_hashlist); 125 INIT_LIST_HEAD(&dqp->q_hashlist);
126 dqp->q_bufoffset = 0; 126 dqp->q_bufoffset = 0;
127 dqp->q_fileoffset = 0; 127 dqp->q_fileoffset = 0;
128 dqp->q_transp = NULL; 128 dqp->q_transp = NULL;
129 dqp->q_gdquot = NULL; 129 dqp->q_gdquot = NULL;
130 dqp->q_res_bcount = 0; 130 dqp->q_res_bcount = 0;
131 dqp->q_res_icount = 0; 131 dqp->q_res_icount = 0;
132 dqp->q_res_rtbcount = 0; 132 dqp->q_res_rtbcount = 0;
133 atomic_set(&dqp->q_pincount, 0); 133 atomic_set(&dqp->q_pincount, 0);
134 dqp->q_hash = NULL; 134 dqp->q_hash = NULL;
135 ASSERT(dqp->dq_flnext == dqp->dq_flprev); 135 ASSERT(list_empty(&dqp->q_freelist));
136 136
137 trace_xfs_dqreuse(dqp); 137 trace_xfs_dqreuse(dqp);
138 } 138 }
@@ -158,7 +158,7 @@ void
158xfs_qm_dqdestroy( 158xfs_qm_dqdestroy(
159 xfs_dquot_t *dqp) 159 xfs_dquot_t *dqp)
160{ 160{
161 ASSERT(! XFS_DQ_IS_ON_FREELIST(dqp)); 161 ASSERT(list_empty(&dqp->q_freelist));
162 162
163 mutex_destroy(&dqp->q_qlock); 163 mutex_destroy(&dqp->q_qlock);
164 sv_destroy(&dqp->q_pinwait); 164 sv_destroy(&dqp->q_pinwait);
@@ -775,8 +775,8 @@ xfs_qm_dqlookup(
775 775
776 xfs_dqlock(dqp); 776 xfs_dqlock(dqp);
777 if (dqp->q_nrefs == 0) { 777 if (dqp->q_nrefs == 0) {
778 ASSERT (XFS_DQ_IS_ON_FREELIST(dqp)); 778 ASSERT(!list_empty(&dqp->q_freelist));
779 if (! xfs_qm_freelist_lock_nowait(xfs_Gqm)) { 779 if (!mutex_trylock(&xfs_Gqm->qm_dqfrlist_lock)) {
780 trace_xfs_dqlookup_want(dqp); 780 trace_xfs_dqlookup_want(dqp);
781 781
782 /* 782 /*
@@ -786,7 +786,7 @@ xfs_qm_dqlookup(
786 */ 786 */
787 dqp->dq_flags |= XFS_DQ_WANT; 787 dqp->dq_flags |= XFS_DQ_WANT;
788 xfs_dqunlock(dqp); 788 xfs_dqunlock(dqp);
789 xfs_qm_freelist_lock(xfs_Gqm); 789 mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
790 xfs_dqlock(dqp); 790 xfs_dqlock(dqp);
791 dqp->dq_flags &= ~(XFS_DQ_WANT); 791 dqp->dq_flags &= ~(XFS_DQ_WANT);
792 } 792 }
@@ -801,27 +801,20 @@ xfs_qm_dqlookup(
801 801
802 if (flist_locked) { 802 if (flist_locked) {
803 if (dqp->q_nrefs != 0) { 803 if (dqp->q_nrefs != 0) {
804 xfs_qm_freelist_unlock(xfs_Gqm); 804 mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
805 flist_locked = B_FALSE; 805 flist_locked = B_FALSE;
806 } else { 806 } else {
807 /* 807 /* take it off the freelist */
808 * take it off the freelist
809 */
810 trace_xfs_dqlookup_freelist(dqp); 808 trace_xfs_dqlookup_freelist(dqp);
811 XQM_FREELIST_REMOVE(dqp); 809 list_del_init(&dqp->q_freelist);
812 /* xfs_qm_freelist_print(&(xfs_Gqm-> 810 xfs_Gqm->qm_dqfrlist_cnt--;
813 qm_dqfreelist),
814 "after removal"); */
815 } 811 }
816 } 812 }
817 813
818 /*
819 * grab a reference
820 */
821 XFS_DQHOLD(dqp); 814 XFS_DQHOLD(dqp);
822 815
823 if (flist_locked) 816 if (flist_locked)
824 xfs_qm_freelist_unlock(xfs_Gqm); 817 mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
825 /* 818 /*
826 * move the dquot to the front of the hashchain 819 * move the dquot to the front of the hashchain
827 */ 820 */
@@ -1075,10 +1068,10 @@ xfs_qm_dqput(
1075 * drop the dqlock and acquire the freelist and dqlock 1068 * drop the dqlock and acquire the freelist and dqlock
1076 * in the right order; but try to get it out-of-order first 1069 * in the right order; but try to get it out-of-order first
1077 */ 1070 */
1078 if (! xfs_qm_freelist_lock_nowait(xfs_Gqm)) { 1071 if (!mutex_trylock(&xfs_Gqm->qm_dqfrlist_lock)) {
1079 trace_xfs_dqput_wait(dqp); 1072 trace_xfs_dqput_wait(dqp);
1080 xfs_dqunlock(dqp); 1073 xfs_dqunlock(dqp);
1081 xfs_qm_freelist_lock(xfs_Gqm); 1074 mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
1082 xfs_dqlock(dqp); 1075 xfs_dqlock(dqp);
1083 } 1076 }
1084 1077
@@ -1089,10 +1082,8 @@ xfs_qm_dqput(
1089 if (--dqp->q_nrefs == 0) { 1082 if (--dqp->q_nrefs == 0) {
1090 trace_xfs_dqput_free(dqp); 1083 trace_xfs_dqput_free(dqp);
1091 1084
1092 /* 1085 list_add_tail(&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist);
1093 * insert at end of the freelist. 1086 xfs_Gqm->qm_dqfrlist_cnt++;
1094 */
1095 XQM_FREELIST_INSERT(&(xfs_Gqm->qm_dqfreelist), dqp);
1096 1087
1097 /* 1088 /*
1098 * If we just added a udquot to the freelist, then 1089 * If we just added a udquot to the freelist, then
@@ -1107,10 +1098,6 @@ xfs_qm_dqput(
1107 xfs_dqlock(gdqp); 1098 xfs_dqlock(gdqp);
1108 dqp->q_gdquot = NULL; 1099 dqp->q_gdquot = NULL;
1109 } 1100 }
1110
1111 /* xfs_qm_freelist_print(&(xfs_Gqm->qm_dqfreelist),
1112 "@@@@@++ Free list (after append) @@@@@+");
1113 */
1114 } 1101 }
1115 xfs_dqunlock(dqp); 1102 xfs_dqunlock(dqp);
1116 1103
@@ -1122,7 +1109,7 @@ xfs_qm_dqput(
1122 break; 1109 break;
1123 dqp = gdqp; 1110 dqp = gdqp;
1124 } 1111 }
1125 xfs_qm_freelist_unlock(xfs_Gqm); 1112 mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
1126} 1113}
1127 1114
1128/* 1115/*
@@ -1396,7 +1383,7 @@ xfs_qm_dqpurge(
1396 return (1); 1383 return (1);
1397 } 1384 }
1398 1385
1399 ASSERT(XFS_DQ_IS_ON_FREELIST(dqp)); 1386 ASSERT(!list_empty(&dqp->q_freelist));
1400 1387
1401 /* 1388 /*
1402 * If we're turning off quotas, we have to make sure that, for 1389 * If we're turning off quotas, we have to make sure that, for
@@ -1450,7 +1437,7 @@ xfs_qm_dqpurge(
1450 * XXX Move this to the front of the freelist, if we can get the 1437 * XXX Move this to the front of the freelist, if we can get the
1451 * freelist lock. 1438 * freelist lock.
1452 */ 1439 */
1453 ASSERT(XFS_DQ_IS_ON_FREELIST(dqp)); 1440 ASSERT(!list_empty(&dqp->q_freelist));
1454 1441
1455 dqp->q_mount = NULL; 1442 dqp->q_mount = NULL;
1456 dqp->q_hash = NULL; 1443 dqp->q_hash = NULL;
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h
index 169b3c24af7..56fb21d81bc 100644
--- a/fs/xfs/quota/xfs_dquot.h
+++ b/fs/xfs/quota/xfs_dquot.h
@@ -50,8 +50,6 @@ struct xfs_trans;
50 * iterations because of locking considerations. 50 * iterations because of locking considerations.
51 */ 51 */
52typedef struct xfs_dqmarker { 52typedef struct xfs_dqmarker {
53 struct xfs_dquot*dqm_flnext; /* link to freelist: must be first */
54 struct xfs_dquot*dqm_flprev;
55 uint dqm_flags; /* various flags (XFS_DQ_*) */ 53 uint dqm_flags; /* various flags (XFS_DQ_*) */
56} xfs_dqmarker_t; 54} xfs_dqmarker_t;
57 55
@@ -60,8 +58,9 @@ typedef struct xfs_dqmarker {
60 */ 58 */
61typedef struct xfs_dquot { 59typedef struct xfs_dquot {
62 xfs_dqmarker_t q_lists; /* list ptrs, q_flags (marker) */ 60 xfs_dqmarker_t q_lists; /* list ptrs, q_flags (marker) */
61 struct list_head q_freelist; /* global free list of dquots */
63 struct list_head q_mplist; /* mount's list of dquots */ 62 struct list_head q_mplist; /* mount's list of dquots */
64 struct list_head q_hashlist; /* mount's list of dquots */ 63 struct list_head q_hashlist; /* gloabl hash list of dquots */
65 xfs_dqhash_t *q_hash; /* the hashchain header */ 64 xfs_dqhash_t *q_hash; /* the hashchain header */
66 struct xfs_mount*q_mount; /* filesystem this relates to */ 65 struct xfs_mount*q_mount; /* filesystem this relates to */
67 struct xfs_trans*q_transp; /* trans this belongs to currently */ 66 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 08e97f1ef65..c40ca94e23e 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -67,9 +67,6 @@ static cred_t xfs_zerocr;
67STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int); 67STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int);
68STATIC void xfs_qm_list_destroy(xfs_dqlist_t *); 68STATIC void xfs_qm_list_destroy(xfs_dqlist_t *);
69 69
70STATIC void xfs_qm_freelist_init(xfs_frlist_t *);
71STATIC void xfs_qm_freelist_destroy(xfs_frlist_t *);
72
73STATIC int xfs_qm_init_quotainos(xfs_mount_t *); 70STATIC int xfs_qm_init_quotainos(xfs_mount_t *);
74STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); 71STATIC int xfs_qm_init_quotainfo(xfs_mount_t *);
75STATIC int xfs_qm_shake(int, gfp_t); 72STATIC int xfs_qm_shake(int, gfp_t);
@@ -148,7 +145,9 @@ xfs_Gqm_init(void)
148 /* 145 /*
149 * Freelist of all dquots of all file systems 146 * Freelist of all dquots of all file systems
150 */ 147 */
151 xfs_qm_freelist_init(&(xqm->qm_dqfreelist)); 148 INIT_LIST_HEAD(&xqm->qm_dqfrlist);
149 xqm->qm_dqfrlist_cnt = 0;
150 mutex_init(&xqm->qm_dqfrlist_lock);
152 151
153 /* 152 /*
154 * dquot zone. we register our own low-memory callback. 153 * dquot zone. we register our own low-memory callback.
@@ -193,6 +192,7 @@ STATIC void
193xfs_qm_destroy( 192xfs_qm_destroy(
194 struct xfs_qm *xqm) 193 struct xfs_qm *xqm)
195{ 194{
195 struct xfs_dquot *dqp, *n;
196 int hsize, i; 196 int hsize, i;
197 197
198 ASSERT(xqm != NULL); 198 ASSERT(xqm != NULL);
@@ -208,7 +208,21 @@ xfs_qm_destroy(
208 xqm->qm_usr_dqhtable = NULL; 208 xqm->qm_usr_dqhtable = NULL;
209 xqm->qm_grp_dqhtable = NULL; 209 xqm->qm_grp_dqhtable = NULL;
210 xqm->qm_dqhashmask = 0; 210 xqm->qm_dqhashmask = 0;
211 xfs_qm_freelist_destroy(&(xqm->qm_dqfreelist)); 211
212 /* frlist cleanup */
213 mutex_lock(&xqm->qm_dqfrlist_lock);
214 list_for_each_entry_safe(dqp, n, &xqm->qm_dqfrlist, q_freelist) {
215 xfs_dqlock(dqp);
216#ifdef QUOTADEBUG
217 cmn_err(CE_DEBUG, "FREELIST destroy 0x%p", dqp);
218#endif
219 list_del_init(&dqp->q_freelist);
220 xfs_Gqm->qm_dqfrlist_cnt--;
221 xfs_dqunlock(dqp);
222 xfs_qm_dqdestroy(dqp);
223 }
224 mutex_unlock(&xqm->qm_dqfrlist_lock);
225 mutex_destroy(&xqm->qm_dqfrlist_lock);
212#ifdef DEBUG 226#ifdef DEBUG
213 mutex_destroy(&qcheck_lock); 227 mutex_destroy(&qcheck_lock);
214#endif 228#endif
@@ -260,7 +274,7 @@ STATIC void
260xfs_qm_rele_quotafs_ref( 274xfs_qm_rele_quotafs_ref(
261 struct xfs_mount *mp) 275 struct xfs_mount *mp)
262{ 276{
263 xfs_dquot_t *dqp, *nextdqp; 277 xfs_dquot_t *dqp, *n;
264 278
265 ASSERT(xfs_Gqm); 279 ASSERT(xfs_Gqm);
266 ASSERT(xfs_Gqm->qm_nrefs > 0); 280 ASSERT(xfs_Gqm->qm_nrefs > 0);
@@ -268,26 +282,24 @@ xfs_qm_rele_quotafs_ref(
268 /* 282 /*
269 * Go thru the freelist and destroy all inactive dquots. 283 * Go thru the freelist and destroy all inactive dquots.
270 */ 284 */
271 xfs_qm_freelist_lock(xfs_Gqm); 285 mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
272 286
273 for (dqp = xfs_Gqm->qm_dqfreelist.qh_next; 287 list_for_each_entry_safe(dqp, n, &xfs_Gqm->qm_dqfrlist, q_freelist) {
274 dqp != (xfs_dquot_t *)&(xfs_Gqm->qm_dqfreelist); ) {
275 xfs_dqlock(dqp); 288 xfs_dqlock(dqp);
276 nextdqp = dqp->dq_flnext;
277 if (dqp->dq_flags & XFS_DQ_INACTIVE) { 289 if (dqp->dq_flags & XFS_DQ_INACTIVE) {
278 ASSERT(dqp->q_mount == NULL); 290 ASSERT(dqp->q_mount == NULL);
279 ASSERT(! XFS_DQ_IS_DIRTY(dqp)); 291 ASSERT(! XFS_DQ_IS_DIRTY(dqp));
280 ASSERT(list_empty(&dqp->q_hashlist)); 292 ASSERT(list_empty(&dqp->q_hashlist));
281 ASSERT(list_empty(&dqp->q_mplist)); 293 ASSERT(list_empty(&dqp->q_mplist));
282 XQM_FREELIST_REMOVE(dqp); 294 list_del_init(&dqp->q_freelist);
295 xfs_Gqm->qm_dqfrlist_cnt--;
283 xfs_dqunlock(dqp); 296 xfs_dqunlock(dqp);
284 xfs_qm_dqdestroy(dqp); 297 xfs_qm_dqdestroy(dqp);
285 } else { 298 } else {
286 xfs_dqunlock(dqp); 299 xfs_dqunlock(dqp);
287 } 300 }
288 dqp = nextdqp;
289 } 301 }
290 xfs_qm_freelist_unlock(xfs_Gqm); 302 mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
291 303
292 /* 304 /*
293 * Destroy the entire XQM. If somebody mounts with quotaon, this'll 305 * Destroy the entire XQM. If somebody mounts with quotaon, this'll
@@ -1943,9 +1955,9 @@ xfs_qm_dqreclaim_one(void)
1943 1955
1944 /* lockorder: hashchainlock, freelistlock, mplistlock, dqlock, dqflock */ 1956 /* lockorder: hashchainlock, freelistlock, mplistlock, dqlock, dqflock */
1945startagain: 1957startagain:
1946 xfs_qm_freelist_lock(xfs_Gqm); 1958 mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
1947 1959
1948 FOREACH_DQUOT_IN_FREELIST(dqp, &(xfs_Gqm->qm_dqfreelist)) { 1960 list_for_each_entry(dqp, &xfs_Gqm->qm_dqfrlist, q_freelist) {
1949 struct xfs_mount *mp = dqp->q_mount; 1961 struct xfs_mount *mp = dqp->q_mount;
1950 xfs_dqlock(dqp); 1962 xfs_dqlock(dqp);
1951 1963
@@ -1961,7 +1973,7 @@ startagain:
1961 trace_xfs_dqreclaim_want(dqp); 1973 trace_xfs_dqreclaim_want(dqp);
1962 1974
1963 xfs_dqunlock(dqp); 1975 xfs_dqunlock(dqp);
1964 xfs_qm_freelist_unlock(xfs_Gqm); 1976 mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
1965 if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) 1977 if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
1966 return NULL; 1978 return NULL;
1967 XQM_STATS_INC(xqmstats.xs_qm_dqwants); 1979 XQM_STATS_INC(xqmstats.xs_qm_dqwants);
@@ -1978,7 +1990,8 @@ startagain:
1978 ASSERT(! XFS_DQ_IS_DIRTY(dqp)); 1990 ASSERT(! XFS_DQ_IS_DIRTY(dqp));
1979 ASSERT(list_empty(&dqp->q_hashlist)); 1991 ASSERT(list_empty(&dqp->q_hashlist));
1980 ASSERT(list_empty(&dqp->q_mplist)); 1992 ASSERT(list_empty(&dqp->q_mplist));
1981 XQM_FREELIST_REMOVE(dqp); 1993 list_del_init(&dqp->q_freelist);
1994 xfs_Gqm->qm_dqfrlist_cnt--;
1982 xfs_dqunlock(dqp); 1995 xfs_dqunlock(dqp);
1983 dqpout = dqp; 1996 dqpout = dqp;
1984 XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims); 1997 XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims);
@@ -2043,7 +2056,7 @@ startagain:
2043 mutex_unlock(&dqp->q_hash->qh_lock); 2056 mutex_unlock(&dqp->q_hash->qh_lock);
2044 xfs_dqfunlock(dqp); 2057 xfs_dqfunlock(dqp);
2045 xfs_dqunlock(dqp); 2058 xfs_dqunlock(dqp);
2046 xfs_qm_freelist_unlock(xfs_Gqm); 2059 mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
2047 if (restarts++ >= XFS_QM_RECLAIM_MAX_RESTARTS) 2060 if (restarts++ >= XFS_QM_RECLAIM_MAX_RESTARTS)
2048 return NULL; 2061 return NULL;
2049 goto startagain; 2062 goto startagain;
@@ -2055,7 +2068,8 @@ startagain:
2055 mp->m_quotainfo->qi_dqreclaims++; 2068 mp->m_quotainfo->qi_dqreclaims++;
2056 list_del_init(&dqp->q_hashlist); 2069 list_del_init(&dqp->q_hashlist);
2057 dqp->q_hash->qh_version++; 2070 dqp->q_hash->qh_version++;
2058 XQM_FREELIST_REMOVE(dqp); 2071 list_del_init(&dqp->q_freelist);
2072 xfs_Gqm->qm_dqfrlist_cnt--;
2059 dqpout = dqp; 2073 dqpout = dqp;
2060 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock); 2074 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
2061 mutex_unlock(&dqp->q_hash->qh_lock); 2075 mutex_unlock(&dqp->q_hash->qh_lock);
@@ -2067,7 +2081,7 @@ dqfunlock:
2067 if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) 2081 if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
2068 return NULL; 2082 return NULL;
2069 } 2083 }
2070 xfs_qm_freelist_unlock(xfs_Gqm); 2084 mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
2071 return dqpout; 2085 return dqpout;
2072} 2086}
2073 2087
@@ -2110,7 +2124,7 @@ xfs_qm_shake(int nr_to_scan, gfp_t gfp_mask)
2110 if (!xfs_Gqm) 2124 if (!xfs_Gqm)
2111 return 0; 2125 return 0;
2112 2126
2113 nfree = xfs_Gqm->qm_dqfreelist.qh_nelems; /* free dquots */ 2127 nfree = xfs_Gqm->qm_dqfrlist_cnt; /* free dquots */
2114 /* incore dquots in all f/s's */ 2128 /* incore dquots in all f/s's */
2115 ndqused = atomic_read(&xfs_Gqm->qm_totaldquots) - nfree; 2129 ndqused = atomic_read(&xfs_Gqm->qm_totaldquots) - nfree;
2116 2130
@@ -2550,66 +2564,3 @@ xfs_qm_vop_create_dqattach(
2550 } 2564 }
2551} 2565}
2552 2566
2553/* ------------- list stuff -----------------*/
2554STATIC void
2555xfs_qm_freelist_init(xfs_frlist_t *ql)
2556{
2557 ql->qh_next = ql->qh_prev = (xfs_dquot_t *) ql;
2558 mutex_init(&ql->qh_lock);
2559 ql->qh_version = 0;
2560 ql->qh_nelems = 0;
2561}
2562
2563STATIC void
2564xfs_qm_freelist_destroy(xfs_frlist_t *ql)
2565{
2566 xfs_dquot_t *dqp, *nextdqp;
2567
2568 mutex_lock(&ql->qh_lock);
2569 for (dqp = ql->qh_next;
2570 dqp != (xfs_dquot_t *)ql; ) {
2571 xfs_dqlock(dqp);
2572 nextdqp = dqp->dq_flnext;
2573#ifdef QUOTADEBUG
2574 cmn_err(CE_DEBUG, "FREELIST destroy 0x%p", dqp);
2575#endif
2576 XQM_FREELIST_REMOVE(dqp);
2577 xfs_dqunlock(dqp);
2578 xfs_qm_dqdestroy(dqp);
2579 dqp = nextdqp;
2580 }
2581 mutex_unlock(&ql->qh_lock);
2582 mutex_destroy(&ql->qh_lock);
2583
2584 ASSERT(ql->qh_nelems == 0);
2585}
2586
2587STATIC void
2588xfs_qm_freelist_insert(xfs_frlist_t *ql, xfs_dquot_t *dq)
2589{
2590 dq->dq_flnext = ql->qh_next;
2591 dq->dq_flprev = (xfs_dquot_t *)ql;
2592 ql->qh_next = dq;
2593 dq->dq_flnext->dq_flprev = dq;
2594 xfs_Gqm->qm_dqfreelist.qh_nelems++;
2595 xfs_Gqm->qm_dqfreelist.qh_version++;
2596}
2597
2598void
2599xfs_qm_freelist_unlink(xfs_dquot_t *dq)
2600{
2601 xfs_dquot_t *next = dq->dq_flnext;
2602 xfs_dquot_t *prev = dq->dq_flprev;
2603
2604 next->dq_flprev = prev;
2605 prev->dq_flnext = next;
2606 dq->dq_flnext = dq->dq_flprev = dq;
2607 xfs_Gqm->qm_dqfreelist.qh_nelems--;
2608 xfs_Gqm->qm_dqfreelist.qh_version++;
2609}
2610
2611void
2612xfs_qm_freelist_append(xfs_frlist_t *ql, xfs_dquot_t *dq)
2613{
2614 xfs_qm_freelist_insert((xfs_frlist_t *)ql->qh_prev, dq);
2615}
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
index 91bd053e90b..c9446f1c726 100644
--- a/fs/xfs/quota/xfs_qm.h
+++ b/fs/xfs/quota/xfs_qm.h
@@ -72,17 +72,6 @@ extern kmem_zone_t *qm_dqtrxzone;
72#define XFS_QM_MAX_DQCLUSTER_LOGSZ 3 72#define XFS_QM_MAX_DQCLUSTER_LOGSZ 3
73 73
74typedef xfs_dqhash_t xfs_dqlist_t; 74typedef xfs_dqhash_t xfs_dqlist_t;
75/*
76 * The freelist head. The first two fields match the first two in the
77 * xfs_dquot_t structure (in xfs_dqmarker_t)
78 */
79typedef struct xfs_frlist {
80 struct xfs_dquot *qh_next;
81 struct xfs_dquot *qh_prev;
82 struct mutex qh_lock;
83 uint qh_version;
84 uint qh_nelems;
85} xfs_frlist_t;
86 75
87/* 76/*
88 * Quota Manager (global) structure. Lives only in core. 77 * Quota Manager (global) structure. Lives only in core.
@@ -91,7 +80,9 @@ typedef struct xfs_qm {
91 xfs_dqlist_t *qm_usr_dqhtable;/* udquot hash table */ 80 xfs_dqlist_t *qm_usr_dqhtable;/* udquot hash table */
92 xfs_dqlist_t *qm_grp_dqhtable;/* gdquot hash table */ 81 xfs_dqlist_t *qm_grp_dqhtable;/* gdquot hash table */
93 uint qm_dqhashmask; /* # buckets in dq hashtab - 1 */ 82 uint qm_dqhashmask; /* # buckets in dq hashtab - 1 */
94 xfs_frlist_t qm_dqfreelist; /* freelist of dquots */ 83 struct list_head qm_dqfrlist; /* freelist of dquots */
84 struct mutex qm_dqfrlist_lock;
85 int qm_dqfrlist_cnt;
95 atomic_t qm_totaldquots; /* total incore dquots */ 86 atomic_t qm_totaldquots; /* total incore dquots */
96 uint qm_nrefs; /* file systems with quota on */ 87 uint qm_nrefs; /* file systems with quota on */
97 int qm_dqfree_ratio;/* ratio of free to inuse dquots */ 88 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 *);
177extern int xfs_qm_scall_quotaon(xfs_mount_t *, uint); 168extern int xfs_qm_scall_quotaon(xfs_mount_t *, uint);
178extern int xfs_qm_scall_quotaoff(xfs_mount_t *, uint); 169extern int xfs_qm_scall_quotaoff(xfs_mount_t *, uint);
179 170
180/* list stuff */
181extern void xfs_qm_freelist_append(xfs_frlist_t *, xfs_dquot_t *);
182extern void xfs_qm_freelist_unlink(xfs_dquot_t *);
183
184#ifdef DEBUG 171#ifdef DEBUG
185extern int xfs_qm_internalqcheck(xfs_mount_t *); 172extern int xfs_qm_internalqcheck(xfs_mount_t *);
186#else 173#else
diff --git a/fs/xfs/quota/xfs_qm_stats.c b/fs/xfs/quota/xfs_qm_stats.c
index 83e7ea3e25f..3d1fc79532e 100644
--- a/fs/xfs/quota/xfs_qm_stats.c
+++ b/fs/xfs/quota/xfs_qm_stats.c
@@ -55,7 +55,7 @@ static int xqm_proc_show(struct seq_file *m, void *v)
55 ndquot, 55 ndquot,
56 xfs_Gqm? atomic_read(&xfs_Gqm->qm_totaldquots) : 0, 56 xfs_Gqm? atomic_read(&xfs_Gqm->qm_totaldquots) : 0,
57 xfs_Gqm? xfs_Gqm->qm_dqfree_ratio : 0, 57 xfs_Gqm? xfs_Gqm->qm_dqfree_ratio : 0,
58 xfs_Gqm? xfs_Gqm->qm_dqfreelist.qh_nelems : 0); 58 xfs_Gqm? xfs_Gqm->qm_dqfrlist_cnt : 0);
59 return 0; 59 return 0;
60} 60}
61 61
diff --git a/fs/xfs/quota/xfs_quota_priv.h b/fs/xfs/quota/xfs_quota_priv.h
index 3a1b9aa763f..3eeee2e591d 100644
--- a/fs/xfs/quota/xfs_quota_priv.h
+++ b/fs/xfs/quota/xfs_quota_priv.h
@@ -40,13 +40,6 @@
40#define XFS_QI_IWARNLIMIT(mp) ((mp)->m_quotainfo->qi_iwarnlimit) 40#define XFS_QI_IWARNLIMIT(mp) ((mp)->m_quotainfo->qi_iwarnlimit)
41#define XFS_QI_QOFFLOCK(mp) ((mp)->m_quotainfo->qi_quotaofflock) 41#define XFS_QI_QOFFLOCK(mp) ((mp)->m_quotainfo->qi_quotaofflock)
42 42
43#define xfs_qm_freelist_lock(qm) \
44 mutex_lock(&((qm)->qm_dqfreelist.qh_lock))
45#define xfs_qm_freelist_lock_nowait(qm) \
46 mutex_trylock(&((qm)->qm_dqfreelist.qh_lock))
47#define xfs_qm_freelist_unlock(qm) \
48 mutex_unlock(&((qm)->qm_dqfreelist.qh_lock))
49
50/* 43/*
51 * Hash into a bucket in the dquot hash table, based on <mp, id>. 44 * Hash into a bucket in the dquot hash table, based on <mp, id>.
52 */ 45 */
@@ -72,16 +65,6 @@
72 !dqp->q_core.d_rtbcount && \ 65 !dqp->q_core.d_rtbcount && \
73 !dqp->q_core.d_icount) 66 !dqp->q_core.d_icount)
74 67
75#define FOREACH_DQUOT_IN_FREELIST(dqp, qlist) \
76for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \
77 (dqp) = (dqp)->dq_flnext)
78
79#define XQM_FREELIST_INSERT(h, dqp) \
80 xfs_qm_freelist_append(h, dqp)
81
82#define XQM_FREELIST_REMOVE(dqp) \
83 xfs_qm_freelist_unlink(dqp)
84
85#define XFS_DQ_IS_LOGITEM_INITD(dqp) ((dqp)->q_logitem.qli_dquot == (dqp)) 68#define XFS_DQ_IS_LOGITEM_INITD(dqp) ((dqp)->q_logitem.qli_dquot == (dqp))
86 69
87#define XFS_QM_DQP_TO_DQACCT(tp, dqp) (XFS_QM_ISUDQ(dqp) ? \ 70#define XFS_QM_DQP_TO_DQACCT(tp, dqp) (XFS_QM_ISUDQ(dqp) ? \