aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_dquot.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2012-03-13 04:52:34 -0400
committerBen Myers <bpm@sgi.com>2012-03-14 12:09:06 -0400
commitf8739c3ce2ac9a01515b56026b6a066c0808234b (patch)
treec3f7b877b5be6e12c62028de7da46fef3e537dc7 /fs/xfs/xfs_dquot.c
parent48776fd22344ad80adcbac0abc9c0da60c6481d2 (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.c84
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
69xfs_qm_dqdestroy( 69xfs_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/* 847STATIC void
848 * Release a reference to the dquot (decrement ref-count) 848xfs_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 */
853void
854xfs_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
864recurse:
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 */
889void
890xfs_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}