aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/radix-tree.c44
1 files changed, 20 insertions, 24 deletions
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 5234a95024a3..ee56562e0a2d 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -768,44 +768,40 @@ EXPORT_SYMBOL(radix_tree_tag_set);
768void *radix_tree_tag_clear(struct radix_tree_root *root, 768void *radix_tree_tag_clear(struct radix_tree_root *root,
769 unsigned long index, unsigned int tag) 769 unsigned long index, unsigned int tag)
770{ 770{
771 struct radix_tree_node *node = NULL; 771 struct radix_tree_node *node, *parent;
772 struct radix_tree_node *slot = NULL; 772 unsigned long maxindex;
773 unsigned int height, shift; 773 unsigned int shift;
774 int uninitialized_var(offset); 774 int uninitialized_var(offset);
775 775
776 height = root->height; 776 shift = radix_tree_load_root(root, &node, &maxindex);
777 if (index > radix_tree_maxindex(height)) 777 if (index > maxindex)
778 goto out; 778 return NULL;
779
780 shift = height * RADIX_TREE_MAP_SHIFT;
781 slot = root->rnode;
782 779
783 while (shift) { 780 parent = NULL;
784 if (slot == NULL)
785 goto out;
786 if (!radix_tree_is_indirect_ptr(slot))
787 break;
788 slot = indirect_to_ptr(slot);
789 781
782 while (radix_tree_is_indirect_ptr(node)) {
790 shift -= RADIX_TREE_MAP_SHIFT; 783 shift -= RADIX_TREE_MAP_SHIFT;
791 offset = (index >> shift) & RADIX_TREE_MAP_MASK; 784 offset = (index >> shift) & RADIX_TREE_MAP_MASK;
792 node = slot; 785
793 slot = slot->slots[offset]; 786 parent = indirect_to_ptr(node);
787 offset = radix_tree_descend(parent, &node, offset);
794 } 788 }
795 789
796 if (slot == NULL) 790 if (node == NULL)
797 goto out; 791 goto out;
798 792
799 while (node) { 793 index >>= shift;
800 if (!tag_get(node, tag, offset)) 794
795 while (parent) {
796 if (!tag_get(parent, tag, offset))
801 goto out; 797 goto out;
802 tag_clear(node, tag, offset); 798 tag_clear(parent, tag, offset);
803 if (any_tag_set(node, tag)) 799 if (any_tag_set(parent, tag))
804 goto out; 800 goto out;
805 801
806 index >>= RADIX_TREE_MAP_SHIFT; 802 index >>= RADIX_TREE_MAP_SHIFT;
807 offset = index & RADIX_TREE_MAP_MASK; 803 offset = index & RADIX_TREE_MAP_MASK;
808 node = node->parent; 804 parent = parent->parent;
809 } 805 }
810 806
811 /* clear the root's tag bit */ 807 /* clear the root's tag bit */
@@ -813,7 +809,7 @@ void *radix_tree_tag_clear(struct radix_tree_root *root,
813 root_tag_clear(root, tag); 809 root_tag_clear(root, tag);
814 810
815out: 811out:
816 return slot; 812 return node;
817} 813}
818EXPORT_SYMBOL(radix_tree_tag_clear); 814EXPORT_SYMBOL(radix_tree_tag_clear);
819 815