aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
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
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')
-rw-r--r--fs/xfs/xfs_dquot.c188
-rw-r--r--fs/xfs/xfs_dquot.h12
-rw-r--r--fs/xfs/xfs_qm.c95
-rw-r--r--fs/xfs/xfs_qm.h19
-rw-r--r--fs/xfs/xfs_quota_priv.h11
-rw-r--r--fs/xfs/xfs_trace.h4
6 files changed, 66 insertions, 263 deletions
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index fec1a3d78e9f..49456e555cfa 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -43,7 +43,7 @@
43 * Lock order: 43 * Lock order:
44 * 44 *
45 * ip->i_lock 45 * ip->i_lock
46 * qh->qh_lock 46 * qi->qi_tree_lock
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)
@@ -602,60 +602,6 @@ error0:
602} 602}
603 603
604/* 604/*
605 * Lookup a dquot in the incore dquot hashtable. We keep two separate
606 * hashtables for user and group dquots; and, these are global tables
607 * inside the XQM, not per-filesystem tables.
608 * The hash chain must be locked by caller, and it is left locked
609 * on return. Returning dquot is locked.
610 */
611STATIC int
612xfs_qm_dqlookup(
613 xfs_mount_t *mp,
614 xfs_dqid_t id,
615 xfs_dqhash_t *qh,
616 xfs_dquot_t **O_dqpp)
617{
618 xfs_dquot_t *dqp;
619
620 ASSERT(mutex_is_locked(&qh->qh_lock));
621
622 /*
623 * Traverse the hashchain looking for a match
624 */
625 list_for_each_entry(dqp, &qh->qh_list, q_hashlist) {
626 /*
627 * We already have the hashlock. We don't need the
628 * dqlock to look at the id field of the dquot, since the
629 * id can't be modified without the hashlock anyway.
630 */
631 if (be32_to_cpu(dqp->q_core.d_id) != id || dqp->q_mount != mp)
632 continue;
633
634 trace_xfs_dqlookup_found(dqp);
635
636 xfs_dqlock(dqp);
637 if (dqp->dq_flags & XFS_DQ_FREEING) {
638 *O_dqpp = NULL;
639 xfs_dqunlock(dqp);
640 return -1;
641 }
642
643 dqp->q_nrefs++;
644
645 /*
646 * move the dquot to the front of the hashchain
647 */
648 list_move(&dqp->q_hashlist, &qh->qh_list);
649 trace_xfs_dqlookup_done(dqp);
650 *O_dqpp = dqp;
651 return 0;
652 }
653
654 *O_dqpp = NULL;
655 return 1;
656}
657
658/*
659 * Given the file system, inode OR id, and type (UDQUOT/GDQUOT), return a 605 * Given the file system, inode OR id, and type (UDQUOT/GDQUOT), return a
660 * a locked dquot, doing an allocation (if requested) as needed. 606 * a locked dquot, doing an allocation (if requested) as needed.
661 * When both an inode and an id are given, the inode's id takes precedence. 607 * When both an inode and an id are given, the inode's id takes precedence.
@@ -672,10 +618,10 @@ xfs_qm_dqget(
672 uint flags, /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */ 618 uint flags, /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */
673 xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */ 619 xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */
674{ 620{
675 xfs_dquot_t *dqp, *dqp1; 621 struct xfs_quotainfo *qi = mp->m_quotainfo;
676 xfs_dqhash_t *h; 622 struct radix_tree_root *tree = XFS_DQUOT_TREE(qi, type);
677 uint version; 623 struct xfs_dquot *dqp;
678 int error; 624 int error;
679 625
680 ASSERT(XFS_IS_QUOTA_RUNNING(mp)); 626 ASSERT(XFS_IS_QUOTA_RUNNING(mp));
681 if ((! XFS_IS_UQUOTA_ON(mp) && type == XFS_DQ_USER) || 627 if ((! XFS_IS_UQUOTA_ON(mp) && type == XFS_DQ_USER) ||
@@ -683,7 +629,6 @@ xfs_qm_dqget(
683 (! XFS_IS_GQUOTA_ON(mp) && type == XFS_DQ_GROUP)) { 629 (! XFS_IS_GQUOTA_ON(mp) && type == XFS_DQ_GROUP)) {
684 return (ESRCH); 630 return (ESRCH);
685 } 631 }
686 h = XFS_DQ_HASH(mp, id, type);
687 632
688#ifdef DEBUG 633#ifdef DEBUG
689 if (xfs_do_dqerror) { 634 if (xfs_do_dqerror) {
@@ -704,34 +649,28 @@ xfs_qm_dqget(
704#endif 649#endif
705 650
706restart: 651restart:
707 mutex_lock(&h->qh_lock); 652 mutex_lock(&qi->qi_tree_lock);
653 dqp = radix_tree_lookup(tree, id);
654 if (dqp) {
655 xfs_dqlock(dqp);
656 if (dqp->dq_flags & XFS_DQ_FREEING) {
657 xfs_dqunlock(dqp);
658 mutex_unlock(&qi->qi_tree_lock);
659 trace_xfs_dqget_freeing(dqp);
660 delay(1);
661 goto restart;
662 }
708 663
709 /* 664 dqp->q_nrefs++;
710 * Look in the cache (hashtable). 665 mutex_unlock(&qi->qi_tree_lock);
711 * The chain is kept locked during lookup. 666
712 */ 667 trace_xfs_dqget_hit(dqp);
713 switch (xfs_qm_dqlookup(mp, id, h, O_dqpp)) {
714 case -1:
715 XFS_STATS_INC(xs_qm_dquot_dups);
716 mutex_unlock(&h->qh_lock);
717 delay(1);
718 goto restart;
719 case 0:
720 XFS_STATS_INC(xs_qm_dqcachehits); 668 XFS_STATS_INC(xs_qm_dqcachehits);
721 /* 669 *O_dqpp = dqp;
722 * The dquot was found, moved to the front of the chain, 670 return 0;
723 * taken off the freelist if it was on it, and locked
724 * at this point. Just unlock the hashchain and return.
725 */
726 ASSERT(*O_dqpp);
727 ASSERT(XFS_DQ_IS_LOCKED(*O_dqpp));
728 mutex_unlock(&h->qh_lock);
729 trace_xfs_dqget_hit(*O_dqpp);
730 return 0; /* success */
731 default:
732 XFS_STATS_INC(xs_qm_dqcachemisses);
733 break;
734 } 671 }
672 mutex_unlock(&qi->qi_tree_lock);
673 XFS_STATS_INC(xs_qm_dqcachemisses);
735 674
736 /* 675 /*
737 * Dquot cache miss. We don't want to keep the inode lock across 676 * Dquot cache miss. We don't want to keep the inode lock across
@@ -742,12 +681,6 @@ restart:
742 */ 681 */
743 if (ip) 682 if (ip)
744 xfs_iunlock(ip, XFS_ILOCK_EXCL); 683 xfs_iunlock(ip, XFS_ILOCK_EXCL);
745 /*
746 * Save the hashchain version stamp, and unlock the chain, so that
747 * we don't keep the lock across a disk read
748 */
749 version = h->qh_version;
750 mutex_unlock(&h->qh_lock);
751 684
752 error = xfs_qm_dqread(mp, id, type, flags, &dqp); 685 error = xfs_qm_dqread(mp, id, type, flags, &dqp);
753 686
@@ -757,15 +690,14 @@ restart:
757 if (error) 690 if (error)
758 return error; 691 return error;
759 692
760 /*
761 * Dquot lock comes after hashlock in the lock ordering
762 */
763 if (ip) { 693 if (ip) {
764 /* 694 /*
765 * A dquot could be attached to this inode by now, since 695 * A dquot could be attached to this inode by now, since
766 * we had dropped the ilock. 696 * we had dropped the ilock.
767 */ 697 */
768 if (xfs_this_quota_on(mp, type)) { 698 if (xfs_this_quota_on(mp, type)) {
699 struct xfs_dquot *dqp1;
700
769 dqp1 = xfs_inode_dquot(ip, type); 701 dqp1 = xfs_inode_dquot(ip, type);
770 if (dqp1) { 702 if (dqp1) {
771 xfs_qm_dqdestroy(dqp); 703 xfs_qm_dqdestroy(dqp);
@@ -780,51 +712,27 @@ restart:
780 } 712 }
781 } 713 }
782 714
783 /* 715 mutex_lock(&qi->qi_tree_lock);
784 * Hashlock comes after ilock in lock order 716 error = -radix_tree_insert(tree, id, dqp);
785 */ 717 if (unlikely(error)) {
786 mutex_lock(&h->qh_lock); 718 WARN_ON(error != EEXIST);
787 if (version != h->qh_version) { 719
788 xfs_dquot_t *tmpdqp;
789 /* 720 /*
790 * Now, see if somebody else put the dquot in the 721 * Duplicate found. Just throw away the new dquot and start
791 * hashtable before us. This can happen because we didn't 722 * over.
792 * keep the hashchain lock. We don't have to worry about
793 * lock order between the two dquots here since dqp isn't
794 * on any findable lists yet.
795 */ 723 */
796 switch (xfs_qm_dqlookup(mp, id, h, &tmpdqp)) { 724 mutex_unlock(&qi->qi_tree_lock);
797 case 0: 725 trace_xfs_dqget_dup(dqp);
798 case -1: 726 xfs_qm_dqdestroy(dqp);
799 /* 727 XFS_STATS_INC(xs_qm_dquot_dups);
800 * Duplicate found, either in cache or on its way out. 728 goto restart;
801 * Just throw away the new dquot and start over.
802 */
803 if (tmpdqp)
804 xfs_qm_dqput(tmpdqp);
805 mutex_unlock(&h->qh_lock);
806 xfs_qm_dqdestroy(dqp);
807 XFS_STATS_INC(xs_qm_dquot_dups);
808 goto restart;
809 default:
810 break;
811 }
812 } 729 }
813 730
814 /* 731 /*
815 * Put the dquot at the beginning of the hash-chain and mp's list
816 * LOCK ORDER: hashlock, freelistlock, mplistlock, udqlock, gdqlock ..
817 */
818 ASSERT(mutex_is_locked(&h->qh_lock));
819 dqp->q_hash = h;
820 list_add(&dqp->q_hashlist, &h->qh_list);
821 h->qh_version++;
822
823 /*
824 * Attach this dquot to this filesystem's list of all dquots, 732 * Attach this dquot to this filesystem's list of all dquots,
825 * kept inside the mount structure in m_quotainfo field 733 * kept inside the mount structure in m_quotainfo field
826 */ 734 */
827 mutex_lock(&mp->m_quotainfo->qi_dqlist_lock); 735 mutex_lock(&qi->qi_dqlist_lock);
828 736
829 /* 737 /*
830 * We return a locked dquot to the caller, with a reference taken 738 * We return a locked dquot to the caller, with a reference taken
@@ -832,10 +740,11 @@ restart:
832 xfs_dqlock(dqp); 740 xfs_dqlock(dqp);
833 dqp->q_nrefs = 1; 741 dqp->q_nrefs = 1;
834 742
835 list_add(&dqp->q_mplist, &mp->m_quotainfo->qi_dqlist); 743 list_add(&dqp->q_mplist, &qi->qi_dqlist);
836 mp->m_quotainfo->qi_dquots++; 744 qi->qi_dquots++;
837 mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock); 745 mutex_unlock(&qi->qi_dqlist_lock);
838 mutex_unlock(&h->qh_lock); 746 mutex_unlock(&qi->qi_tree_lock);
747
839 dqret: 748 dqret:
840 ASSERT((ip == NULL) || xfs_isilocked(ip, XFS_ILOCK_EXCL)); 749 ASSERT((ip == NULL) || xfs_isilocked(ip, XFS_ILOCK_EXCL));
841 trace_xfs_dqget_miss(dqp); 750 trace_xfs_dqget_miss(dqp);
@@ -1117,7 +1026,6 @@ xfs_qm_dqpurge(
1117 struct xfs_dquot *dqp) 1026 struct xfs_dquot *dqp)
1118{ 1027{
1119 struct xfs_mount *mp = dqp->q_mount; 1028 struct xfs_mount *mp = dqp->q_mount;
1120 struct xfs_dqhash *qh = dqp->q_hash;
1121 struct xfs_quotainfo *qi = mp->m_quotainfo; 1029 struct xfs_quotainfo *qi = mp->m_quotainfo;
1122 1030
1123 xfs_dqlock(dqp); 1031 xfs_dqlock(dqp);
@@ -1164,10 +1072,10 @@ xfs_qm_dqpurge(
1164 xfs_dqfunlock(dqp); 1072 xfs_dqfunlock(dqp);
1165 xfs_dqunlock(dqp); 1073 xfs_dqunlock(dqp);
1166 1074
1167 mutex_lock(&qh->qh_lock); 1075 mutex_lock(&qi->qi_tree_lock);
1168 list_del_init(&dqp->q_hashlist); 1076 radix_tree_delete(XFS_DQUOT_TREE(qi, dqp->q_core.d_flags),
1169 qh->qh_version++; 1077 be32_to_cpu(dqp->q_core.d_id));
1170 mutex_unlock(&qh->qh_lock); 1078 mutex_unlock(&qi->qi_tree_lock);
1171 1079
1172 mutex_lock(&qi->qi_dqlist_lock); 1080 mutex_lock(&qi->qi_dqlist_lock);
1173 list_del_init(&dqp->q_mplist); 1081 list_del_init(&dqp->q_mplist);
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index f291c25e5992..4061f1731271 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -29,16 +29,6 @@
29 * when quotas are off. 29 * when quotas are off.
30 */ 30 */
31 31
32/*
33 * The hash chain headers (hash buckets)
34 */
35typedef struct xfs_dqhash {
36 struct list_head qh_list;
37 struct mutex qh_lock;
38 uint qh_version; /* ever increasing version */
39 uint qh_nelems; /* number of dquots on the list */
40} xfs_dqhash_t;
41
42struct xfs_mount; 32struct xfs_mount;
43struct xfs_trans; 33struct xfs_trans;
44 34
@@ -49,8 +39,6 @@ typedef struct xfs_dquot {
49 uint dq_flags; /* various flags (XFS_DQ_*) */ 39 uint dq_flags; /* various flags (XFS_DQ_*) */
50 struct list_head q_lru; /* global free list of dquots */ 40 struct list_head q_lru; /* global free list of dquots */
51 struct list_head q_mplist; /* mount's list of dquots */ 41 struct list_head q_mplist; /* mount's list of dquots */
52 struct list_head q_hashlist; /* gloabl hash list of dquots */
53 xfs_dqhash_t *q_hash; /* the hashchain header */
54 struct xfs_mount*q_mount; /* filesystem this relates to */ 42 struct xfs_mount*q_mount; /* filesystem this relates to */
55 struct xfs_trans*q_transp; /* trans this belongs to currently */ 43 struct xfs_trans*q_transp; /* trans this belongs to currently */
56 uint q_nrefs; /* # active refs from inodes */ 44 uint q_nrefs; /* # active refs from inodes */
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 /*
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index c236bba9bfab..8f4b117823cc 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -31,12 +31,6 @@ extern kmem_zone_t *qm_dqzone;
31extern kmem_zone_t *qm_dqtrxzone; 31extern kmem_zone_t *qm_dqtrxzone;
32 32
33/* 33/*
34 * Dquot hashtable constants/threshold values.
35 */
36#define XFS_QM_HASHSIZE_LOW (PAGE_SIZE / sizeof(xfs_dqhash_t))
37#define XFS_QM_HASHSIZE_HIGH ((PAGE_SIZE * 4) / sizeof(xfs_dqhash_t))
38
39/*
40 * This defines the unit of allocation of dquots. 34 * This defines the unit of allocation of dquots.
41 * Currently, it is just one file system block, and a 4K blk contains 30 35 * Currently, it is just one file system block, and a 4K blk contains 30
42 * (136 * 30 = 4080) dquots. It's probably not worth trying to make 36 * (136 * 30 = 4080) dquots. It's probably not worth trying to make
@@ -47,15 +41,10 @@ extern kmem_zone_t *qm_dqtrxzone;
47 */ 41 */
48#define XFS_DQUOT_CLUSTER_SIZE_FSB (xfs_filblks_t)1 42#define XFS_DQUOT_CLUSTER_SIZE_FSB (xfs_filblks_t)1
49 43
50typedef xfs_dqhash_t xfs_dqlist_t;
51
52/* 44/*
53 * Quota Manager (global) structure. Lives only in core. 45 * Quota Manager (global) structure. Lives only in core.
54 */ 46 */
55typedef struct xfs_qm { 47typedef struct xfs_qm {
56 xfs_dqlist_t *qm_usr_dqhtable;/* udquot hash table */
57 xfs_dqlist_t *qm_grp_dqhtable;/* gdquot hash table */
58 uint qm_dqhashmask; /* # buckets in dq hashtab - 1 */
59 uint qm_nrefs; /* file systems with quota on */ 48 uint qm_nrefs; /* file systems with quota on */
60 kmem_zone_t *qm_dqzone; /* dquot mem-alloc zone */ 49 kmem_zone_t *qm_dqzone; /* dquot mem-alloc zone */
61 kmem_zone_t *qm_dqtrxzone; /* t_dqinfo of transactions */ 50 kmem_zone_t *qm_dqtrxzone; /* t_dqinfo of transactions */
@@ -66,6 +55,9 @@ typedef struct xfs_qm {
66 * The mount structure keeps a pointer to this. 55 * The mount structure keeps a pointer to this.
67 */ 56 */
68typedef struct xfs_quotainfo { 57typedef struct xfs_quotainfo {
58 struct radix_tree_root qi_uquota_tree;
59 struct radix_tree_root qi_gquota_tree;
60 struct mutex qi_tree_lock;
69 xfs_inode_t *qi_uquotaip; /* user quota inode */ 61 xfs_inode_t *qi_uquotaip; /* user quota inode */
70 xfs_inode_t *qi_gquotaip; /* group quota inode */ 62 xfs_inode_t *qi_gquotaip; /* group quota inode */
71 struct list_head qi_lru_list; 63 struct list_head qi_lru_list;
@@ -94,6 +86,11 @@ typedef struct xfs_quotainfo {
94 struct shrinker qi_shrinker; 86 struct shrinker qi_shrinker;
95} xfs_quotainfo_t; 87} xfs_quotainfo_t;
96 88
89#define XFS_DQUOT_TREE(qi, type) \
90 ((type & XFS_DQ_USER) ? \
91 &((qi)->qi_uquota_tree) : \
92 &((qi)->qi_gquota_tree))
93
97 94
98extern void xfs_trans_mod_dquot(xfs_trans_t *, xfs_dquot_t *, uint, long); 95extern void xfs_trans_mod_dquot(xfs_trans_t *, xfs_dquot_t *, uint, long);
99extern int xfs_trans_reserve_quota_bydquots(xfs_trans_t *, xfs_mount_t *, 96extern int xfs_trans_reserve_quota_bydquots(xfs_trans_t *, xfs_mount_t *,
diff --git a/fs/xfs/xfs_quota_priv.h b/fs/xfs/xfs_quota_priv.h
index 94a3d927d716..6d86219d93da 100644
--- a/fs/xfs/xfs_quota_priv.h
+++ b/fs/xfs/xfs_quota_priv.h
@@ -24,17 +24,6 @@
24 */ 24 */
25#define XFS_DQITER_MAP_SIZE 10 25#define XFS_DQITER_MAP_SIZE 10
26 26
27/*
28 * Hash into a bucket in the dquot hash table, based on <mp, id>.
29 */
30#define XFS_DQ_HASHVAL(mp, id) (((__psunsigned_t)(mp) + \
31 (__psunsigned_t)(id)) & \
32 (xfs_Gqm->qm_dqhashmask - 1))
33#define XFS_DQ_HASH(mp, id, type) (type == XFS_DQ_USER ? \
34 (xfs_Gqm->qm_usr_dqhtable + \
35 XFS_DQ_HASHVAL(mp, id)) : \
36 (xfs_Gqm->qm_grp_dqhtable + \
37 XFS_DQ_HASHVAL(mp, id)))
38#define XFS_IS_DQUOT_UNINITIALIZED(dqp) ( \ 27#define XFS_IS_DQUOT_UNINITIALIZED(dqp) ( \
39 !dqp->q_core.d_blk_hardlimit && \ 28 !dqp->q_core.d_blk_hardlimit && \
40 !dqp->q_core.d_blk_softlimit && \ 29 !dqp->q_core.d_blk_softlimit && \
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index ceaf6fe67e41..75eb54af4d58 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -741,10 +741,10 @@ DEFINE_DQUOT_EVENT(xfs_dqalloc);
741DEFINE_DQUOT_EVENT(xfs_dqtobp_read); 741DEFINE_DQUOT_EVENT(xfs_dqtobp_read);
742DEFINE_DQUOT_EVENT(xfs_dqread); 742DEFINE_DQUOT_EVENT(xfs_dqread);
743DEFINE_DQUOT_EVENT(xfs_dqread_fail); 743DEFINE_DQUOT_EVENT(xfs_dqread_fail);
744DEFINE_DQUOT_EVENT(xfs_dqlookup_found);
745DEFINE_DQUOT_EVENT(xfs_dqlookup_done);
746DEFINE_DQUOT_EVENT(xfs_dqget_hit); 744DEFINE_DQUOT_EVENT(xfs_dqget_hit);
747DEFINE_DQUOT_EVENT(xfs_dqget_miss); 745DEFINE_DQUOT_EVENT(xfs_dqget_miss);
746DEFINE_DQUOT_EVENT(xfs_dqget_freeing);
747DEFINE_DQUOT_EVENT(xfs_dqget_dup);
748DEFINE_DQUOT_EVENT(xfs_dqput); 748DEFINE_DQUOT_EVENT(xfs_dqput);
749DEFINE_DQUOT_EVENT(xfs_dqput_wait); 749DEFINE_DQUOT_EVENT(xfs_dqput_wait);
750DEFINE_DQUOT_EVENT(xfs_dqput_free); 750DEFINE_DQUOT_EVENT(xfs_dqput_free);