|
@@ -753,19 +753,10 @@ void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index)
|
|
|
}
|
|
|
EXPORT_SYMBOL(radix_tree_lookup);
|
|
|
|
|
|
-/**
|
|
|
- * __radix_tree_replace - replace item in a slot
|
|
|
- * @root: radix tree root
|
|
|
- * @node: pointer to tree node
|
|
|
- * @slot: pointer to slot in @node
|
|
|
- * @item: new item to store in the slot.
|
|
|
- *
|
|
|
- * For use with __radix_tree_lookup(). Caller must hold tree write locked
|
|
|
- * across slot lookup and replacement.
|
|
|
- */
|
|
|
-void __radix_tree_replace(struct radix_tree_root *root,
|
|
|
- struct radix_tree_node *node,
|
|
|
- void **slot, void *item)
|
|
|
+static void replace_slot(struct radix_tree_root *root,
|
|
|
+ struct radix_tree_node *node,
|
|
|
+ void **slot, void *item,
|
|
|
+ bool warn_typeswitch)
|
|
|
{
|
|
|
void *old = rcu_dereference_raw(*slot);
|
|
|
int exceptional;
|
|
@@ -776,7 +767,7 @@ void __radix_tree_replace(struct radix_tree_root *root,
|
|
|
exceptional = !!radix_tree_exceptional_entry(item) -
|
|
|
!!radix_tree_exceptional_entry(old);
|
|
|
|
|
|
- WARN_ON_ONCE(exceptional && !node && slot != (void **)&root->rnode);
|
|
|
+ WARN_ON_ONCE(warn_typeswitch && exceptional);
|
|
|
|
|
|
if (node)
|
|
|
node->exceptional += exceptional;
|
|
@@ -784,6 +775,50 @@ void __radix_tree_replace(struct radix_tree_root *root,
|
|
|
rcu_assign_pointer(*slot, item);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * __radix_tree_replace - replace item in a slot
|
|
|
+ * @root: radix tree root
|
|
|
+ * @node: pointer to tree node
|
|
|
+ * @slot: pointer to slot in @node
|
|
|
+ * @item: new item to store in the slot.
|
|
|
+ *
|
|
|
+ * For use with __radix_tree_lookup(). Caller must hold tree write locked
|
|
|
+ * across slot lookup and replacement.
|
|
|
+ */
|
|
|
+void __radix_tree_replace(struct radix_tree_root *root,
|
|
|
+ struct radix_tree_node *node,
|
|
|
+ void **slot, void *item)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * This function supports replacing exceptional entries, but
|
|
|
+ * that needs accounting against the node unless the slot is
|
|
|
+ * root->rnode.
|
|
|
+ */
|
|
|
+ replace_slot(root, node, slot, item,
|
|
|
+ !node && slot != (void **)&root->rnode);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * radix_tree_replace_slot - replace item in a slot
|
|
|
+ * @root: radix tree root
|
|
|
+ * @slot: pointer to slot
|
|
|
+ * @item: new item to store in the slot.
|
|
|
+ *
|
|
|
+ * For use with radix_tree_lookup_slot(), radix_tree_gang_lookup_slot(),
|
|
|
+ * radix_tree_gang_lookup_tag_slot(). Caller must hold tree write locked
|
|
|
+ * across slot lookup and replacement.
|
|
|
+ *
|
|
|
+ * NOTE: This cannot be used to switch between non-entries (empty slots),
|
|
|
+ * regular entries, and exceptional entries, as that requires accounting
|
|
|
+ * inside the radix tree node. When switching from one type of entry to
|
|
|
+ * another, use __radix_tree_lookup() and __radix_tree_replace().
|
|
|
+ */
|
|
|
+void radix_tree_replace_slot(struct radix_tree_root *root,
|
|
|
+ void **slot, void *item)
|
|
|
+{
|
|
|
+ replace_slot(root, NULL, slot, item, true);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* radix_tree_tag_set - set a tag on a radix tree node
|
|
|
* @root: radix tree root
|