diff options
author | Dave Chinner <dchinner@redhat.com> | 2010-04-13 01:06:52 -0400 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2010-05-19 10:58:11 -0400 |
commit | 3a8406f6d6916e8211936edb9e1193123df2daab (patch) | |
tree | 53f490a433ef3bd2f430ef19cdfbbe5dc514e89d /fs | |
parent | e6a81f13aa9aa20ef03174210aed24791865b05e (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')
-rw-r--r-- | fs/xfs/quota/xfs_dquot.c | 75 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_dquot.h | 5 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_qm.c | 119 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_qm.h | 19 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_qm_stats.c | 2 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_quota_priv.h | 17 |
6 files changed, 72 insertions, 165 deletions
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index ad64ab62d9c5..02dac0a5f1ec 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 | |||
158 | xfs_qm_dqdestroy( | 158 | xfs_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 169b3c24af79..56fb21d81bc4 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 | */ |
52 | typedef struct xfs_dqmarker { | 52 | typedef 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 | */ |
61 | typedef struct xfs_dquot { | 59 | typedef 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 08e97f1ef653..c40ca94e23ea 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
@@ -67,9 +67,6 @@ static cred_t xfs_zerocr; | |||
67 | STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int); | 67 | STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int); |
68 | STATIC void xfs_qm_list_destroy(xfs_dqlist_t *); | 68 | STATIC void xfs_qm_list_destroy(xfs_dqlist_t *); |
69 | 69 | ||
70 | STATIC void xfs_qm_freelist_init(xfs_frlist_t *); | ||
71 | STATIC void xfs_qm_freelist_destroy(xfs_frlist_t *); | ||
72 | |||
73 | STATIC int xfs_qm_init_quotainos(xfs_mount_t *); | 70 | STATIC int xfs_qm_init_quotainos(xfs_mount_t *); |
74 | STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); | 71 | STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); |
75 | STATIC int xfs_qm_shake(int, gfp_t); | 72 | STATIC 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 | |||
193 | xfs_qm_destroy( | 192 | xfs_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 | |||
260 | xfs_qm_rele_quotafs_ref( | 274 | xfs_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 */ |
1945 | startagain: | 1957 | startagain: |
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 -----------------*/ | ||
2554 | STATIC void | ||
2555 | xfs_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 | |||
2563 | STATIC void | ||
2564 | xfs_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 | |||
2587 | STATIC void | ||
2588 | xfs_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 | |||
2598 | void | ||
2599 | xfs_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 | |||
2611 | void | ||
2612 | xfs_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 91bd053e90ba..c9446f1c726d 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 | ||
74 | typedef xfs_dqhash_t xfs_dqlist_t; | 74 | typedef 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 | */ | ||
79 | typedef 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 *); | |||
177 | extern int xfs_qm_scall_quotaon(xfs_mount_t *, uint); | 168 | extern int xfs_qm_scall_quotaon(xfs_mount_t *, uint); |
178 | extern int xfs_qm_scall_quotaoff(xfs_mount_t *, uint); | 169 | extern int xfs_qm_scall_quotaoff(xfs_mount_t *, uint); |
179 | 170 | ||
180 | /* list stuff */ | ||
181 | extern void xfs_qm_freelist_append(xfs_frlist_t *, xfs_dquot_t *); | ||
182 | extern void xfs_qm_freelist_unlink(xfs_dquot_t *); | ||
183 | |||
184 | #ifdef DEBUG | 171 | #ifdef DEBUG |
185 | extern int xfs_qm_internalqcheck(xfs_mount_t *); | 172 | extern 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 83e7ea3e25fa..3d1fc79532e2 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 3a1b9aa763fc..3eeee2e591df 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) \ | ||
76 | for ((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) ? \ |