* radix_tree_tag_get
* radix_tree_tagged
*
- * The first 7 functions are able to be called locklessly, using RCU. The
+ * The first 3 functions are able to be called locklessly, using RCU. The
* caller must ensure calls to these functions are made within rcu_read_lock()
* regions. Other readers (lock-free or otherwise) and modifications may be
* running concurrently.
* radix_tree_tagged is able to be called without locking or RCU.
*/
-int radix_tree_insert(struct radix_tree_root *, unsigned long index,
- void *);
void *__radix_tree_lookup(const struct radix_tree_root *, unsigned long index,
struct radix_tree_node **nodep, void __rcu ***slotp);
void *radix_tree_lookup(const struct radix_tree_root *, unsigned long);
void radix_tree_iter_replace(struct radix_tree_root *,
const struct radix_tree_iter *, void __rcu **slot, void *entry);
void *radix_tree_delete_item(struct radix_tree_root *, unsigned long, void *);
-void *radix_tree_delete(struct radix_tree_root *, unsigned long);
void radix_tree_init(void);
-void *radix_tree_tag_set(struct radix_tree_root *,
- unsigned long index, unsigned int tag);
-void *radix_tree_tag_clear(struct radix_tree_root *,
- unsigned long index, unsigned int tag);
int radix_tree_tag_get(const struct radix_tree_root *,
unsigned long index, unsigned int tag);
void radix_tree_iter_tag_clear(struct radix_tree_root *,
return offset;
}
-static inline gfp_t root_gfp_mask(const struct radix_tree_root *root)
-{
- return root->xa_flags & (__GFP_BITS_MASK & ~GFP_ZONEMASK);
-}
-
static inline void tag_set(struct radix_tree_node *node, unsigned int tag,
int offset)
{
return deleted;
}
-/**
- * __radix_tree_create - create a slot in a radix tree
- * @root: radix tree root
- * @index: index key
- * @nodep: returns node
- * @slotp: returns slot
- *
- * Create, if necessary, and return the node and slot for an item
- * at position @index in the radix tree @root.
- *
- * Until there is more than one item in the tree, no nodes are
- * allocated and @root->xa_head is used as a direct slot instead of
- * pointing to a node, in which case *@nodep will be NULL.
- *
- * Returns -ENOMEM, or 0 for success.
- */
-static int __radix_tree_create(struct radix_tree_root *root,
- unsigned long index, struct radix_tree_node **nodep,
- void __rcu ***slotp)
-{
- struct radix_tree_node *node = NULL, *child;
- void __rcu **slot = (void __rcu **)&root->xa_head;
- unsigned long maxindex;
- unsigned int shift, offset = 0;
- unsigned long max = index;
- gfp_t gfp = root_gfp_mask(root);
-
- shift = radix_tree_load_root(root, &child, &maxindex);
-
- /* Make sure the tree is high enough. */
- if (max > maxindex) {
- int error = radix_tree_extend(root, gfp, max, shift);
- if (error < 0)
- return error;
- shift = error;
- child = rcu_dereference_raw(root->xa_head);
- }
-
- while (shift > 0) {
- shift -= RADIX_TREE_MAP_SHIFT;
- if (child == NULL) {
- /* Have to add a child node. */
- child = radix_tree_node_alloc(gfp, node, root, shift,
- offset, 0, 0);
- if (!child)
- return -ENOMEM;
- rcu_assign_pointer(*slot, node_to_entry(child));
- if (node)
- node->count++;
- } else if (!radix_tree_is_internal_node(child))
- break;
-
- /* Go a level down */
- node = entry_to_node(child);
- offset = radix_tree_descend(node, &child, index);
- slot = &node->slots[offset];
- }
-
- if (nodep)
- *nodep = node;
- if (slotp)
- *slotp = slot;
- return 0;
-}
-
/*
* Free any nodes below this node. The tree is presumed to not need
* shrinking, and any user data in the tree is presumed to not need a
return 1;
}
-/**
- * __radix_tree_insert - insert into a radix tree
- * @root: radix tree root
- * @index: index key
- * @item: item to insert
- *
- * Insert an item into the radix tree at position @index.
- */
-int radix_tree_insert(struct radix_tree_root *root, unsigned long index,
- void *item)
-{
- struct radix_tree_node *node;
- void __rcu **slot;
- int error;
-
- BUG_ON(radix_tree_is_internal_node(item));
-
- error = __radix_tree_create(root, index, &node, &slot);
- if (error)
- return error;
-
- error = insert_entries(node, slot, item, false);
- if (error < 0)
- return error;
-
- if (node) {
- unsigned offset = get_slot_offset(node, slot);
- BUG_ON(tag_get(node, 0, offset));
- BUG_ON(tag_get(node, 1, offset));
- BUG_ON(tag_get(node, 2, offset));
- } else {
- BUG_ON(root_tags_get(root));
- }
-
- return 0;
-}
-EXPORT_SYMBOL(radix_tree_insert);
-
/**
* __radix_tree_lookup - lookup an item in a radix tree
* @root: radix tree root
{
return __radix_tree_lookup(root, index, NULL, NULL);
}
-EXPORT_SYMBOL(radix_tree_lookup);
static void replace_slot(void __rcu **slot, void *item,
struct radix_tree_node *node, int count, int values)
root_tag_set(root, tag);
}
-/**
- * radix_tree_tag_set - set a tag on a radix tree node
- * @root: radix tree root
- * @index: index key
- * @tag: tag index
- *
- * Set the search tag (which must be < RADIX_TREE_MAX_TAGS)
- * corresponding to @index in the radix tree. From
- * the root all the way down to the leaf node.
- *
- * Returns the address of the tagged item. Setting a tag on a not-present
- * item is a bug.
- */
-void *radix_tree_tag_set(struct radix_tree_root *root,
- unsigned long index, unsigned int tag)
-{
- struct radix_tree_node *node, *parent;
- unsigned long maxindex;
-
- radix_tree_load_root(root, &node, &maxindex);
- BUG_ON(index > maxindex);
-
- while (radix_tree_is_internal_node(node)) {
- unsigned offset;
-
- parent = entry_to_node(node);
- offset = radix_tree_descend(parent, &node, index);
- BUG_ON(!node);
-
- if (!tag_get(parent, tag, offset))
- tag_set(parent, tag, offset);
- }
-
- /* set the root's tag bit */
- if (!root_tag_get(root, tag))
- root_tag_set(root, tag);
-
- return node;
-}
-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)
root_tag_clear(root, tag);
}
-/**
- * radix_tree_tag_clear - clear a tag on a radix tree node
- * @root: radix tree root
- * @index: index key
- * @tag: tag index
- *
- * Clear the search tag (which must be < RADIX_TREE_MAX_TAGS)
- * corresponding to @index in the radix tree. If this causes
- * the leaf node to have no tags set then clear the tag in the
- * next-to-leaf node, etc.
- *
- * Returns the address of the tagged item on success, else NULL. ie:
- * has the same return value and semantics as radix_tree_lookup().
- */
-void *radix_tree_tag_clear(struct radix_tree_root *root,
- unsigned long index, unsigned int tag)
-{
- struct radix_tree_node *node, *parent;
- unsigned long maxindex;
- int uninitialized_var(offset);
-
- radix_tree_load_root(root, &node, &maxindex);
- if (index > maxindex)
- return NULL;
-
- parent = NULL;
-
- while (radix_tree_is_internal_node(node)) {
- parent = entry_to_node(node);
- offset = radix_tree_descend(parent, &node, index);
- }
-
- if (node)
- node_tag_clear(root, parent, tag, offset);
-
- return node;
-}
-EXPORT_SYMBOL(radix_tree_tag_clear);
-
/**
* radix_tree_iter_tag_clear - clear a tag on the current iterator entry
* @root: radix tree root
return 1;
}
-EXPORT_SYMBOL(radix_tree_tag_get);
/**
* radix_tree_next_chunk - find next chunk of slots for iteration
return entry;
}
-EXPORT_SYMBOL(radix_tree_delete_item);
-
-/**
- * radix_tree_delete - delete an entry from a radix tree
- * @root: radix tree root
- * @index: index key
- *
- * Remove the entry at @index from the radix tree rooted at @root.
- *
- * Return: The deleted entry, or %NULL if it was not present.
- */
-void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
-{
- return radix_tree_delete_item(root, index, NULL);
-}
-EXPORT_SYMBOL(radix_tree_delete);
/**
* radix_tree_tagged - test whether any items in the tree are tagged