diff options
author | Christoph Hellwig <hch@infradead.org> | 2011-12-06 16:58:16 -0500 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2011-12-13 15:55:54 -0500 |
commit | 80a376bfb7f8ff8f1942cb1bdd0052e908918252 (patch) | |
tree | f370553d188065bfa2722b74076ef81b111cd477 /fs/xfs | |
parent | 497507b9ee63499d364ad7149c584285cd925dfc (diff) |
xfs: remove XFS_DQ_INACTIVE
Free dquots when purging them during umount instead of keeping them around
on the freelist in a degraded state. The out of order locking in
xfs_qm_dqpurge will be removed again later in this series.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_dquot.c | 28 | ||||
-rw-r--r-- | fs/xfs/xfs_qm.c | 61 | ||||
-rw-r--r-- | fs/xfs/xfs_quota.h | 4 |
3 files changed, 24 insertions, 69 deletions
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 2a9ffc1086bc..3f94f2428a35 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c | |||
@@ -1302,6 +1302,14 @@ xfs_qm_dqpurge( | |||
1302 | ASSERT(mutex_is_locked(&mp->m_quotainfo->qi_dqlist_lock)); | 1302 | ASSERT(mutex_is_locked(&mp->m_quotainfo->qi_dqlist_lock)); |
1303 | ASSERT(mutex_is_locked(&dqp->q_hash->qh_lock)); | 1303 | ASSERT(mutex_is_locked(&dqp->q_hash->qh_lock)); |
1304 | 1304 | ||
1305 | /* | ||
1306 | * XXX(hch): horrible locking order, will get cleaned up ASAP. | ||
1307 | */ | ||
1308 | if (!mutex_trylock(&xfs_Gqm->qm_dqfrlist_lock)) { | ||
1309 | mutex_unlock(&dqp->q_hash->qh_lock); | ||
1310 | return 1; | ||
1311 | } | ||
1312 | |||
1305 | xfs_dqlock(dqp); | 1313 | xfs_dqlock(dqp); |
1306 | /* | 1314 | /* |
1307 | * We really can't afford to purge a dquot that is | 1315 | * We really can't afford to purge a dquot that is |
@@ -1364,25 +1372,23 @@ xfs_qm_dqpurge( | |||
1364 | 1372 | ||
1365 | list_del_init(&dqp->q_hashlist); | 1373 | list_del_init(&dqp->q_hashlist); |
1366 | qh->qh_version++; | 1374 | qh->qh_version++; |
1375 | |||
1367 | list_del_init(&dqp->q_mplist); | 1376 | list_del_init(&dqp->q_mplist); |
1368 | mp->m_quotainfo->qi_dqreclaims++; | 1377 | mp->m_quotainfo->qi_dqreclaims++; |
1369 | mp->m_quotainfo->qi_dquots--; | 1378 | mp->m_quotainfo->qi_dquots--; |
1370 | /* | ||
1371 | * XXX Move this to the front of the freelist, if we can get the | ||
1372 | * freelist lock. | ||
1373 | */ | ||
1374 | ASSERT(!list_empty(&dqp->q_freelist)); | ||
1375 | 1379 | ||
1376 | dqp->q_mount = NULL; | 1380 | list_del_init(&dqp->q_freelist); |
1377 | dqp->q_hash = NULL; | 1381 | xfs_Gqm->qm_dqfrlist_cnt--; |
1378 | dqp->dq_flags = XFS_DQ_INACTIVE; | 1382 | |
1379 | memset(&dqp->q_core, 0, sizeof(dqp->q_core)); | ||
1380 | xfs_dqfunlock(dqp); | 1383 | xfs_dqfunlock(dqp); |
1381 | xfs_dqunlock(dqp); | 1384 | xfs_dqunlock(dqp); |
1385 | |||
1386 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); | ||
1382 | mutex_unlock(&qh->qh_lock); | 1387 | mutex_unlock(&qh->qh_lock); |
1383 | return (0); | ||
1384 | } | ||
1385 | 1388 | ||
1389 | xfs_qm_dqdestroy(dqp); | ||
1390 | return 0; | ||
1391 | } | ||
1386 | 1392 | ||
1387 | /* | 1393 | /* |
1388 | * Give the buffer a little push if it is incore and | 1394 | * Give the buffer a little push if it is incore and |
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 6535c4e5f875..be1df6839237 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c | |||
@@ -154,12 +154,17 @@ STATIC void | |||
154 | xfs_qm_destroy( | 154 | xfs_qm_destroy( |
155 | struct xfs_qm *xqm) | 155 | struct xfs_qm *xqm) |
156 | { | 156 | { |
157 | struct xfs_dquot *dqp, *n; | ||
158 | int hsize, i; | 157 | int hsize, i; |
159 | 158 | ||
160 | ASSERT(xqm != NULL); | 159 | ASSERT(xqm != NULL); |
161 | ASSERT(xqm->qm_nrefs == 0); | 160 | ASSERT(xqm->qm_nrefs == 0); |
161 | |||
162 | unregister_shrinker(&xfs_qm_shaker); | 162 | unregister_shrinker(&xfs_qm_shaker); |
163 | |||
164 | mutex_lock(&xqm->qm_dqfrlist_lock); | ||
165 | ASSERT(list_empty(&xqm->qm_dqfrlist)); | ||
166 | mutex_unlock(&xqm->qm_dqfrlist_lock); | ||
167 | |||
163 | hsize = xqm->qm_dqhashmask + 1; | 168 | hsize = xqm->qm_dqhashmask + 1; |
164 | for (i = 0; i < hsize; i++) { | 169 | for (i = 0; i < hsize; i++) { |
165 | xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i])); | 170 | xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i])); |
@@ -171,17 +176,6 @@ xfs_qm_destroy( | |||
171 | xqm->qm_grp_dqhtable = NULL; | 176 | xqm->qm_grp_dqhtable = NULL; |
172 | xqm->qm_dqhashmask = 0; | 177 | xqm->qm_dqhashmask = 0; |
173 | 178 | ||
174 | /* frlist cleanup */ | ||
175 | mutex_lock(&xqm->qm_dqfrlist_lock); | ||
176 | list_for_each_entry_safe(dqp, n, &xqm->qm_dqfrlist, q_freelist) { | ||
177 | xfs_dqlock(dqp); | ||
178 | list_del_init(&dqp->q_freelist); | ||
179 | xfs_Gqm->qm_dqfrlist_cnt--; | ||
180 | xfs_dqunlock(dqp); | ||
181 | xfs_qm_dqdestroy(dqp); | ||
182 | } | ||
183 | mutex_unlock(&xqm->qm_dqfrlist_lock); | ||
184 | mutex_destroy(&xqm->qm_dqfrlist_lock); | ||
185 | kmem_free(xqm); | 179 | kmem_free(xqm); |
186 | } | 180 | } |
187 | 181 | ||
@@ -232,34 +226,10 @@ STATIC void | |||
232 | xfs_qm_rele_quotafs_ref( | 226 | xfs_qm_rele_quotafs_ref( |
233 | struct xfs_mount *mp) | 227 | struct xfs_mount *mp) |
234 | { | 228 | { |
235 | xfs_dquot_t *dqp, *n; | ||
236 | |||
237 | ASSERT(xfs_Gqm); | 229 | ASSERT(xfs_Gqm); |
238 | ASSERT(xfs_Gqm->qm_nrefs > 0); | 230 | ASSERT(xfs_Gqm->qm_nrefs > 0); |
239 | 231 | ||
240 | /* | 232 | /* |
241 | * Go thru the freelist and destroy all inactive dquots. | ||
242 | */ | ||
243 | mutex_lock(&xfs_Gqm->qm_dqfrlist_lock); | ||
244 | |||
245 | list_for_each_entry_safe(dqp, n, &xfs_Gqm->qm_dqfrlist, q_freelist) { | ||
246 | xfs_dqlock(dqp); | ||
247 | if (dqp->dq_flags & XFS_DQ_INACTIVE) { | ||
248 | ASSERT(dqp->q_mount == NULL); | ||
249 | ASSERT(! XFS_DQ_IS_DIRTY(dqp)); | ||
250 | ASSERT(list_empty(&dqp->q_hashlist)); | ||
251 | ASSERT(list_empty(&dqp->q_mplist)); | ||
252 | list_del_init(&dqp->q_freelist); | ||
253 | xfs_Gqm->qm_dqfrlist_cnt--; | ||
254 | xfs_dqunlock(dqp); | ||
255 | xfs_qm_dqdestroy(dqp); | ||
256 | } else { | ||
257 | xfs_dqunlock(dqp); | ||
258 | } | ||
259 | } | ||
260 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); | ||
261 | |||
262 | /* | ||
263 | * Destroy the entire XQM. If somebody mounts with quotaon, this'll | 233 | * Destroy the entire XQM. If somebody mounts with quotaon, this'll |
264 | * be restarted. | 234 | * be restarted. |
265 | */ | 235 | */ |
@@ -1728,8 +1698,6 @@ again: | |||
1728 | * both the dquot and the freelistlock. | 1698 | * both the dquot and the freelistlock. |
1729 | */ | 1699 | */ |
1730 | if (dqp->dq_flags & XFS_DQ_WANT) { | 1700 | if (dqp->dq_flags & XFS_DQ_WANT) { |
1731 | ASSERT(! (dqp->dq_flags & XFS_DQ_INACTIVE)); | ||
1732 | |||
1733 | trace_xfs_dqreclaim_want(dqp); | 1701 | trace_xfs_dqreclaim_want(dqp); |
1734 | XQM_STATS_INC(xqmstats.xs_qm_dqwants); | 1702 | XQM_STATS_INC(xqmstats.xs_qm_dqwants); |
1735 | restarts++; | 1703 | restarts++; |
@@ -1737,23 +1705,6 @@ again: | |||
1737 | goto dqunlock; | 1705 | goto dqunlock; |
1738 | } | 1706 | } |
1739 | 1707 | ||
1740 | /* | ||
1741 | * If the dquot is inactive, we are assured that it is | ||
1742 | * not on the mplist or the hashlist, and that makes our | ||
1743 | * life easier. | ||
1744 | */ | ||
1745 | if (dqp->dq_flags & XFS_DQ_INACTIVE) { | ||
1746 | ASSERT(mp == NULL); | ||
1747 | ASSERT(! XFS_DQ_IS_DIRTY(dqp)); | ||
1748 | ASSERT(list_empty(&dqp->q_hashlist)); | ||
1749 | ASSERT(list_empty(&dqp->q_mplist)); | ||
1750 | list_del_init(&dqp->q_freelist); | ||
1751 | xfs_Gqm->qm_dqfrlist_cnt--; | ||
1752 | dqpout = dqp; | ||
1753 | XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims); | ||
1754 | goto dqunlock; | ||
1755 | } | ||
1756 | |||
1757 | ASSERT(dqp->q_hash); | 1708 | ASSERT(dqp->q_hash); |
1758 | ASSERT(!list_empty(&dqp->q_mplist)); | 1709 | ASSERT(!list_empty(&dqp->q_mplist)); |
1759 | 1710 | ||
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 707ba33e3196..cbafdee8b98a 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h | |||
@@ -88,7 +88,6 @@ typedef struct xfs_dqblk { | |||
88 | #define XFS_DQ_GROUP 0x0004 /* a group quota */ | 88 | #define XFS_DQ_GROUP 0x0004 /* a group quota */ |
89 | #define XFS_DQ_DIRTY 0x0008 /* dquot is dirty */ | 89 | #define XFS_DQ_DIRTY 0x0008 /* dquot is dirty */ |
90 | #define XFS_DQ_WANT 0x0010 /* for lookup/reclaim race */ | 90 | #define XFS_DQ_WANT 0x0010 /* for lookup/reclaim race */ |
91 | #define XFS_DQ_INACTIVE 0x0020 /* dq off mplist & hashlist */ | ||
92 | 91 | ||
93 | #define XFS_DQ_ALLTYPES (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP) | 92 | #define XFS_DQ_ALLTYPES (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP) |
94 | 93 | ||
@@ -97,8 +96,7 @@ typedef struct xfs_dqblk { | |||
97 | { XFS_DQ_PROJ, "PROJ" }, \ | 96 | { XFS_DQ_PROJ, "PROJ" }, \ |
98 | { XFS_DQ_GROUP, "GROUP" }, \ | 97 | { XFS_DQ_GROUP, "GROUP" }, \ |
99 | { XFS_DQ_DIRTY, "DIRTY" }, \ | 98 | { XFS_DQ_DIRTY, "DIRTY" }, \ |
100 | { XFS_DQ_WANT, "WANT" }, \ | 99 | { XFS_DQ_WANT, "WANT" } |
101 | { XFS_DQ_INACTIVE, "INACTIVE" } | ||
102 | 100 | ||
103 | /* | 101 | /* |
104 | * In the worst case, when both user and group quotas are on, | 102 | * In the worst case, when both user and group quotas are on, |