mas->node = MAS_NONE;
mas->min = 0;
mas->max = ULONG_MAX;
+ mas_set_slot(mas, 0);
if (!mas->tree->ma_root) // empty tree.
goto done;
* mas->max if no node is found. Node is returned as mas->node which may be
* MAS_NONE.
*
- * Note, the slot for the first node is not valid if it is a leaf.
+ * Note, if we descend to a leaf, then the slot is not valid.
*
* @mas: maple state
- * @max: The maximum index to consider valid.
+ * @limit: The maximum index to consider valid.
*/
static inline unsigned long mas_first_node(struct ma_state *mas,
unsigned long limit)
continue;
}
-
+ // Non-leaf nodes need to descend.
if (!mte_is_leaf(mas->node)) {
mas->max = pivot;
mas->min = min;
}
/* Private
*
- * Returns the first entry.
+ * Returns the pivot which points to the entry with the lowest index.
+ * @mas slot is set to the entry location.
+ * @limit is the maximum index to check.
*
*/
static inline unsigned long mas_first_entry(struct ma_state *mas,
if (!mas_get_slot(mas))
return mas->min;
else
- return mas_get_safe_pivot(mas, mas_get_slot(mas)-1);
+ return mas_get_safe_pivot(mas,
+ mas_get_slot(mas) - 1);
}
mas_set_slot(mas, 0);
}
}
+
+/* Private
+ * mte_destroy_walk: Free the sub-tree from @mn and below.
+ */
void mte_destroy_walk(struct maple_enode *mn)
{
struct maple_enode *node;
no_entry:
mas->node = MAS_NONE;
}
-
-static inline void* mas_prev_entry(struct ma_state *mas, unsigned long min)
-{
- if (mas->node == MAS_NONE)
- return NULL;
-
- mas_prev_node(mas, min);
- if (mas->node == MAS_NONE)
- return NULL;
-
- return mte_get_rcu_slot(mas->node, mas_get_slot(mas));
-}
/*
* Find the next non-null entry at the same level in the tree. The next value
* will be mas->node[mas_get_slot(mas)] or MAS_NONE.
/** Private
* prev node entry
*/
-static inline bool mas_prev_nentry(struct ma_state *mas, unsigned long min,
- unsigned long *piv)
+static inline bool mas_prev_nentry(struct ma_state *mas, unsigned long limit,
+ unsigned long *max)
{
- unsigned long pivot;
+ unsigned long pivot = mas->max;
unsigned char slot = mas_get_slot(mas);
void *entry;
slot--;
do {
pivot = mas_get_safe_pivot(mas, slot);
- if (pivot < min)
+ if (pivot < limit)
goto no_entry;
- *piv = pivot;
entry = mte_get_rcu_slot(mas->node, slot);
if (!mt_is_empty(entry))
goto found;
return false;
found:
+ *max = pivot;
mas_set_slot(mas, slot);
return true;
}
mas_set_slot(mas, slot);
return true;
}
+/* Private
+ *
+ * Returns the pivot which points to the entry with the highest index.
+ * @mas slot is set to the entry location.
+ * @limit is the minimum index to check.
+ *
+ */
+static inline void* mas_last_entry(struct ma_state *mas,
+ unsigned long limit)
+{
+ unsigned long prev_min, prev_max, range_start = 0;
+ unsigned char slot = 1;
+
+ if (mas_start(mas) || mas_is_none(mas))
+ return NULL;
+
+ prev_min = mas->min;
+ prev_max = mas->max;
+ while (range_start < limit) {
+ mas_set_slot(mas, slot);
+ if (!mas_next_nentry(mas, limit, &range_start)) {
+ void *entry = mte_get_rcu_slot(mas->node, slot - 1);
+ if (mte_is_leaf(mas->node)) {
+ mas->index = range_start;
+ return entry;
+ }
+ mas->max = prev_max;
+ mas->min = prev_min;
+ mas->node = entry;
+ slot = 0;
+ } else {
+ slot = mas_get_slot(mas) + 1;
+ prev_min = prev_max + 1;
+ if (range_start > prev_min)
+ prev_min = range_start;
+ range_start = prev_min;
+ prev_max = mas->last;
+ }
+ }
+ return NULL;
+}
/** Private
*
entry = mte_get_rcu_slot(mas->node, mas_get_slot(mas));
if (mas_dead_node(mas, index))
goto retry;
+
return entry;
}
if (!mas->node || mas_is_start(mas)) { // First run.
unsigned long range_max;
+
entry = mas_range_load(mas, range_start, &range_max);
}
}
EXPORT_SYMBOL_GPL(mas_next);
+/* Private
+ *
+ * _mas_prev() - Find the previous entry from the current mas state.
+ * @mas the current maple state (must have a valid slot)
+ */
+static inline void* _mas_prev(struct ma_state *mas, unsigned long limit)
+{
+ unsigned long max = mas->max;
+ unsigned char slot;
+
+ while(!mas_is_none(mas)) {
+ if (mas_prev_nentry(mas, limit, &max))
+ break;
+
+ mas_prev_node(mas, limit);
+ mas_set_slot(mas, mt_slot_count(mas->node) - 1);
+ }
+
+ if (mas->node == MAS_NONE)
+ return NULL;
+
+ mas->last = max;
+ slot = mas_get_slot(mas);
+ if (slot)
+ mas->index = mas_get_safe_pivot(mas, slot - 1) + 1;
+ else
+ mas->index = mas->min;
+
+ return mte_get_rcu_slot(mas->node, mas_get_slot(mas));
+}
+
+/*
+ * mas_prev() - Get the previous entry. Can return the zero entry.
+ *
+ *
+ */
+static inline void *mas_prev(struct ma_state *mas, unsigned long min)
+{
+ void *entry;
+ if (mas->node && !mas_searchable(mas))
+ return NULL;
+
+ if (!mas->node)
+ mas->node = MAS_START;
+
+ if (mas_is_start(mas)) {
+ mas_start(mas);
+ return mas_last_entry(mas, ULONG_MAX);
+ }
+
+ entry = _mas_prev(mas, min);
+ return entry;
+}
+EXPORT_SYMBOL_GPL(mas_prev);
+
static inline int mas_coalesce_node(struct ma_state *mas, unsigned char end,
unsigned char coalesce, bool replace)
{
unsigned char all_slots; // Total slots needed for this and right node.
unsigned char l_slot_cnt, r_slot_cnt; // left and right slot counts
unsigned char trimmed = 0; // Trimmed terminating null range from left
- unsigned long l_piv, r_piv; // left and right pivots
+ unsigned long l_piv, r_piv = 0; // left and right pivots
unsigned char r_end, r_coalesce; // right node end and values that can be coalesced.
unsigned char node_cnt; // Number of nodes to allocate
unsigned long this_max = mas->max, this_min = mas->min; // ma state saves for this entry
enum maple_type type;
struct maple_enode *next;
unsigned long pivot = 0;
- unsigned long pivot_cnt, max, min, i;
+ unsigned long max, min, i;
bool ret = false;
min = mas->min;
while (true) {
type = mte_node_type(mas->node);
- pivot_cnt = mt_pivots[type];
if (ma_is_leaf(type)) // Leaf.
ret = true;
skip_entry:
switch (type) {
default:
- for (i = mas_get_slot(mas); i < pivot_cnt; i++) {
- pivot = _mte_get_pivot(mas->node, i, type);
+ for (i = mas_get_slot(mas); i < mt_slots[type]; i++) {
+ pivot = _mas_get_safe_pivot(mas, i, type);
if (i != 0 && pivot == 0) {
i = MAPLE_NODE_SLOTS;
goto done;
min = pivot + 1;
}
- if ((i == pivot_cnt - 1) && (mas->index > pivot))
- i++;
-
if (ret)
goto done;
break;
*/
void *mas_find(struct ma_state *mas, unsigned long max)
{
- unsigned long index = 0;
+ unsigned long index;
void *entry = NULL;
entry = _mas_next(mas, max, &index);
void *mas_load(struct ma_state *mas)
{
unsigned long range_max, range_min;
+
return mas_range_load(mas, &range_min, &range_max);
}
static inline bool mas_rewind_node(struct ma_state *mas)