summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@linux.intel.com>2016-05-20 20:03:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-20 20:58:30 -0400
commit8c1244de00ef98f73e21eecc42d84b2742fbb4f9 (patch)
tree387657f853337b8fffe77215c9254c2ccb2a2ca4 /lib
parentaf49a63e101eb62376cc1d6bd25b97eb8c691d54 (diff)
radix-tree: tidy up next_chunk
Convert radix_tree_next_chunk to use 'child' instead of 'slot' as the name of the child node. Also use node_maxindex() where it makes sense. The 'rnode' variable was unnecessary; it doesn't overlap in usage with 'node', so we can just use 'node' the whole way through the function. Improve the testcase to start the walk from every index in the carefully constructed tree, and to accept any index within the range covered by the entry. 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>
Diffstat (limited to 'lib')
-rw-r--r--lib/radix-tree.c53
1 files changed, 19 insertions, 34 deletions
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 4b4a2a20a3d1..c42867a1769a 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -876,7 +876,7 @@ void **radix_tree_next_chunk(struct radix_tree_root *root,
876 struct radix_tree_iter *iter, unsigned flags) 876 struct radix_tree_iter *iter, unsigned flags)
877{ 877{
878 unsigned shift, tag = flags & RADIX_TREE_ITER_TAG_MASK; 878 unsigned shift, tag = flags & RADIX_TREE_ITER_TAG_MASK;
879 struct radix_tree_node *rnode, *node; 879 struct radix_tree_node *node, *child;
880 unsigned long index, offset, maxindex; 880 unsigned long index, offset, maxindex;
881 881
882 if ((flags & RADIX_TREE_ITER_TAGGED) && !root_tag_get(root, tag)) 882 if ((flags & RADIX_TREE_ITER_TAGGED) && !root_tag_get(root, tag))
@@ -896,38 +896,29 @@ void **radix_tree_next_chunk(struct radix_tree_root *root,
896 return NULL; 896 return NULL;
897 897
898 restart: 898 restart:
899 shift = radix_tree_load_root(root, &rnode, &maxindex); 899 shift = radix_tree_load_root(root, &child, &maxindex);
900 if (index > maxindex) 900 if (index > maxindex)
901 return NULL; 901 return NULL;
902 if (!child)
903 return NULL;
902 904
903 if (radix_tree_is_internal_node(rnode)) { 905 if (!radix_tree_is_internal_node(child)) {
904 rnode = entry_to_node(rnode);
905 } else if (rnode) {
906 /* Single-slot tree */ 906 /* Single-slot tree */
907 iter->index = index; 907 iter->index = index;
908 iter->next_index = maxindex + 1; 908 iter->next_index = maxindex + 1;
909 iter->tags = 1; 909 iter->tags = 1;
910 __set_iter_shift(iter, shift); 910 __set_iter_shift(iter, 0);
911 return (void **)&root->rnode; 911 return (void **)&root->rnode;
912 } else 912 }
913 return NULL;
914
915 shift -= RADIX_TREE_MAP_SHIFT;
916 offset = index >> shift;
917
918 node = rnode;
919 while (1) {
920 struct radix_tree_node *slot;
921 unsigned new_off = radix_tree_descend(node, &slot, offset);
922 913
923 if (new_off < offset) { 914 do {
924 offset = new_off; 915 node = entry_to_node(child);
925 index &= ~((RADIX_TREE_MAP_SIZE << shift) - 1); 916 shift -= RADIX_TREE_MAP_SHIFT;
926 index |= offset << shift; 917 offset = (index >> shift) & RADIX_TREE_MAP_MASK;
927 } 918 offset = radix_tree_descend(node, &child, offset);
928 919
929 if ((flags & RADIX_TREE_ITER_TAGGED) ? 920 if ((flags & RADIX_TREE_ITER_TAGGED) ?
930 !tag_get(node, tag, offset) : !slot) { 921 !tag_get(node, tag, offset) : !child) {
931 /* Hole detected */ 922 /* Hole detected */
932 if (flags & RADIX_TREE_ITER_CONTIG) 923 if (flags & RADIX_TREE_ITER_CONTIG)
933 return NULL; 924 return NULL;
@@ -945,29 +936,23 @@ void **radix_tree_next_chunk(struct radix_tree_root *root,
945 if (slot) 936 if (slot)
946 break; 937 break;
947 } 938 }
948 index &= ~((RADIX_TREE_MAP_SIZE << shift) - 1); 939 index &= ~node_maxindex(node);
949 index += offset << shift; 940 index += offset << shift;
950 /* Overflow after ~0UL */ 941 /* Overflow after ~0UL */
951 if (!index) 942 if (!index)
952 return NULL; 943 return NULL;
953 if (offset == RADIX_TREE_MAP_SIZE) 944 if (offset == RADIX_TREE_MAP_SIZE)
954 goto restart; 945 goto restart;
955 slot = rcu_dereference_raw(node->slots[offset]); 946 child = rcu_dereference_raw(node->slots[offset]);
956 } 947 }
957 948
958 if ((slot == NULL) || (slot == RADIX_TREE_RETRY)) 949 if ((child == NULL) || (child == RADIX_TREE_RETRY))
959 goto restart; 950 goto restart;
960 if (!radix_tree_is_internal_node(slot)) 951 } while (radix_tree_is_internal_node(child));
961 break;
962
963 node = entry_to_node(slot);
964 shift -= RADIX_TREE_MAP_SHIFT;
965 offset = (index >> shift) & RADIX_TREE_MAP_MASK;
966 }
967 952
968 /* Update the iterator state */ 953 /* Update the iterator state */
969 iter->index = index & ~((1 << shift) - 1); 954 iter->index = (index &~ node_maxindex(node)) | (offset << node->shift);
970 iter->next_index = (index | ((RADIX_TREE_MAP_SIZE << shift) - 1)) + 1; 955 iter->next_index = (index | node_maxindex(node)) + 1;
971 __set_iter_shift(iter, shift); 956 __set_iter_shift(iter, shift);
972 957
973 /* Construct iter->tags bit-mask from node->tags[tag] array */ 958 /* Construct iter->tags bit-mask from node->tags[tag] array */