diff options
author | Christoph Hellwig <hch@infradead.org> | 2012-03-13 04:52:34 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-03-14 12:09:06 -0400 |
commit | f8739c3ce2ac9a01515b56026b6a066c0808234b (patch) | |
tree | c3f7b877b5be6e12c62028de7da46fef3e537dc7 /fs/xfs/xfs_dquot.c | |
parent | 48776fd22344ad80adcbac0abc9c0da60c6481d2 (diff) |
xfs: per-filesystem dquot LRU lists
Replace the global dquot lru lists with a per-filesystem one.
Note that the shrinker isn't wire up to the per-superblock VFS shrinker
infrastructure as would have problems summing up and splitting the counts
for inodes and dquots. I don't think this is a major problem as the quota
cache isn't as interwinded with the inode cache as the dentry cache is,
because an inode that is dropped from the cache will generally release
a dquot reference, but most of the time it won't be the last one.
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/xfs_dquot.c')
-rw-r--r-- | fs/xfs/xfs_dquot.c | 84 |
1 files changed, 44 insertions, 40 deletions
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 98d7e25947fa..fec1a3d78e9f 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c | |||
@@ -47,7 +47,7 @@ | |||
47 | * qi->qi_dqlist_lock | 47 | * qi->qi_dqlist_lock |
48 | * dquot->q_qlock (xfs_dqlock() and friends) | 48 | * dquot->q_qlock (xfs_dqlock() and friends) |
49 | * dquot->q_flush (xfs_dqflock() and friends) | 49 | * dquot->q_flush (xfs_dqflock() and friends) |
50 | * xfs_Gqm->qm_dqfrlist_lock | 50 | * qi->qi_lru_lock |
51 | * | 51 | * |
52 | * If two dquots need to be locked the order is user before group/project, | 52 | * If two dquots need to be locked the order is user before group/project, |
53 | * otherwise by the lowest id first, see xfs_dqlock2. | 53 | * otherwise by the lowest id first, see xfs_dqlock2. |
@@ -69,7 +69,7 @@ void | |||
69 | xfs_qm_dqdestroy( | 69 | xfs_qm_dqdestroy( |
70 | xfs_dquot_t *dqp) | 70 | xfs_dquot_t *dqp) |
71 | { | 71 | { |
72 | ASSERT(list_empty(&dqp->q_freelist)); | 72 | ASSERT(list_empty(&dqp->q_lru)); |
73 | 73 | ||
74 | mutex_destroy(&dqp->q_qlock); | 74 | mutex_destroy(&dqp->q_qlock); |
75 | kmem_zone_free(xfs_Gqm->qm_dqzone, dqp); | 75 | kmem_zone_free(xfs_Gqm->qm_dqzone, dqp); |
@@ -497,7 +497,7 @@ xfs_qm_dqread( | |||
497 | dqp->dq_flags = type; | 497 | dqp->dq_flags = type; |
498 | dqp->q_core.d_id = cpu_to_be32(id); | 498 | dqp->q_core.d_id = cpu_to_be32(id); |
499 | dqp->q_mount = mp; | 499 | dqp->q_mount = mp; |
500 | INIT_LIST_HEAD(&dqp->q_freelist); | 500 | INIT_LIST_HEAD(&dqp->q_lru); |
501 | mutex_init(&dqp->q_qlock); | 501 | mutex_init(&dqp->q_qlock); |
502 | init_waitqueue_head(&dqp->q_pinwait); | 502 | init_waitqueue_head(&dqp->q_pinwait); |
503 | 503 | ||
@@ -844,38 +844,22 @@ restart: | |||
844 | } | 844 | } |
845 | 845 | ||
846 | 846 | ||
847 | /* | 847 | STATIC void |
848 | * Release a reference to the dquot (decrement ref-count) | 848 | xfs_qm_dqput_final( |
849 | * and unlock it. If there is a group quota attached to this | ||
850 | * dquot, carefully release that too without tripping over | ||
851 | * deadlocks'n'stuff. | ||
852 | */ | ||
853 | void | ||
854 | xfs_qm_dqput( | ||
855 | struct xfs_dquot *dqp) | 849 | struct xfs_dquot *dqp) |
856 | { | 850 | { |
851 | struct xfs_quotainfo *qi = dqp->q_mount->m_quotainfo; | ||
857 | struct xfs_dquot *gdqp; | 852 | struct xfs_dquot *gdqp; |
858 | 853 | ||
859 | ASSERT(dqp->q_nrefs > 0); | ||
860 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | ||
861 | |||
862 | trace_xfs_dqput(dqp); | ||
863 | |||
864 | recurse: | ||
865 | if (--dqp->q_nrefs > 0) { | ||
866 | xfs_dqunlock(dqp); | ||
867 | return; | ||
868 | } | ||
869 | |||
870 | trace_xfs_dqput_free(dqp); | 854 | trace_xfs_dqput_free(dqp); |
871 | 855 | ||
872 | mutex_lock(&xfs_Gqm->qm_dqfrlist_lock); | 856 | mutex_lock(&qi->qi_lru_lock); |
873 | if (list_empty(&dqp->q_freelist)) { | 857 | if (list_empty(&dqp->q_lru)) { |
874 | list_add_tail(&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist); | 858 | list_add_tail(&dqp->q_lru, &qi->qi_lru_list); |
875 | xfs_Gqm->qm_dqfrlist_cnt++; | 859 | qi->qi_lru_count++; |
876 | XFS_STATS_INC(xs_qm_dquot_unused); | 860 | XFS_STATS_INC(xs_qm_dquot_unused); |
877 | } | 861 | } |
878 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); | 862 | mutex_unlock(&qi->qi_lru_lock); |
879 | 863 | ||
880 | /* | 864 | /* |
881 | * If we just added a udquot to the freelist, then we want to release | 865 | * If we just added a udquot to the freelist, then we want to release |
@@ -892,10 +876,29 @@ recurse: | |||
892 | /* | 876 | /* |
893 | * If we had a group quota hint, release it now. | 877 | * If we had a group quota hint, release it now. |
894 | */ | 878 | */ |
895 | if (gdqp) { | 879 | if (gdqp) |
896 | dqp = gdqp; | 880 | xfs_qm_dqput(gdqp); |
897 | goto recurse; | 881 | } |
898 | } | 882 | |
883 | /* | ||
884 | * Release a reference to the dquot (decrement ref-count) and unlock it. | ||
885 | * | ||
886 | * If there is a group quota attached to this dquot, carefully release that | ||
887 | * too without tripping over deadlocks'n'stuff. | ||
888 | */ | ||
889 | void | ||
890 | xfs_qm_dqput( | ||
891 | struct xfs_dquot *dqp) | ||
892 | { | ||
893 | ASSERT(dqp->q_nrefs > 0); | ||
894 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | ||
895 | |||
896 | trace_xfs_dqput(dqp); | ||
897 | |||
898 | if (--dqp->q_nrefs > 0) | ||
899 | xfs_dqunlock(dqp); | ||
900 | else | ||
901 | xfs_qm_dqput_final(dqp); | ||
899 | } | 902 | } |
900 | 903 | ||
901 | /* | 904 | /* |
@@ -1115,6 +1118,7 @@ xfs_qm_dqpurge( | |||
1115 | { | 1118 | { |
1116 | struct xfs_mount *mp = dqp->q_mount; | 1119 | struct xfs_mount *mp = dqp->q_mount; |
1117 | struct xfs_dqhash *qh = dqp->q_hash; | 1120 | struct xfs_dqhash *qh = dqp->q_hash; |
1121 | struct xfs_quotainfo *qi = mp->m_quotainfo; | ||
1118 | 1122 | ||
1119 | xfs_dqlock(dqp); | 1123 | xfs_dqlock(dqp); |
1120 | 1124 | ||
@@ -1165,22 +1169,22 @@ xfs_qm_dqpurge( | |||
1165 | qh->qh_version++; | 1169 | qh->qh_version++; |
1166 | mutex_unlock(&qh->qh_lock); | 1170 | mutex_unlock(&qh->qh_lock); |
1167 | 1171 | ||
1168 | mutex_lock(&mp->m_quotainfo->qi_dqlist_lock); | 1172 | mutex_lock(&qi->qi_dqlist_lock); |
1169 | list_del_init(&dqp->q_mplist); | 1173 | list_del_init(&dqp->q_mplist); |
1170 | mp->m_quotainfo->qi_dqreclaims++; | 1174 | qi->qi_dqreclaims++; |
1171 | mp->m_quotainfo->qi_dquots--; | 1175 | qi->qi_dquots--; |
1172 | mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock); | 1176 | mutex_unlock(&qi->qi_dqlist_lock); |
1173 | 1177 | ||
1174 | /* | 1178 | /* |
1175 | * We move dquots to the freelist as soon as their reference count | 1179 | * We move dquots to the freelist as soon as their reference count |
1176 | * hits zero, so it really should be on the freelist here. | 1180 | * hits zero, so it really should be on the freelist here. |
1177 | */ | 1181 | */ |
1178 | mutex_lock(&xfs_Gqm->qm_dqfrlist_lock); | 1182 | mutex_lock(&qi->qi_lru_lock); |
1179 | ASSERT(!list_empty(&dqp->q_freelist)); | 1183 | ASSERT(!list_empty(&dqp->q_lru)); |
1180 | list_del_init(&dqp->q_freelist); | 1184 | list_del_init(&dqp->q_lru); |
1181 | xfs_Gqm->qm_dqfrlist_cnt--; | 1185 | qi->qi_lru_count--; |
1182 | XFS_STATS_DEC(xs_qm_dquot_unused); | 1186 | XFS_STATS_DEC(xs_qm_dquot_unused); |
1183 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); | 1187 | mutex_unlock(&qi->qi_lru_lock); |
1184 | 1188 | ||
1185 | xfs_qm_dqdestroy(dqp); | 1189 | xfs_qm_dqdestroy(dqp); |
1186 | } | 1190 | } |