diff options
author | Matthew Wilcox <willy@linux.intel.com> | 2016-05-20 20:03:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-20 20:58:30 -0400 |
commit | 9e85d811196583126785a0405d0c879ae7a9eb2f (patch) | |
tree | 44919d0e37d0d4d2bc97d6152e313dd64a75365c | |
parent | d604c324524bf61c68182bb27db64656a78fe911 (diff) |
radix-tree: make radix_tree_descend() more useful
Now that the shift amount is stored in the node, radix_tree_descend()
can calculate offset itself from index, which removes several lines of
code from each of the tree walkers.
Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Cc: Kirill Shutemov <kirill.shutemov@linux.intel.com>
Cc: Jan Kara <jack@suse.com>
Cc: Neil Brown <neilb@suse.de>
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | lib/radix-tree.c | 78 |
1 files changed, 26 insertions, 52 deletions
diff --git a/lib/radix-tree.c b/lib/radix-tree.c index c7114d233b38..8b7d8459bb9d 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c | |||
@@ -94,9 +94,10 @@ static inline unsigned long get_slot_offset(struct radix_tree_node *parent, | |||
94 | return slot - parent->slots; | 94 | return slot - parent->slots; |
95 | } | 95 | } |
96 | 96 | ||
97 | static unsigned radix_tree_descend(struct radix_tree_node *parent, | 97 | static unsigned int radix_tree_descend(struct radix_tree_node *parent, |
98 | struct radix_tree_node **nodep, unsigned offset) | 98 | struct radix_tree_node **nodep, unsigned long index) |
99 | { | 99 | { |
100 | unsigned int offset = (index >> parent->shift) & RADIX_TREE_MAP_MASK; | ||
100 | void **entry = rcu_dereference_raw(parent->slots[offset]); | 101 | void **entry = rcu_dereference_raw(parent->slots[offset]); |
101 | 102 | ||
102 | #ifdef CONFIG_RADIX_TREE_MULTIORDER | 103 | #ifdef CONFIG_RADIX_TREE_MULTIORDER |
@@ -536,8 +537,7 @@ int __radix_tree_create(struct radix_tree_root *root, unsigned long index, | |||
536 | 537 | ||
537 | /* Go a level down */ | 538 | /* Go a level down */ |
538 | node = entry_to_node(child); | 539 | node = entry_to_node(child); |
539 | offset = (index >> shift) & RADIX_TREE_MAP_MASK; | 540 | offset = radix_tree_descend(node, &child, index); |
540 | offset = radix_tree_descend(node, &child, offset); | ||
541 | slot = &node->slots[offset]; | 541 | slot = &node->slots[offset]; |
542 | } | 542 | } |
543 | 543 | ||
@@ -625,13 +625,12 @@ void *__radix_tree_lookup(struct radix_tree_root *root, unsigned long index, | |||
625 | { | 625 | { |
626 | struct radix_tree_node *node, *parent; | 626 | struct radix_tree_node *node, *parent; |
627 | unsigned long maxindex; | 627 | unsigned long maxindex; |
628 | unsigned int shift; | ||
629 | void **slot; | 628 | void **slot; |
630 | 629 | ||
631 | restart: | 630 | restart: |
632 | parent = NULL; | 631 | parent = NULL; |
633 | slot = (void **)&root->rnode; | 632 | slot = (void **)&root->rnode; |
634 | shift = radix_tree_load_root(root, &node, &maxindex); | 633 | radix_tree_load_root(root, &node, &maxindex); |
635 | if (index > maxindex) | 634 | if (index > maxindex) |
636 | return NULL; | 635 | return NULL; |
637 | 636 | ||
@@ -641,9 +640,7 @@ void *__radix_tree_lookup(struct radix_tree_root *root, unsigned long index, | |||
641 | if (node == RADIX_TREE_RETRY) | 640 | if (node == RADIX_TREE_RETRY) |
642 | goto restart; | 641 | goto restart; |
643 | parent = entry_to_node(node); | 642 | parent = entry_to_node(node); |
644 | shift -= RADIX_TREE_MAP_SHIFT; | 643 | offset = radix_tree_descend(parent, &node, index); |
645 | offset = (index >> shift) & RADIX_TREE_MAP_MASK; | ||
646 | offset = radix_tree_descend(parent, &node, offset); | ||
647 | slot = parent->slots + offset; | 644 | slot = parent->slots + offset; |
648 | } | 645 | } |
649 | 646 | ||
@@ -713,19 +710,15 @@ void *radix_tree_tag_set(struct radix_tree_root *root, | |||
713 | { | 710 | { |
714 | struct radix_tree_node *node, *parent; | 711 | struct radix_tree_node *node, *parent; |
715 | unsigned long maxindex; | 712 | unsigned long maxindex; |
716 | unsigned int shift; | ||
717 | 713 | ||
718 | shift = radix_tree_load_root(root, &node, &maxindex); | 714 | radix_tree_load_root(root, &node, &maxindex); |
719 | BUG_ON(index > maxindex); | 715 | BUG_ON(index > maxindex); |
720 | 716 | ||
721 | while (radix_tree_is_internal_node(node)) { | 717 | while (radix_tree_is_internal_node(node)) { |
722 | unsigned offset; | 718 | unsigned offset; |
723 | 719 | ||
724 | shift -= RADIX_TREE_MAP_SHIFT; | ||
725 | offset = (index >> shift) & RADIX_TREE_MAP_MASK; | ||
726 | |||
727 | parent = entry_to_node(node); | 720 | parent = entry_to_node(node); |
728 | offset = radix_tree_descend(parent, &node, offset); | 721 | offset = radix_tree_descend(parent, &node, index); |
729 | BUG_ON(!node); | 722 | BUG_ON(!node); |
730 | 723 | ||
731 | if (!tag_get(parent, tag, offset)) | 724 | if (!tag_get(parent, tag, offset)) |
@@ -779,21 +772,17 @@ void *radix_tree_tag_clear(struct radix_tree_root *root, | |||
779 | { | 772 | { |
780 | struct radix_tree_node *node, *parent; | 773 | struct radix_tree_node *node, *parent; |
781 | unsigned long maxindex; | 774 | unsigned long maxindex; |
782 | unsigned int shift; | ||
783 | int uninitialized_var(offset); | 775 | int uninitialized_var(offset); |
784 | 776 | ||
785 | shift = radix_tree_load_root(root, &node, &maxindex); | 777 | radix_tree_load_root(root, &node, &maxindex); |
786 | if (index > maxindex) | 778 | if (index > maxindex) |
787 | return NULL; | 779 | return NULL; |
788 | 780 | ||
789 | parent = NULL; | 781 | parent = NULL; |
790 | 782 | ||
791 | while (radix_tree_is_internal_node(node)) { | 783 | while (radix_tree_is_internal_node(node)) { |
792 | shift -= RADIX_TREE_MAP_SHIFT; | ||
793 | offset = (index >> shift) & RADIX_TREE_MAP_MASK; | ||
794 | |||
795 | parent = entry_to_node(node); | 784 | parent = entry_to_node(node); |
796 | offset = radix_tree_descend(parent, &node, offset); | 785 | offset = radix_tree_descend(parent, &node, index); |
797 | } | 786 | } |
798 | 787 | ||
799 | if (node) | 788 | if (node) |
@@ -823,25 +812,21 @@ int radix_tree_tag_get(struct radix_tree_root *root, | |||
823 | { | 812 | { |
824 | struct radix_tree_node *node, *parent; | 813 | struct radix_tree_node *node, *parent; |
825 | unsigned long maxindex; | 814 | unsigned long maxindex; |
826 | unsigned int shift; | ||
827 | 815 | ||
828 | if (!root_tag_get(root, tag)) | 816 | if (!root_tag_get(root, tag)) |
829 | return 0; | 817 | return 0; |
830 | 818 | ||
831 | shift = radix_tree_load_root(root, &node, &maxindex); | 819 | radix_tree_load_root(root, &node, &maxindex); |
832 | if (index > maxindex) | 820 | if (index > maxindex) |
833 | return 0; | 821 | return 0; |
834 | if (node == NULL) | 822 | if (node == NULL) |
835 | return 0; | 823 | return 0; |
836 | 824 | ||
837 | while (radix_tree_is_internal_node(node)) { | 825 | while (radix_tree_is_internal_node(node)) { |
838 | int offset; | 826 | unsigned offset; |
839 | |||
840 | shift -= RADIX_TREE_MAP_SHIFT; | ||
841 | offset = (index >> shift) & RADIX_TREE_MAP_MASK; | ||
842 | 827 | ||
843 | parent = entry_to_node(node); | 828 | parent = entry_to_node(node); |
844 | offset = radix_tree_descend(parent, &node, offset); | 829 | offset = radix_tree_descend(parent, &node, index); |
845 | 830 | ||
846 | if (!node) | 831 | if (!node) |
847 | return 0; | 832 | return 0; |
@@ -874,7 +859,7 @@ static inline void __set_iter_shift(struct radix_tree_iter *iter, | |||
874 | void **radix_tree_next_chunk(struct radix_tree_root *root, | 859 | void **radix_tree_next_chunk(struct radix_tree_root *root, |
875 | struct radix_tree_iter *iter, unsigned flags) | 860 | struct radix_tree_iter *iter, unsigned flags) |
876 | { | 861 | { |
877 | unsigned shift, tag = flags & RADIX_TREE_ITER_TAG_MASK; | 862 | unsigned tag = flags & RADIX_TREE_ITER_TAG_MASK; |
878 | struct radix_tree_node *node, *child; | 863 | struct radix_tree_node *node, *child; |
879 | unsigned long index, offset, maxindex; | 864 | unsigned long index, offset, maxindex; |
880 | 865 | ||
@@ -895,7 +880,7 @@ void **radix_tree_next_chunk(struct radix_tree_root *root, | |||
895 | return NULL; | 880 | return NULL; |
896 | 881 | ||
897 | restart: | 882 | restart: |
898 | shift = radix_tree_load_root(root, &child, &maxindex); | 883 | radix_tree_load_root(root, &child, &maxindex); |
899 | if (index > maxindex) | 884 | if (index > maxindex) |
900 | return NULL; | 885 | return NULL; |
901 | if (!child) | 886 | if (!child) |
@@ -912,9 +897,7 @@ void **radix_tree_next_chunk(struct radix_tree_root *root, | |||
912 | 897 | ||
913 | do { | 898 | do { |
914 | node = entry_to_node(child); | 899 | node = entry_to_node(child); |
915 | shift -= RADIX_TREE_MAP_SHIFT; | 900 | offset = radix_tree_descend(node, &child, index); |
916 | offset = (index >> shift) & RADIX_TREE_MAP_MASK; | ||
917 | offset = radix_tree_descend(node, &child, offset); | ||
918 | 901 | ||
919 | if ((flags & RADIX_TREE_ITER_TAGGED) ? | 902 | if ((flags & RADIX_TREE_ITER_TAGGED) ? |
920 | !tag_get(node, tag, offset) : !child) { | 903 | !tag_get(node, tag, offset) : !child) { |
@@ -936,7 +919,7 @@ void **radix_tree_next_chunk(struct radix_tree_root *root, | |||
936 | break; | 919 | break; |
937 | } | 920 | } |
938 | index &= ~node_maxindex(node); | 921 | index &= ~node_maxindex(node); |
939 | index += offset << shift; | 922 | index += offset << node->shift; |
940 | /* Overflow after ~0UL */ | 923 | /* Overflow after ~0UL */ |
941 | if (!index) | 924 | if (!index) |
942 | return NULL; | 925 | return NULL; |
@@ -952,7 +935,7 @@ void **radix_tree_next_chunk(struct radix_tree_root *root, | |||
952 | /* Update the iterator state */ | 935 | /* Update the iterator state */ |
953 | iter->index = (index &~ node_maxindex(node)) | (offset << node->shift); | 936 | iter->index = (index &~ node_maxindex(node)) | (offset << node->shift); |
954 | iter->next_index = (index | node_maxindex(node)) + 1; | 937 | iter->next_index = (index | node_maxindex(node)) + 1; |
955 | __set_iter_shift(iter, shift); | 938 | __set_iter_shift(iter, node->shift); |
956 | 939 | ||
957 | /* Construct iter->tags bit-mask from node->tags[tag] array */ | 940 | /* Construct iter->tags bit-mask from node->tags[tag] array */ |
958 | if (flags & RADIX_TREE_ITER_TAGGED) { | 941 | if (flags & RADIX_TREE_ITER_TAGGED) { |
@@ -1010,10 +993,10 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root, | |||
1010 | { | 993 | { |
1011 | struct radix_tree_node *parent, *node, *child; | 994 | struct radix_tree_node *parent, *node, *child; |
1012 | unsigned long maxindex; | 995 | unsigned long maxindex; |
1013 | unsigned int shift = radix_tree_load_root(root, &child, &maxindex); | ||
1014 | unsigned long tagged = 0; | 996 | unsigned long tagged = 0; |
1015 | unsigned long index = *first_indexp; | 997 | unsigned long index = *first_indexp; |
1016 | 998 | ||
999 | radix_tree_load_root(root, &child, &maxindex); | ||
1017 | last_index = min(last_index, maxindex); | 1000 | last_index = min(last_index, maxindex); |
1018 | if (index > last_index) | 1001 | if (index > last_index) |
1019 | return 0; | 1002 | return 0; |
@@ -1030,11 +1013,9 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root, | |||
1030 | } | 1013 | } |
1031 | 1014 | ||
1032 | node = entry_to_node(child); | 1015 | node = entry_to_node(child); |
1033 | shift -= RADIX_TREE_MAP_SHIFT; | ||
1034 | 1016 | ||
1035 | for (;;) { | 1017 | for (;;) { |
1036 | unsigned offset = (index >> shift) & RADIX_TREE_MAP_MASK; | 1018 | unsigned offset = radix_tree_descend(node, &child, index); |
1037 | offset = radix_tree_descend(node, &child, offset); | ||
1038 | if (!child) | 1019 | if (!child) |
1039 | goto next; | 1020 | goto next; |
1040 | if (!tag_get(node, iftag, offset)) | 1021 | if (!tag_get(node, iftag, offset)) |
@@ -1042,7 +1023,6 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root, | |||
1042 | /* Sibling slots never have tags set on them */ | 1023 | /* Sibling slots never have tags set on them */ |
1043 | if (radix_tree_is_internal_node(child)) { | 1024 | if (radix_tree_is_internal_node(child)) { |
1044 | node = entry_to_node(child); | 1025 | node = entry_to_node(child); |
1045 | shift -= RADIX_TREE_MAP_SHIFT; | ||
1046 | continue; | 1026 | continue; |
1047 | } | 1027 | } |
1048 | 1028 | ||
@@ -1063,12 +1043,12 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root, | |||
1063 | tag_set(parent, settag, offset); | 1043 | tag_set(parent, settag, offset); |
1064 | } | 1044 | } |
1065 | next: | 1045 | next: |
1066 | /* Go to next item at level determined by 'shift' */ | 1046 | /* Go to next entry in node */ |
1067 | index = ((index >> shift) + 1) << shift; | 1047 | index = ((index >> node->shift) + 1) << node->shift; |
1068 | /* Overflow can happen when last_index is ~0UL... */ | 1048 | /* Overflow can happen when last_index is ~0UL... */ |
1069 | if (index > last_index || !index) | 1049 | if (index > last_index || !index) |
1070 | break; | 1050 | break; |
1071 | offset = (index >> shift) & RADIX_TREE_MAP_MASK; | 1051 | offset = (index >> node->shift) & RADIX_TREE_MAP_MASK; |
1072 | while (offset == 0) { | 1052 | while (offset == 0) { |
1073 | /* | 1053 | /* |
1074 | * We've fully scanned this node. Go up. Because | 1054 | * We've fully scanned this node. Go up. Because |
@@ -1076,8 +1056,7 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root, | |||
1076 | * we do below cannot wander astray. | 1056 | * we do below cannot wander astray. |
1077 | */ | 1057 | */ |
1078 | node = node->parent; | 1058 | node = node->parent; |
1079 | shift += RADIX_TREE_MAP_SHIFT; | 1059 | offset = (index >> node->shift) & RADIX_TREE_MAP_MASK; |
1080 | offset = (index >> shift) & RADIX_TREE_MAP_MASK; | ||
1081 | } | 1060 | } |
1082 | if (is_sibling_entry(node, node->slots[offset])) | 1061 | if (is_sibling_entry(node, node->slots[offset])) |
1083 | goto next; | 1062 | goto next; |
@@ -1275,13 +1254,10 @@ struct locate_info { | |||
1275 | static unsigned long __locate(struct radix_tree_node *slot, void *item, | 1254 | static unsigned long __locate(struct radix_tree_node *slot, void *item, |
1276 | unsigned long index, struct locate_info *info) | 1255 | unsigned long index, struct locate_info *info) |
1277 | { | 1256 | { |
1278 | unsigned int shift; | ||
1279 | unsigned long i; | 1257 | unsigned long i; |
1280 | 1258 | ||
1281 | shift = slot->shift + RADIX_TREE_MAP_SHIFT; | ||
1282 | |||
1283 | do { | 1259 | do { |
1284 | shift -= RADIX_TREE_MAP_SHIFT; | 1260 | unsigned int shift = slot->shift; |
1285 | 1261 | ||
1286 | for (i = (index >> shift) & RADIX_TREE_MAP_MASK; | 1262 | for (i = (index >> shift) & RADIX_TREE_MAP_MASK; |
1287 | i < RADIX_TREE_MAP_SIZE; | 1263 | i < RADIX_TREE_MAP_SIZE; |
@@ -1304,9 +1280,7 @@ static unsigned long __locate(struct radix_tree_node *slot, void *item, | |||
1304 | slot = node; | 1280 | slot = node; |
1305 | break; | 1281 | break; |
1306 | } | 1282 | } |
1307 | if (i == RADIX_TREE_MAP_SIZE) | 1283 | } while (i < RADIX_TREE_MAP_SIZE); |
1308 | break; | ||
1309 | } while (shift); | ||
1310 | 1284 | ||
1311 | out: | 1285 | out: |
1312 | if ((index == 0) && (i == RADIX_TREE_MAP_SIZE)) | 1286 | if ((index == 0) && (i == RADIX_TREE_MAP_SIZE)) |