Merge tag 'irqchip-core-4.8' of git://git.infradead.org/users/jcooper/linux into...
[cascardo/linux.git] / lib / radix-tree.c
index 58f79fe..8b7d845 100644 (file)
@@ -66,12 +66,12 @@ struct radix_tree_preload {
 };
 static DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads) = { 0, };
 
-static inline void *ptr_to_indirect(void *ptr)
+static inline void *node_to_entry(void *ptr)
 {
-       return (void *)((unsigned long)ptr | RADIX_TREE_INDIRECT_PTR);
+       return (void *)((unsigned long)ptr | RADIX_TREE_INTERNAL_NODE);
 }
 
-#define RADIX_TREE_RETRY       ptr_to_indirect(NULL)
+#define RADIX_TREE_RETRY       node_to_entry(NULL)
 
 #ifdef CONFIG_RADIX_TREE_MULTIORDER
 /* Sibling slots point directly to another slot in the same node */
@@ -94,13 +94,14 @@ static inline unsigned long get_slot_offset(struct radix_tree_node *parent,
        return slot - parent->slots;
 }
 
-static unsigned radix_tree_descend(struct radix_tree_node *parent,
-                               struct radix_tree_node **nodep, unsigned offset)
+static unsigned int radix_tree_descend(struct radix_tree_node *parent,
+                       struct radix_tree_node **nodep, unsigned long index)
 {
+       unsigned int offset = (index >> parent->shift) & RADIX_TREE_MAP_MASK;
        void **entry = rcu_dereference_raw(parent->slots[offset]);
 
 #ifdef CONFIG_RADIX_TREE_MULTIORDER
-       if (radix_tree_is_indirect_ptr(entry)) {
+       if (radix_tree_is_internal_node(entry)) {
                unsigned long siboff = get_slot_offset(parent, entry);
                if (siboff < RADIX_TREE_MAP_SIZE) {
                        offset = siboff;
@@ -230,13 +231,13 @@ static void dump_node(struct radix_tree_node *node, unsigned long index)
                if (is_sibling_entry(node, entry)) {
                        pr_debug("radix sblng %p offset %ld val %p indices %ld-%ld\n",
                                        entry, i,
-                                       *(void **)indirect_to_ptr(entry),
+                                       *(void **)entry_to_node(entry),
                                        first, last);
-               } else if (!radix_tree_is_indirect_ptr(entry)) {
+               } else if (!radix_tree_is_internal_node(entry)) {
                        pr_debug("radix entry %p offset %ld indices %ld-%ld\n",
                                        entry, i, first, last);
                } else {
-                       dump_node(indirect_to_ptr(entry), first);
+                       dump_node(entry_to_node(entry), first);
                }
        }
 }
@@ -247,9 +248,9 @@ static void radix_tree_dump(struct radix_tree_root *root)
        pr_debug("radix root: %p rnode %p tags %x\n",
                        root, root->rnode,
                        root->gfp_mask >> __GFP_BITS_SHIFT);
-       if (!radix_tree_is_indirect_ptr(root->rnode))
+       if (!radix_tree_is_internal_node(root->rnode))
                return;
-       dump_node(indirect_to_ptr(root->rnode), 0);
+       dump_node(entry_to_node(root->rnode), 0);
 }
 #endif
 
@@ -302,7 +303,7 @@ radix_tree_node_alloc(struct radix_tree_root *root)
        ret = kmem_cache_alloc(radix_tree_node_cachep,
                               gfp_mask | __GFP_ACCOUNT);
 out:
-       BUG_ON(radix_tree_is_indirect_ptr(ret));
+       BUG_ON(radix_tree_is_internal_node(ret));
        return ret;
 }
 
@@ -421,8 +422,8 @@ static unsigned radix_tree_load_root(struct radix_tree_root *root,
 
        *nodep = node;
 
-       if (likely(radix_tree_is_indirect_ptr(node))) {
-               node = indirect_to_ptr(node);
+       if (likely(radix_tree_is_internal_node(node))) {
+               node = entry_to_node(node);
                *maxindex = node_maxindex(node);
                return node->shift + RADIX_TREE_MAP_SHIFT;
        }
@@ -467,16 +468,12 @@ static int radix_tree_extend(struct radix_tree_root *root,
                node->offset = 0;
                node->count = 1;
                node->parent = NULL;
-               if (radix_tree_is_indirect_ptr(slot)) {
-                       slot = indirect_to_ptr(slot);
-                       slot->parent = node;
-                       slot = ptr_to_indirect(slot);
-               }
+               if (radix_tree_is_internal_node(slot))
+                       entry_to_node(slot)->parent = node;
                node->slots[0] = slot;
-               node = ptr_to_indirect(node);
-               rcu_assign_pointer(root->rnode, node);
+               slot = node_to_entry(node);
+               rcu_assign_pointer(root->rnode, slot);
                shift += RADIX_TREE_MAP_SHIFT;
-               slot = node;
        } while (shift <= maxshift);
 out:
        return maxshift + RADIX_TREE_MAP_SHIFT;
@@ -503,12 +500,13 @@ int __radix_tree_create(struct radix_tree_root *root, unsigned long index,
                        unsigned order, struct radix_tree_node **nodep,
                        void ***slotp)
 {
-       struct radix_tree_node *node = NULL, *slot;
+       struct radix_tree_node *node = NULL, *child;
+       void **slot = (void **)&root->rnode;
        unsigned long maxindex;
-       unsigned int shift, offset;
+       unsigned int shift, offset = 0;
        unsigned long max = index | ((1UL << order) - 1);
 
-       shift = radix_tree_load_root(root, &slot, &maxindex);
+       shift = radix_tree_load_root(root, &child, &maxindex);
 
        /* Make sure the tree is high enough.  */
        if (max > maxindex) {
@@ -516,51 +514,47 @@ int __radix_tree_create(struct radix_tree_root *root, unsigned long index,
                if (error < 0)
                        return error;
                shift = error;
-               slot = root->rnode;
+               child = root->rnode;
                if (order == shift)
                        shift += RADIX_TREE_MAP_SHIFT;
        }
 
-       offset = 0;                     /* uninitialised var warning */
        while (shift > order) {
                shift -= RADIX_TREE_MAP_SHIFT;
-               if (slot == NULL) {
+               if (child == NULL) {
                        /* Have to add a child node.  */
-                       slot = radix_tree_node_alloc(root);
-                       if (!slot)
+                       child = radix_tree_node_alloc(root);
+                       if (!child)
                                return -ENOMEM;
-                       slot->shift = shift;
-                       slot->offset = offset;
-                       slot->parent = node;
-                       if (node) {
-                               rcu_assign_pointer(node->slots[offset],
-                                                       ptr_to_indirect(slot));
+                       child->shift = shift;
+                       child->offset = offset;
+                       child->parent = node;
+                       rcu_assign_pointer(*slot, node_to_entry(child));
+                       if (node)
                                node->count++;
-                       } else
-                               rcu_assign_pointer(root->rnode,
-                                                       ptr_to_indirect(slot));
-               } else if (!radix_tree_is_indirect_ptr(slot))
+               } else if (!radix_tree_is_internal_node(child))
                        break;
 
                /* Go a level down */
-               node = indirect_to_ptr(slot);
-               offset = (index >> shift) & RADIX_TREE_MAP_MASK;
-               offset = radix_tree_descend(node, &slot, offset);
+               node = entry_to_node(child);
+               offset = radix_tree_descend(node, &child, index);
+               slot = &node->slots[offset];
        }
 
 #ifdef CONFIG_RADIX_TREE_MULTIORDER
        /* Insert pointers to the canonical entry */
        if (order > shift) {
-               int i, n = 1 << (order - shift);
+               unsigned i, n = 1 << (order - shift);
                offset = offset & ~(n - 1);
-               slot = ptr_to_indirect(&node->slots[offset]);
+               slot = &node->slots[offset];
+               child = node_to_entry(slot);
                for (i = 0; i < n; i++) {
-                       if (node->slots[offset + i])
+                       if (slot[i])
                                return -EEXIST;
                }
 
                for (i = 1; i < n; i++) {
-                       rcu_assign_pointer(node->slots[offset + i], slot);
+                       rcu_assign_pointer(slot[i], child);
                        node->count++;
                }
        }
@@ -569,7 +563,7 @@ int __radix_tree_create(struct radix_tree_root *root, unsigned long index,
        if (nodep)
                *nodep = node;
        if (slotp)
-               *slotp = node ? node->slots + offset : (void **)&root->rnode;
+               *slotp = slot;
        return 0;
 }
 
@@ -589,7 +583,7 @@ int __radix_tree_insert(struct radix_tree_root *root, unsigned long index,
        void **slot;
        int error;
 
-       BUG_ON(radix_tree_is_indirect_ptr(item));
+       BUG_ON(radix_tree_is_internal_node(item));
 
        error = __radix_tree_create(root, index, order, &node, &slot);
        if (error)
@@ -631,25 +625,22 @@ void *__radix_tree_lookup(struct radix_tree_root *root, unsigned long index,
 {
        struct radix_tree_node *node, *parent;
        unsigned long maxindex;
-       unsigned int shift;
        void **slot;
 
  restart:
        parent = NULL;
        slot = (void **)&root->rnode;
-       shift = radix_tree_load_root(root, &node, &maxindex);
+       radix_tree_load_root(root, &node, &maxindex);
        if (index > maxindex)
                return NULL;
 
-       while (radix_tree_is_indirect_ptr(node)) {
+       while (radix_tree_is_internal_node(node)) {
                unsigned offset;
 
                if (node == RADIX_TREE_RETRY)
                        goto restart;
-               parent = indirect_to_ptr(node);
-               shift -= RADIX_TREE_MAP_SHIFT;
-               offset = (index >> shift) & RADIX_TREE_MAP_MASK;
-               offset = radix_tree_descend(parent, &node, offset);
+               parent = entry_to_node(node);
+               offset = radix_tree_descend(parent, &node, index);
                slot = parent->slots + offset;
        }
 
@@ -719,19 +710,15 @@ void *radix_tree_tag_set(struct radix_tree_root *root,
 {
        struct radix_tree_node *node, *parent;
        unsigned long maxindex;
-       unsigned int shift;
 
-       shift = radix_tree_load_root(root, &node, &maxindex);
+       radix_tree_load_root(root, &node, &maxindex);
        BUG_ON(index > maxindex);
 
-       while (radix_tree_is_indirect_ptr(node)) {
+       while (radix_tree_is_internal_node(node)) {
                unsigned offset;
 
-               shift -= RADIX_TREE_MAP_SHIFT;
-               offset = (index >> shift) & RADIX_TREE_MAP_MASK;
-
-               parent = indirect_to_ptr(node);
-               offset = radix_tree_descend(parent, &node, offset);
+               parent = entry_to_node(node);
+               offset = radix_tree_descend(parent, &node, index);
                BUG_ON(!node);
 
                if (!tag_get(parent, tag, offset))
@@ -746,6 +733,26 @@ void *radix_tree_tag_set(struct radix_tree_root *root,
 }
 EXPORT_SYMBOL(radix_tree_tag_set);
 
+static void node_tag_clear(struct radix_tree_root *root,
+                               struct radix_tree_node *node,
+                               unsigned int tag, unsigned int offset)
+{
+       while (node) {
+               if (!tag_get(node, tag, offset))
+                       return;
+               tag_clear(node, tag, offset);
+               if (any_tag_set(node, tag))
+                       return;
+
+               offset = node->offset;
+               node = node->parent;
+       }
+
+       /* clear the root's tag bit */
+       if (root_tag_get(root, tag))
+               root_tag_clear(root, tag);
+}
+
 /**
  *     radix_tree_tag_clear - clear a tag on a radix tree node
  *     @root:          radix tree root
@@ -765,45 +772,22 @@ void *radix_tree_tag_clear(struct radix_tree_root *root,
 {
        struct radix_tree_node *node, *parent;
        unsigned long maxindex;
-       unsigned int shift;
        int uninitialized_var(offset);
 
-       shift = radix_tree_load_root(root, &node, &maxindex);
+       radix_tree_load_root(root, &node, &maxindex);
        if (index > maxindex)
                return NULL;
 
        parent = NULL;
 
-       while (radix_tree_is_indirect_ptr(node)) {
-               shift -= RADIX_TREE_MAP_SHIFT;
-               offset = (index >> shift) & RADIX_TREE_MAP_MASK;
-
-               parent = indirect_to_ptr(node);
-               offset = radix_tree_descend(parent, &node, offset);
+       while (radix_tree_is_internal_node(node)) {
+               parent = entry_to_node(node);
+               offset = radix_tree_descend(parent, &node, index);
        }
 
-       if (node == NULL)
-               goto out;
-
-       index >>= shift;
+       if (node)
+               node_tag_clear(root, parent, tag, offset);
 
-       while (parent) {
-               if (!tag_get(parent, tag, offset))
-                       goto out;
-               tag_clear(parent, tag, offset);
-               if (any_tag_set(parent, tag))
-                       goto out;
-
-               index >>= RADIX_TREE_MAP_SHIFT;
-               offset = index & RADIX_TREE_MAP_MASK;
-               parent = parent->parent;
-       }
-
-       /* clear the root's tag bit */
-       if (root_tag_get(root, tag))
-               root_tag_clear(root, tag);
-
-out:
        return node;
 }
 EXPORT_SYMBOL(radix_tree_tag_clear);
@@ -828,25 +812,21 @@ int radix_tree_tag_get(struct radix_tree_root *root,
 {
        struct radix_tree_node *node, *parent;
        unsigned long maxindex;
-       unsigned int shift;
 
        if (!root_tag_get(root, tag))
                return 0;
 
-       shift = radix_tree_load_root(root, &node, &maxindex);
+       radix_tree_load_root(root, &node, &maxindex);
        if (index > maxindex)
                return 0;
        if (node == NULL)
                return 0;
 
-       while (radix_tree_is_indirect_ptr(node)) {
-               int offset;
-
-               shift -= RADIX_TREE_MAP_SHIFT;
-               offset = (index >> shift) & RADIX_TREE_MAP_MASK;
+       while (radix_tree_is_internal_node(node)) {
+               unsigned offset;
 
-               parent = indirect_to_ptr(node);
-               offset = radix_tree_descend(parent, &node, offset);
+               parent = entry_to_node(node);
+               offset = radix_tree_descend(parent, &node, index);
 
                if (!node)
                        return 0;
@@ -879,8 +859,8 @@ static inline void __set_iter_shift(struct radix_tree_iter *iter,
 void **radix_tree_next_chunk(struct radix_tree_root *root,
                             struct radix_tree_iter *iter, unsigned flags)
 {
-       unsigned shift, tag = flags & RADIX_TREE_ITER_TAG_MASK;
-       struct radix_tree_node *rnode, *node;
+       unsigned tag = flags & RADIX_TREE_ITER_TAG_MASK;
+       struct radix_tree_node *node, *child;
        unsigned long index, offset, maxindex;
 
        if ((flags & RADIX_TREE_ITER_TAGGED) && !root_tag_get(root, tag))
@@ -900,38 +880,27 @@ void **radix_tree_next_chunk(struct radix_tree_root *root,
                return NULL;
 
  restart:
-       shift = radix_tree_load_root(root, &rnode, &maxindex);
+       radix_tree_load_root(root, &child, &maxindex);
        if (index > maxindex)
                return NULL;
+       if (!child)
+               return NULL;
 
-       if (radix_tree_is_indirect_ptr(rnode)) {
-               rnode = indirect_to_ptr(rnode);
-       } else if (rnode) {
+       if (!radix_tree_is_internal_node(child)) {
                /* Single-slot tree */
                iter->index = index;
                iter->next_index = maxindex + 1;
                iter->tags = 1;
-               __set_iter_shift(iter, shift);
+               __set_iter_shift(iter, 0);
                return (void **)&root->rnode;
-       } else
-               return NULL;
-
-       shift -= RADIX_TREE_MAP_SHIFT;
-       offset = index >> shift;
-
-       node = rnode;
-       while (1) {
-               struct radix_tree_node *slot;
-               unsigned new_off = radix_tree_descend(node, &slot, offset);
+       }
 
-               if (new_off < offset) {
-                       offset = new_off;
-                       index &= ~((RADIX_TREE_MAP_SIZE << shift) - 1);
-                       index |= offset << shift;
-               }
+       do {
+               node = entry_to_node(child);
+               offset = radix_tree_descend(node, &child, index);
 
                if ((flags & RADIX_TREE_ITER_TAGGED) ?
-                               !tag_get(node, tag, offset) : !slot) {
+                               !tag_get(node, tag, offset) : !child) {
                        /* Hole detected */
                        if (flags & RADIX_TREE_ITER_CONTIG)
                                return NULL;
@@ -949,30 +918,24 @@ void **radix_tree_next_chunk(struct radix_tree_root *root,
                                        if (slot)
                                                break;
                                }
-                       index &= ~((RADIX_TREE_MAP_SIZE << shift) - 1);
-                       index += offset << shift;
+                       index &= ~node_maxindex(node);
+                       index += offset << node->shift;
                        /* Overflow after ~0UL */
                        if (!index)
                                return NULL;
                        if (offset == RADIX_TREE_MAP_SIZE)
                                goto restart;
-                       slot = rcu_dereference_raw(node->slots[offset]);
+                       child = rcu_dereference_raw(node->slots[offset]);
                }
 
-               if ((slot == NULL) || (slot == RADIX_TREE_RETRY))
+               if ((child == NULL) || (child == RADIX_TREE_RETRY))
                        goto restart;
-               if (!radix_tree_is_indirect_ptr(slot))
-                       break;
-
-               node = indirect_to_ptr(slot);
-               shift -= RADIX_TREE_MAP_SHIFT;
-               offset = (index >> shift) & RADIX_TREE_MAP_MASK;
-       }
+       } while (radix_tree_is_internal_node(child));
 
        /* Update the iterator state */
-       iter->index = index & ~((1 << shift) - 1);
-       iter->next_index = (index | ((RADIX_TREE_MAP_SIZE << shift) - 1)) + 1;
-       __set_iter_shift(iter, shift);
+       iter->index = (index &~ node_maxindex(node)) | (offset << node->shift);
+       iter->next_index = (index | node_maxindex(node)) + 1;
+       __set_iter_shift(iter, node->shift);
 
        /* Construct iter->tags bit-mask from node->tags[tag] array */
        if (flags & RADIX_TREE_ITER_TAGGED) {
@@ -1028,12 +991,12 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root,
                unsigned long nr_to_tag,
                unsigned int iftag, unsigned int settag)
 {
-       struct radix_tree_node *slot, *node = NULL;
+       struct radix_tree_node *parent, *node, *child;
        unsigned long maxindex;
-       unsigned int shift = radix_tree_load_root(root, &slot, &maxindex);
        unsigned long tagged = 0;
        unsigned long index = *first_indexp;
 
+       radix_tree_load_root(root, &child, &maxindex);
        last_index = min(last_index, maxindex);
        if (index > last_index)
                return 0;
@@ -1043,29 +1006,23 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root,
                *first_indexp = last_index + 1;
                return 0;
        }
-       if (!radix_tree_is_indirect_ptr(slot)) {
+       if (!radix_tree_is_internal_node(child)) {
                *first_indexp = last_index + 1;
                root_tag_set(root, settag);
                return 1;
        }
 
-       node = indirect_to_ptr(slot);
-       shift -= RADIX_TREE_MAP_SHIFT;
+       node = entry_to_node(child);
 
        for (;;) {
-               unsigned long upindex;
-               unsigned offset;
-
-               offset = (index >> shift) & RADIX_TREE_MAP_MASK;
-               offset = radix_tree_descend(node, &slot, offset);
-               if (!slot)
+               unsigned offset = radix_tree_descend(node, &child, index);
+               if (!child)
                        goto next;
                if (!tag_get(node, iftag, offset))
                        goto next;
                /* Sibling slots never have tags set on them */
-               if (radix_tree_is_indirect_ptr(slot)) {
-                       node = indirect_to_ptr(slot);
-                       shift -= RADIX_TREE_MAP_SHIFT;
+               if (radix_tree_is_internal_node(child)) {
+                       node = entry_to_node(child);
                        continue;
                }
 
@@ -1073,27 +1030,25 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root,
                tagged++;
                tag_set(node, settag, offset);
 
-               slot = node->parent;
                /* walk back up the path tagging interior nodes */
-               upindex = index >> shift;
-               while (slot) {
-                       upindex >>= RADIX_TREE_MAP_SHIFT;
-                       offset = upindex & RADIX_TREE_MAP_MASK;
-
+               parent = node;
+               for (;;) {
+                       offset = parent->offset;
+                       parent = parent->parent;
+                       if (!parent)
+                               break;
                        /* stop if we find a node with the tag already set */
-                       if (tag_get(slot, settag, offset))
+                       if (tag_get(parent, settag, offset))
                                break;
-                       tag_set(slot, settag, offset);
-                       slot = slot->parent;
+                       tag_set(parent, settag, offset);
                }
-
  next:
-               /* Go to next item at level determined by 'shift' */
-               index = ((index >> shift) + 1) << shift;
+               /* Go to next entry in node */
+               index = ((index >> node->shift) + 1) << node->shift;
                /* Overflow can happen when last_index is ~0UL... */
                if (index > last_index || !index)
                        break;
-               offset = (index >> shift) & RADIX_TREE_MAP_MASK;
+               offset = (index >> node->shift) & RADIX_TREE_MAP_MASK;
                while (offset == 0) {
                        /*
                         * We've fully scanned this node. Go up. Because
@@ -1101,8 +1056,7 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root,
                         * we do below cannot wander astray.
                         */
                        node = node->parent;
-                       shift += RADIX_TREE_MAP_SHIFT;
-                       offset = (index >> shift) & RADIX_TREE_MAP_MASK;
+                       offset = (index >> node->shift) & RADIX_TREE_MAP_MASK;
                }
                if (is_sibling_entry(node, node->slots[offset]))
                        goto next;
@@ -1156,7 +1110,7 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
                results[ret] = rcu_dereference_raw(*slot);
                if (!results[ret])
                        continue;
-               if (radix_tree_is_indirect_ptr(results[ret])) {
+               if (radix_tree_is_internal_node(results[ret])) {
                        slot = radix_tree_iter_retry(&iter);
                        continue;
                }
@@ -1239,7 +1193,7 @@ radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results,
                results[ret] = rcu_dereference_raw(*slot);
                if (!results[ret])
                        continue;
-               if (radix_tree_is_indirect_ptr(results[ret])) {
+               if (radix_tree_is_internal_node(results[ret])) {
                        slot = radix_tree_iter_retry(&iter);
                        continue;
                }
@@ -1300,13 +1254,10 @@ struct locate_info {
 static unsigned long __locate(struct radix_tree_node *slot, void *item,
                              unsigned long index, struct locate_info *info)
 {
-       unsigned int shift;
        unsigned long i;
 
-       shift = slot->shift + RADIX_TREE_MAP_SHIFT;
-
        do {
-               shift -= RADIX_TREE_MAP_SHIFT;
+               unsigned int shift = slot->shift;
 
                for (i = (index >> shift) & RADIX_TREE_MAP_MASK;
                     i < RADIX_TREE_MAP_SIZE;
@@ -1315,7 +1266,7 @@ static unsigned long __locate(struct radix_tree_node *slot, void *item,
                                        rcu_dereference_raw(slot->slots[i]);
                        if (node == RADIX_TREE_RETRY)
                                goto out;
-                       if (!radix_tree_is_indirect_ptr(node)) {
+                       if (!radix_tree_is_internal_node(node)) {
                                if (node == item) {
                                        info->found_index = index;
                                        info->stop = true;
@@ -1323,15 +1274,13 @@ static unsigned long __locate(struct radix_tree_node *slot, void *item,
                                }
                                continue;
                        }
-                       node = indirect_to_ptr(node);
+                       node = entry_to_node(node);
                        if (is_sibling_entry(slot, node))
                                continue;
                        slot = node;
                        break;
                }
-               if (i == RADIX_TREE_MAP_SIZE)
-                       break;
-       } while (shift);
+       } while (i < RADIX_TREE_MAP_SIZE);
 
 out:
        if ((index == 0) && (i == RADIX_TREE_MAP_SIZE))
@@ -1361,14 +1310,14 @@ unsigned long radix_tree_locate_item(struct radix_tree_root *root, void *item)
        do {
                rcu_read_lock();
                node = rcu_dereference_raw(root->rnode);
-               if (!radix_tree_is_indirect_ptr(node)) {
+               if (!radix_tree_is_internal_node(node)) {
                        rcu_read_unlock();
                        if (node == item)
                                info.found_index = 0;
                        break;
                }
 
-               node = indirect_to_ptr(node);
+               node = entry_to_node(node);
 
                max_index = node_maxindex(node);
                if (cur_index > max_index) {
@@ -1399,40 +1348,37 @@ static inline bool radix_tree_shrink(struct radix_tree_root *root)
        bool shrunk = false;
 
        for (;;) {
-               struct radix_tree_node *to_free = root->rnode;
-               struct radix_tree_node *slot;
+               struct radix_tree_node *node = root->rnode;
+               struct radix_tree_node *child;
 
-               if (!radix_tree_is_indirect_ptr(to_free))
+               if (!radix_tree_is_internal_node(node))
                        break;
-               to_free = indirect_to_ptr(to_free);
+               node = entry_to_node(node);
 
                /*
                 * The candidate node has more than one child, or its child
                 * is not at the leftmost slot, or the child is a multiorder
                 * entry, we cannot shrink.
                 */
-               if (to_free->count != 1)
+               if (node->count != 1)
                        break;
-               slot = to_free->slots[0];
-               if (!slot)
+               child = node->slots[0];
+               if (!child)
                        break;
-               if (!radix_tree_is_indirect_ptr(slot) && to_free->shift)
+               if (!radix_tree_is_internal_node(child) && node->shift)
                        break;
 
-               if (radix_tree_is_indirect_ptr(slot)) {
-                       slot = indirect_to_ptr(slot);
-                       slot->parent = NULL;
-                       slot = ptr_to_indirect(slot);
-               }
+               if (radix_tree_is_internal_node(child))
+                       entry_to_node(child)->parent = NULL;
 
                /*
                 * We don't need rcu_assign_pointer(), since we are simply
                 * moving the node from one part of the tree to another: if it
                 * was safe to dereference the old pointer to it
-                * (to_free->slots[0]), it will be safe to dereference the new
+                * (node->slots[0]), it will be safe to dereference the new
                 * one (root->rnode) as far as dependent read barriers go.
                 */
-               root->rnode = slot;
+               root->rnode = child;
 
                /*
                 * We have a dilemma here. The node's slot[0] must not be
@@ -1452,10 +1398,10 @@ static inline bool radix_tree_shrink(struct radix_tree_root *root)
                 * also results in a stale slot). So tag the slot as indirect
                 * to force callers to retry.
                 */
-               if (!radix_tree_is_indirect_ptr(slot))
-                       to_free->slots[0] = RADIX_TREE_RETRY;
+               if (!radix_tree_is_internal_node(child))
+                       node->slots[0] = RADIX_TREE_RETRY;
 
-               radix_tree_node_free(to_free);
+               radix_tree_node_free(node);
                shrunk = true;
        }
 
@@ -1482,7 +1428,7 @@ bool __radix_tree_delete_node(struct radix_tree_root *root,
                struct radix_tree_node *parent;
 
                if (node->count) {
-                       if (node == indirect_to_ptr(root->rnode))
+                       if (node == entry_to_node(root->rnode))
                                deleted |= radix_tree_shrink(root);
                        return deleted;
                }
@@ -1554,16 +1500,11 @@ void *radix_tree_delete_item(struct radix_tree_root *root,
 
        offset = get_slot_offset(node, slot);
 
-       /*
-        * Clear all tags associated with the item to be deleted.
-        * This way of doing it would be inefficient, but seldom is any set.
-        */
-       for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) {
-               if (tag_get(node, tag, offset))
-                       radix_tree_tag_clear(root, index, tag);
-       }
+       /* Clear all tags associated with the item to be deleted.  */
+       for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++)
+               node_tag_clear(root, node, tag, offset);
 
-       delete_sibling_entries(node, ptr_to_indirect(slot), offset);
+       delete_sibling_entries(node, node_to_entry(slot), offset);
        node->slots[offset] = NULL;
        node->count--;
 
@@ -1588,6 +1529,28 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
 }
 EXPORT_SYMBOL(radix_tree_delete);
 
+struct radix_tree_node *radix_tree_replace_clear_tags(
+                       struct radix_tree_root *root,
+                       unsigned long index, void *entry)
+{
+       struct radix_tree_node *node;
+       void **slot;
+
+       __radix_tree_lookup(root, index, &node, &slot);
+
+       if (node) {
+               unsigned int tag, offset = get_slot_offset(node, slot);
+               for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++)
+                       node_tag_clear(root, node, tag, offset);
+       } else {
+               /* Clear root node tags */
+               root->gfp_mask &= __GFP_BITS_MASK;
+       }
+
+       radix_tree_replace_slot(slot, entry);
+       return node;
+}
+
 /**
  *     radix_tree_tagged - test whether any items in the tree are tagged
  *     @root:          radix tree root