/*
* Private: Returns true if mas->node is a leaf
+ *
+ *
+ * Will not point to a skip entry.
+ * May point to a deleted or retry entry.
+ *
*/
static inline bool __mas_walk(struct ma_state *mas)
{
case maple_dense:
// Linear node.
i = mas->index - mas->min;
+ mas->min = mas->max = mas->index;
goto done;
}
goto skip_entry;
}
- if (mt_is_empty(next)) // Not found.
- goto done;
-
// Traverse.
mas->max = max;
mas->min = min;
+ if (mt_is_empty(next)) // Not found.
+ goto done;
+
mas->node = next;
}
done:
static inline bool _mas_walk(struct ma_state *mas)
{
void *entry = mas_start(mas);
+
if (entry)
return true;
return 1;
}
-void *mas_load(struct ma_state *mas)
-{
- void *entry = mas_walk(mas);
- if (xa_is_zero(entry) || mt_is_empty(entry))
- return NULL;
-
- return entry;
-}
/**
* mas_find - Find the first entry that overlaps the range.
* If mas->node is root, finds mas->index and returns the value. If the
return -EBUSY;
}
-/*
- * Private
+/**
*
* Must hold rcu_read_lock or the write lock.
*
* Find where ms->index is located and return the entry.
- * ms->node will point to the node containing the entry.
+ * mas->node will point to the node containing the entry.
*
*
*/
-void *mas_walk(struct ma_state *mas)
+void *mas_load(struct ma_state *mas)
{
void *entry = NULL;
- unsigned char slot = MAPLE_NODE_SLOTS;
- bool leaf = false;
- void *root = rcu_dereference(mas->tree->ma_root);
- if (root == NULL)
+retry:
+ if (_mas_walk(mas)) {
+ unsigned char slot = MAPLE_NODE_SLOTS;
+
+ if (mas_is_ptr(mas) && mas->last == 0)
+ return mte_safe_root(mas->tree->ma_root);
+
+ slot = mas_get_slot(mas);
+ if (slot >= MAPLE_NODE_SLOTS)
+ return NULL;
+
+ entry = mte_get_rcu_slot(mas->node, slot);
+ if (mte_dead_node(mas->node))
+ goto retry;
+
+ }
+
+ if (mas_is_none(mas))
return NULL;
- if (!xa_is_node(root)) {
- if (mas->last == 0)
- return root;
+ if (!entry || xa_is_deleted(entry))
return NULL;
- }
- leaf = _mas_walk(mas);
- slot = mas_get_slot(mas);
- if (leaf == true) {
- if (slot == MAPLE_NODE_SLOTS) {
- if (mas->index == 0)
- return root;
- } else {
- entry = mte_get_rcu_slot(mas->node, slot);
- }
- }
+ if (xa_is_retry(entry))
+ goto retry;
return entry;
}
rcu_read_lock();
entry = mas_load(&mas);
rcu_read_unlock();
+ if (xa_is_zero(entry))
+ return NULL;
+
return entry;
}
EXPORT_SYMBOL(mtree_load);