aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_qm.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2012-03-13 04:52:35 -0400
committerBen Myers <bpm@sgi.com>2012-03-14 12:09:06 -0400
commit9f920f116426806bfa34c1422742e1bf7b7a2b4b (patch)
tree3ec0a4f006dc10ed56e5bec1b605f5ecbb3a3275 /fs/xfs/xfs_qm.c
parentf8739c3ce2ac9a01515b56026b6a066c0808234b (diff)
xfs: use per-filesystem radix trees for dquot lookup
Replace the global hash tables for looking up in-memory dquot structures with per-filesystem radix trees to allow scaling to a large number of in-memory dquot structures. Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_qm.c')
-rw-r--r--fs/xfs/xfs_qm.c95
1 files changed, 8 insertions, 87 deletions
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index a2579e1d687f..bb884e701cd9 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -54,9 +54,6 @@ struct xfs_qm *xfs_Gqm;
54kmem_zone_t *qm_dqzone; 54kmem_zone_t *qm_dqzone;
55kmem_zone_t *qm_dqtrxzone; 55kmem_zone_t *qm_dqtrxzone;
56 56
57STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int);
58STATIC void xfs_qm_list_destroy(xfs_dqlist_t *);
59
60STATIC int xfs_qm_init_quotainos(xfs_mount_t *); 57STATIC int xfs_qm_init_quotainos(xfs_mount_t *);
61STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); 58STATIC int xfs_qm_init_quotainfo(xfs_mount_t *);
62STATIC int xfs_qm_shake(struct shrinker *, struct shrink_control *); 59STATIC int xfs_qm_shake(struct shrinker *, struct shrink_control *);
@@ -68,37 +65,9 @@ STATIC int xfs_qm_shake(struct shrinker *, struct shrink_control *);
68STATIC struct xfs_qm * 65STATIC struct xfs_qm *
69xfs_Gqm_init(void) 66xfs_Gqm_init(void)
70{ 67{
71 xfs_dqhash_t *udqhash, *gdqhash;
72 xfs_qm_t *xqm; 68 xfs_qm_t *xqm;
73 size_t hsize;
74 uint i;
75
76 /*
77 * Initialize the dquot hash tables.
78 */
79 udqhash = kmem_zalloc_greedy(&hsize,
80 XFS_QM_HASHSIZE_LOW * sizeof(xfs_dqhash_t),
81 XFS_QM_HASHSIZE_HIGH * sizeof(xfs_dqhash_t));
82 if (!udqhash)
83 goto out;
84
85 gdqhash = kmem_zalloc_large(hsize);
86 if (!gdqhash)
87 goto out_free_udqhash;
88
89 hsize /= sizeof(xfs_dqhash_t);
90 69
91 xqm = kmem_zalloc(sizeof(xfs_qm_t), KM_SLEEP); 70 xqm = kmem_zalloc(sizeof(xfs_qm_t), KM_SLEEP);
92 xqm->qm_dqhashmask = hsize - 1;
93 xqm->qm_usr_dqhtable = udqhash;
94 xqm->qm_grp_dqhtable = gdqhash;
95 ASSERT(xqm->qm_usr_dqhtable != NULL);
96 ASSERT(xqm->qm_grp_dqhtable != NULL);
97
98 for (i = 0; i < hsize; i++) {
99 xfs_qm_list_init(&(xqm->qm_usr_dqhtable[i]), "uxdqh", i);
100 xfs_qm_list_init(&(xqm->qm_grp_dqhtable[i]), "gxdqh", i);
101 }
102 71
103 /* 72 /*
104 * dquot zone. we register our own low-memory callback. 73 * dquot zone. we register our own low-memory callback.
@@ -122,11 +91,6 @@ xfs_Gqm_init(void)
122 91
123 xqm->qm_nrefs = 0; 92 xqm->qm_nrefs = 0;
124 return xqm; 93 return xqm;
125
126 out_free_udqhash:
127 kmem_free_large(udqhash);
128 out:
129 return NULL;
130} 94}
131 95
132/* 96/*
@@ -136,22 +100,9 @@ STATIC void
136xfs_qm_destroy( 100xfs_qm_destroy(
137 struct xfs_qm *xqm) 101 struct xfs_qm *xqm)
138{ 102{
139 int hsize, i;
140
141 ASSERT(xqm != NULL); 103 ASSERT(xqm != NULL);
142 ASSERT(xqm->qm_nrefs == 0); 104 ASSERT(xqm->qm_nrefs == 0);
143 105
144 hsize = xqm->qm_dqhashmask + 1;
145 for (i = 0; i < hsize; i++) {
146 xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i]));
147 xfs_qm_list_destroy(&(xqm->qm_grp_dqhtable[i]));
148 }
149 kmem_free_large(xqm->qm_usr_dqhtable);
150 kmem_free_large(xqm->qm_grp_dqhtable);
151 xqm->qm_usr_dqhtable = NULL;
152 xqm->qm_grp_dqhtable = NULL;
153 xqm->qm_dqhashmask = 0;
154
155 kmem_free(xqm); 106 kmem_free(xqm);
156} 107}
157 108
@@ -762,14 +713,6 @@ xfs_qm_dqdetach(
762} 713}
763 714
764/* 715/*
765 * The hash chains and the mplist use the same xfs_dqhash structure as
766 * their list head, but we can take the mplist qh_lock and one of the
767 * hash qh_locks at the same time without any problem as they aren't
768 * related.
769 */
770static struct lock_class_key xfs_quota_mplist_class;
771
772/*
773 * This initializes all the quota information that's kept in the 716 * This initializes all the quota information that's kept in the
774 * mount structure 717 * mount structure
775 */ 718 */
@@ -802,9 +745,12 @@ xfs_qm_init_quotainfo(
802 return error; 745 return error;
803 } 746 }
804 747
748 INIT_RADIX_TREE(&qinf->qi_uquota_tree, GFP_NOFS);
749 INIT_RADIX_TREE(&qinf->qi_gquota_tree, GFP_NOFS);
750 mutex_init(&qinf->qi_tree_lock);
751
805 INIT_LIST_HEAD(&qinf->qi_dqlist); 752 INIT_LIST_HEAD(&qinf->qi_dqlist);
806 mutex_init(&qinf->qi_dqlist_lock); 753 mutex_init(&qinf->qi_dqlist_lock);
807 lockdep_set_class(&qinf->qi_dqlist_lock, &xfs_quota_mplist_class);
808 754
809 INIT_LIST_HEAD(&qinf->qi_lru_list); 755 INIT_LIST_HEAD(&qinf->qi_lru_list);
810 qinf->qi_lru_count = 0; 756 qinf->qi_lru_count = 0;
@@ -924,30 +870,6 @@ xfs_qm_destroy_quotainfo(
924 mp->m_quotainfo = NULL; 870 mp->m_quotainfo = NULL;
925} 871}
926 872
927
928
929/* ------------------- PRIVATE STATIC FUNCTIONS ----------------------- */
930
931/* ARGSUSED */
932STATIC void
933xfs_qm_list_init(
934 xfs_dqlist_t *list,
935 char *str,
936 int n)
937{
938 mutex_init(&list->qh_lock);
939 INIT_LIST_HEAD(&list->qh_list);
940 list->qh_version = 0;
941 list->qh_nelems = 0;
942}
943
944STATIC void
945xfs_qm_list_destroy(
946 xfs_dqlist_t *list)
947{
948 mutex_destroy(&(list->qh_lock));
949}
950
951/* 873/*
952 * Create an inode and return with a reference already taken, but unlocked 874 * Create an inode and return with a reference already taken, but unlocked
953 * This is how we create quota inodes 875 * This is how we create quota inodes
@@ -1592,10 +1514,10 @@ xfs_qm_dqfree_one(
1592 struct xfs_mount *mp = dqp->q_mount; 1514 struct xfs_mount *mp = dqp->q_mount;
1593 struct xfs_quotainfo *qi = mp->m_quotainfo; 1515 struct xfs_quotainfo *qi = mp->m_quotainfo;
1594 1516
1595 mutex_lock(&dqp->q_hash->qh_lock); 1517 mutex_lock(&qi->qi_tree_lock);
1596 list_del_init(&dqp->q_hashlist); 1518 radix_tree_delete(XFS_DQUOT_TREE(qi, dqp->q_core.d_flags),
1597 dqp->q_hash->qh_version++; 1519 be32_to_cpu(dqp->q_core.d_id));
1598 mutex_unlock(&dqp->q_hash->qh_lock); 1520 mutex_unlock(&qi->qi_tree_lock);
1599 1521
1600 mutex_lock(&qi->qi_dqlist_lock); 1522 mutex_lock(&qi->qi_dqlist_lock);
1601 list_del_init(&dqp->q_mplist); 1523 list_del_init(&dqp->q_mplist);
@@ -1634,7 +1556,6 @@ xfs_qm_dqreclaim_one(
1634 return; 1556 return;
1635 } 1557 }
1636 1558
1637 ASSERT(dqp->q_hash);
1638 ASSERT(!list_empty(&dqp->q_mplist)); 1559 ASSERT(!list_empty(&dqp->q_mplist));
1639 1560
1640 /* 1561 /*