diff options
-rw-r--r-- | lib/radix-tree.c | 44 |
1 files changed, 18 insertions, 26 deletions
diff --git a/lib/radix-tree.c b/lib/radix-tree.c index ee56562e0a2d..b1ca74489bc2 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c | |||
@@ -831,45 +831,37 @@ EXPORT_SYMBOL(radix_tree_tag_clear); | |||
831 | int radix_tree_tag_get(struct radix_tree_root *root, | 831 | int radix_tree_tag_get(struct radix_tree_root *root, |
832 | unsigned long index, unsigned int tag) | 832 | unsigned long index, unsigned int tag) |
833 | { | 833 | { |
834 | unsigned int height, shift; | 834 | struct radix_tree_node *node, *parent; |
835 | struct radix_tree_node *node; | 835 | unsigned long maxindex; |
836 | unsigned int shift; | ||
836 | 837 | ||
837 | /* check the root's tag bit */ | ||
838 | if (!root_tag_get(root, tag)) | 838 | if (!root_tag_get(root, tag)) |
839 | return 0; | 839 | return 0; |
840 | 840 | ||
841 | node = rcu_dereference_raw(root->rnode); | 841 | shift = radix_tree_load_root(root, &node, &maxindex); |
842 | if (index > maxindex) | ||
843 | return 0; | ||
842 | if (node == NULL) | 844 | if (node == NULL) |
843 | return 0; | 845 | return 0; |
844 | 846 | ||
845 | if (!radix_tree_is_indirect_ptr(node)) | 847 | while (radix_tree_is_indirect_ptr(node)) { |
846 | return (index == 0); | 848 | int offset; |
847 | node = indirect_to_ptr(node); | ||
848 | |||
849 | height = node->path & RADIX_TREE_HEIGHT_MASK; | ||
850 | if (index > radix_tree_maxindex(height)) | ||
851 | return 0; | ||
852 | 849 | ||
853 | shift = (height - 1) * RADIX_TREE_MAP_SHIFT; | 850 | shift -= RADIX_TREE_MAP_SHIFT; |
851 | offset = (index >> shift) & RADIX_TREE_MAP_MASK; | ||
854 | 852 | ||
855 | for ( ; ; ) { | 853 | parent = indirect_to_ptr(node); |
856 | int offset; | 854 | offset = radix_tree_descend(parent, &node, offset); |
857 | 855 | ||
858 | if (node == NULL) | 856 | if (!node) |
859 | return 0; | 857 | return 0; |
860 | node = indirect_to_ptr(node); | 858 | if (!tag_get(parent, tag, offset)) |
861 | |||
862 | offset = (index >> shift) & RADIX_TREE_MAP_MASK; | ||
863 | if (!tag_get(node, tag, offset)) | ||
864 | return 0; | 859 | return 0; |
865 | if (height == 1) | 860 | if (node == RADIX_TREE_RETRY) |
866 | return 1; | 861 | break; |
867 | node = rcu_dereference_raw(node->slots[offset]); | ||
868 | if (!radix_tree_is_indirect_ptr(node)) | ||
869 | return 1; | ||
870 | shift -= RADIX_TREE_MAP_SHIFT; | ||
871 | height--; | ||
872 | } | 862 | } |
863 | |||
864 | return 1; | ||
873 | } | 865 | } |
874 | EXPORT_SYMBOL(radix_tree_tag_get); | 866 | EXPORT_SYMBOL(radix_tree_tag_get); |
875 | 867 | ||