Commit 9f920f116426806bfa34c1422742e1bf7b7a2b4b
Committed by
Ben Myers
1 parent
f8739c3ce2
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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>
Showing 6 changed files with 66 additions and 263 deletions Side-by-side Diff
fs/xfs/xfs_dquot.c
... | ... | @@ -43,7 +43,7 @@ |
43 | 43 | * Lock order: |
44 | 44 | * |
45 | 45 | * ip->i_lock |
46 | - * qh->qh_lock | |
46 | + * qi->qi_tree_lock | |
47 | 47 | * qi->qi_dqlist_lock |
48 | 48 | * dquot->q_qlock (xfs_dqlock() and friends) |
49 | 49 | * dquot->q_flush (xfs_dqflock() and friends) |
... | ... | @@ -602,60 +602,6 @@ |
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 | - */ | |
611 | -STATIC int | |
612 | -xfs_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 | 605 | * Given the file system, inode OR id, and type (UDQUOT/GDQUOT), return a |
660 | 606 | * a locked dquot, doing an allocation (if requested) as needed. |
661 | 607 | * When both an inode and an id are given, the inode's id takes precedence. |
... | ... | @@ -672,10 +618,10 @@ |
672 | 618 | uint flags, /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */ |
673 | 619 | xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */ |
674 | 620 | { |
675 | - xfs_dquot_t *dqp, *dqp1; | |
676 | - xfs_dqhash_t *h; | |
677 | - uint version; | |
678 | - int error; | |
621 | + struct xfs_quotainfo *qi = mp->m_quotainfo; | |
622 | + struct radix_tree_root *tree = XFS_DQUOT_TREE(qi, type); | |
623 | + struct xfs_dquot *dqp; | |
624 | + int error; | |
679 | 625 | |
680 | 626 | ASSERT(XFS_IS_QUOTA_RUNNING(mp)); |
681 | 627 | if ((! XFS_IS_UQUOTA_ON(mp) && type == XFS_DQ_USER) || |
... | ... | @@ -683,7 +629,6 @@ |
683 | 629 | (! XFS_IS_GQUOTA_ON(mp) && type == XFS_DQ_GROUP)) { |
684 | 630 | return (ESRCH); |
685 | 631 | } |
686 | - h = XFS_DQ_HASH(mp, id, type); | |
687 | 632 | |
688 | 633 | #ifdef DEBUG |
689 | 634 | if (xfs_do_dqerror) { |
690 | 635 | |
691 | 636 | |
692 | 637 | |
... | ... | @@ -704,34 +649,28 @@ |
704 | 649 | #endif |
705 | 650 | |
706 | 651 | restart: |
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 | - /* | |
710 | - * Look in the cache (hashtable). | |
711 | - * The chain is kept locked during lookup. | |
712 | - */ | |
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: | |
664 | + dqp->q_nrefs++; | |
665 | + mutex_unlock(&qi->qi_tree_lock); | |
666 | + | |
667 | + trace_xfs_dqget_hit(dqp); | |
720 | 668 | XFS_STATS_INC(xs_qm_dqcachehits); |
721 | - /* | |
722 | - * The dquot was found, moved to the front of the chain, | |
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; | |
669 | + *O_dqpp = dqp; | |
670 | + return 0; | |
734 | 671 | } |
672 | + mutex_unlock(&qi->qi_tree_lock); | |
673 | + XFS_STATS_INC(xs_qm_dqcachemisses); | |
735 | 674 | |
736 | 675 | /* |
737 | 676 | * Dquot cache miss. We don't want to keep the inode lock across |
... | ... | @@ -742,12 +681,6 @@ |
742 | 681 | */ |
743 | 682 | if (ip) |
744 | 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 | 685 | error = xfs_qm_dqread(mp, id, type, flags, &dqp); |
753 | 686 | |
754 | 687 | |
... | ... | @@ -757,15 +690,14 @@ |
757 | 690 | if (error) |
758 | 691 | return error; |
759 | 692 | |
760 | - /* | |
761 | - * Dquot lock comes after hashlock in the lock ordering | |
762 | - */ | |
763 | 693 | if (ip) { |
764 | 694 | /* |
765 | 695 | * A dquot could be attached to this inode by now, since |
766 | 696 | * we had dropped the ilock. |
767 | 697 | */ |
768 | 698 | if (xfs_this_quota_on(mp, type)) { |
699 | + struct xfs_dquot *dqp1; | |
700 | + | |
769 | 701 | dqp1 = xfs_inode_dquot(ip, type); |
770 | 702 | if (dqp1) { |
771 | 703 | xfs_qm_dqdestroy(dqp); |
772 | 704 | |
773 | 705 | |
774 | 706 | |
775 | 707 | |
... | ... | @@ -780,51 +712,27 @@ |
780 | 712 | } |
781 | 713 | } |
782 | 714 | |
783 | - /* | |
784 | - * Hashlock comes after ilock in lock order | |
785 | - */ | |
786 | - mutex_lock(&h->qh_lock); | |
787 | - if (version != h->qh_version) { | |
788 | - xfs_dquot_t *tmpdqp; | |
715 | + mutex_lock(&qi->qi_tree_lock); | |
716 | + error = -radix_tree_insert(tree, id, dqp); | |
717 | + if (unlikely(error)) { | |
718 | + WARN_ON(error != EEXIST); | |
719 | + | |
789 | 720 | /* |
790 | - * Now, see if somebody else put the dquot in the | |
791 | - * hashtable before us. This can happen because we didn't | |
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. | |
721 | + * Duplicate found. Just throw away the new dquot and start | |
722 | + * over. | |
795 | 723 | */ |
796 | - switch (xfs_qm_dqlookup(mp, id, h, &tmpdqp)) { | |
797 | - case 0: | |
798 | - case -1: | |
799 | - /* | |
800 | - * Duplicate found, either in cache or on its way out. | |
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 | - } | |
724 | + mutex_unlock(&qi->qi_tree_lock); | |
725 | + trace_xfs_dqget_dup(dqp); | |
726 | + xfs_qm_dqdestroy(dqp); | |
727 | + XFS_STATS_INC(xs_qm_dquot_dups); | |
728 | + goto restart; | |
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 | 732 | * Attach this dquot to this filesystem's list of all dquots, |
825 | 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 | 738 | * We return a locked dquot to the caller, with a reference taken |
... | ... | @@ -832,10 +740,11 @@ |
832 | 740 | xfs_dqlock(dqp); |
833 | 741 | dqp->q_nrefs = 1; |
834 | 742 | |
835 | - list_add(&dqp->q_mplist, &mp->m_quotainfo->qi_dqlist); | |
836 | - mp->m_quotainfo->qi_dquots++; | |
837 | - mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock); | |
838 | - mutex_unlock(&h->qh_lock); | |
743 | + list_add(&dqp->q_mplist, &qi->qi_dqlist); | |
744 | + qi->qi_dquots++; | |
745 | + mutex_unlock(&qi->qi_dqlist_lock); | |
746 | + mutex_unlock(&qi->qi_tree_lock); | |
747 | + | |
839 | 748 | dqret: |
840 | 749 | ASSERT((ip == NULL) || xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
841 | 750 | trace_xfs_dqget_miss(dqp); |
... | ... | @@ -1117,7 +1026,6 @@ |
1117 | 1026 | struct xfs_dquot *dqp) |
1118 | 1027 | { |
1119 | 1028 | struct xfs_mount *mp = dqp->q_mount; |
1120 | - struct xfs_dqhash *qh = dqp->q_hash; | |
1121 | 1029 | struct xfs_quotainfo *qi = mp->m_quotainfo; |
1122 | 1030 | |
1123 | 1031 | xfs_dqlock(dqp); |
... | ... | @@ -1164,10 +1072,10 @@ |
1164 | 1072 | xfs_dqfunlock(dqp); |
1165 | 1073 | xfs_dqunlock(dqp); |
1166 | 1074 | |
1167 | - mutex_lock(&qh->qh_lock); | |
1168 | - list_del_init(&dqp->q_hashlist); | |
1169 | - qh->qh_version++; | |
1170 | - mutex_unlock(&qh->qh_lock); | |
1075 | + mutex_lock(&qi->qi_tree_lock); | |
1076 | + radix_tree_delete(XFS_DQUOT_TREE(qi, dqp->q_core.d_flags), | |
1077 | + be32_to_cpu(dqp->q_core.d_id)); | |
1078 | + mutex_unlock(&qi->qi_tree_lock); | |
1171 | 1079 | |
1172 | 1080 | mutex_lock(&qi->qi_dqlist_lock); |
1173 | 1081 | list_del_init(&dqp->q_mplist); |
fs/xfs/xfs_dquot.h
... | ... | @@ -29,16 +29,6 @@ |
29 | 29 | * when quotas are off. |
30 | 30 | */ |
31 | 31 | |
32 | -/* | |
33 | - * The hash chain headers (hash buckets) | |
34 | - */ | |
35 | -typedef 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 | - | |
42 | 32 | struct xfs_mount; |
43 | 33 | struct xfs_trans; |
44 | 34 | |
... | ... | @@ -49,8 +39,6 @@ |
49 | 39 | uint dq_flags; /* various flags (XFS_DQ_*) */ |
50 | 40 | struct list_head q_lru; /* global free list of dquots */ |
51 | 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 | 42 | struct xfs_mount*q_mount; /* filesystem this relates to */ |
55 | 43 | struct xfs_trans*q_transp; /* trans this belongs to currently */ |
56 | 44 | uint q_nrefs; /* # active refs from inodes */ |
fs/xfs/xfs_qm.c
... | ... | @@ -54,9 +54,6 @@ |
54 | 54 | kmem_zone_t *qm_dqzone; |
55 | 55 | kmem_zone_t *qm_dqtrxzone; |
56 | 56 | |
57 | -STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int); | |
58 | -STATIC void xfs_qm_list_destroy(xfs_dqlist_t *); | |
59 | - | |
60 | 57 | STATIC int xfs_qm_init_quotainos(xfs_mount_t *); |
61 | 58 | STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); |
62 | 59 | STATIC int xfs_qm_shake(struct shrinker *, struct shrink_control *); |
63 | 60 | |
64 | 61 | |
65 | 62 | |
66 | 63 | |
... | ... | @@ -68,38 +65,10 @@ |
68 | 65 | STATIC struct xfs_qm * |
69 | 66 | xfs_Gqm_init(void) |
70 | 67 | { |
71 | - xfs_dqhash_t *udqhash, *gdqhash; | |
72 | 68 | xfs_qm_t *xqm; |
73 | - size_t hsize; | |
74 | - uint i; | |
75 | 69 | |
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 | - | |
91 | 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 | 71 | |
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 | - | |
103 | 72 | /* |
104 | 73 | * dquot zone. we register our own low-memory callback. |
105 | 74 | */ |
... | ... | @@ -122,11 +91,6 @@ |
122 | 91 | |
123 | 92 | xqm->qm_nrefs = 0; |
124 | 93 | return xqm; |
125 | - | |
126 | - out_free_udqhash: | |
127 | - kmem_free_large(udqhash); | |
128 | - out: | |
129 | - return NULL; | |
130 | 94 | } |
131 | 95 | |
132 | 96 | /* |
133 | 97 | |
... | ... | @@ -136,22 +100,9 @@ |
136 | 100 | xfs_qm_destroy( |
137 | 101 | struct xfs_qm *xqm) |
138 | 102 | { |
139 | - int hsize, i; | |
140 | - | |
141 | 103 | ASSERT(xqm != NULL); |
142 | 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 | 106 | kmem_free(xqm); |
156 | 107 | } |
157 | 108 | |
... | ... | @@ -762,14 +713,6 @@ |
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 | - */ | |
770 | -static struct lock_class_key xfs_quota_mplist_class; | |
771 | - | |
772 | -/* | |
773 | 716 | * This initializes all the quota information that's kept in the |
774 | 717 | * mount structure |
775 | 718 | */ |
776 | 719 | |
... | ... | @@ -802,9 +745,12 @@ |
802 | 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 | 752 | INIT_LIST_HEAD(&qinf->qi_dqlist); |
806 | 753 | mutex_init(&qinf->qi_dqlist_lock); |
807 | - lockdep_set_class(&qinf->qi_dqlist_lock, &xfs_quota_mplist_class); | |
808 | 754 | |
809 | 755 | INIT_LIST_HEAD(&qinf->qi_lru_list); |
810 | 756 | qinf->qi_lru_count = 0; |
... | ... | @@ -924,30 +870,6 @@ |
924 | 870 | mp->m_quotainfo = NULL; |
925 | 871 | } |
926 | 872 | |
927 | - | |
928 | - | |
929 | -/* ------------------- PRIVATE STATIC FUNCTIONS ----------------------- */ | |
930 | - | |
931 | -/* ARGSUSED */ | |
932 | -STATIC void | |
933 | -xfs_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 | - | |
944 | -STATIC void | |
945 | -xfs_qm_list_destroy( | |
946 | - xfs_dqlist_t *list) | |
947 | -{ | |
948 | - mutex_destroy(&(list->qh_lock)); | |
949 | -} | |
950 | - | |
951 | 873 | /* |
952 | 874 | * Create an inode and return with a reference already taken, but unlocked |
953 | 875 | * This is how we create quota inodes |
... | ... | @@ -1592,10 +1514,10 @@ |
1592 | 1514 | struct xfs_mount *mp = dqp->q_mount; |
1593 | 1515 | struct xfs_quotainfo *qi = mp->m_quotainfo; |
1594 | 1516 | |
1595 | - mutex_lock(&dqp->q_hash->qh_lock); | |
1596 | - list_del_init(&dqp->q_hashlist); | |
1597 | - dqp->q_hash->qh_version++; | |
1598 | - mutex_unlock(&dqp->q_hash->qh_lock); | |
1517 | + mutex_lock(&qi->qi_tree_lock); | |
1518 | + radix_tree_delete(XFS_DQUOT_TREE(qi, dqp->q_core.d_flags), | |
1519 | + be32_to_cpu(dqp->q_core.d_id)); | |
1520 | + mutex_unlock(&qi->qi_tree_lock); | |
1599 | 1521 | |
1600 | 1522 | mutex_lock(&qi->qi_dqlist_lock); |
1601 | 1523 | list_del_init(&dqp->q_mplist); |
... | ... | @@ -1634,7 +1556,6 @@ |
1634 | 1556 | return; |
1635 | 1557 | } |
1636 | 1558 | |
1637 | - ASSERT(dqp->q_hash); | |
1638 | 1559 | ASSERT(!list_empty(&dqp->q_mplist)); |
1639 | 1560 | |
1640 | 1561 | /* |
fs/xfs/xfs_qm.h
... | ... | @@ -31,12 +31,6 @@ |
31 | 31 | extern 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 | 34 | * This defines the unit of allocation of dquots. |
41 | 35 | * Currently, it is just one file system block, and a 4K blk contains 30 |
42 | 36 | * (136 * 30 = 4080) dquots. It's probably not worth trying to make |
43 | 37 | |
... | ... | @@ -47,15 +41,10 @@ |
47 | 41 | */ |
48 | 42 | #define XFS_DQUOT_CLUSTER_SIZE_FSB (xfs_filblks_t)1 |
49 | 43 | |
50 | -typedef xfs_dqhash_t xfs_dqlist_t; | |
51 | - | |
52 | 44 | /* |
53 | 45 | * Quota Manager (global) structure. Lives only in core. |
54 | 46 | */ |
55 | 47 | typedef 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 | 48 | uint qm_nrefs; /* file systems with quota on */ |
60 | 49 | kmem_zone_t *qm_dqzone; /* dquot mem-alloc zone */ |
61 | 50 | kmem_zone_t *qm_dqtrxzone; /* t_dqinfo of transactions */ |
... | ... | @@ -66,6 +55,9 @@ |
66 | 55 | * The mount structure keeps a pointer to this. |
67 | 56 | */ |
68 | 57 | typedef 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 | 61 | xfs_inode_t *qi_uquotaip; /* user quota inode */ |
70 | 62 | xfs_inode_t *qi_gquotaip; /* group quota inode */ |
71 | 63 | struct list_head qi_lru_list; |
... | ... | @@ -93,6 +85,11 @@ |
93 | 85 | xfs_qcnt_t qi_rtbsoftlimit;/* default realtime blk soft limit */ |
94 | 86 | struct shrinker qi_shrinker; |
95 | 87 | } xfs_quotainfo_t; |
88 | + | |
89 | +#define XFS_DQUOT_TREE(qi, type) \ | |
90 | + ((type & XFS_DQ_USER) ? \ | |
91 | + &((qi)->qi_uquota_tree) : \ | |
92 | + &((qi)->qi_gquota_tree)) | |
96 | 93 | |
97 | 94 | |
98 | 95 | extern void xfs_trans_mod_dquot(xfs_trans_t *, xfs_dquot_t *, uint, long); |
fs/xfs/xfs_quota_priv.h
... | ... | @@ -24,17 +24,6 @@ |
24 | 24 | */ |
25 | 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 | 27 | #define XFS_IS_DQUOT_UNINITIALIZED(dqp) ( \ |
39 | 28 | !dqp->q_core.d_blk_hardlimit && \ |
40 | 29 | !dqp->q_core.d_blk_softlimit && \ |
fs/xfs/xfs_trace.h
... | ... | @@ -741,10 +741,10 @@ |
741 | 741 | DEFINE_DQUOT_EVENT(xfs_dqtobp_read); |
742 | 742 | DEFINE_DQUOT_EVENT(xfs_dqread); |
743 | 743 | DEFINE_DQUOT_EVENT(xfs_dqread_fail); |
744 | -DEFINE_DQUOT_EVENT(xfs_dqlookup_found); | |
745 | -DEFINE_DQUOT_EVENT(xfs_dqlookup_done); | |
746 | 744 | DEFINE_DQUOT_EVENT(xfs_dqget_hit); |
747 | 745 | DEFINE_DQUOT_EVENT(xfs_dqget_miss); |
746 | +DEFINE_DQUOT_EVENT(xfs_dqget_freeing); | |
747 | +DEFINE_DQUOT_EVENT(xfs_dqget_dup); | |
748 | 748 | DEFINE_DQUOT_EVENT(xfs_dqput); |
749 | 749 | DEFINE_DQUOT_EVENT(xfs_dqput_wait); |
750 | 750 | DEFINE_DQUOT_EVENT(xfs_dqput_free); |