}
/*
- * __mas_next() - Internal function to get the next entry.
+ * _mas_next() - Internal function to get the next entry.
* @mas: The maple state
* @limit: The maximum range start.
*
*
* Return: the next entry or %NULL.
*/
-static inline void *__mas_next(struct ma_state *mas, unsigned long limit)
+static inline void *_mas_next(struct ma_state *mas, unsigned long limit)
{
void *entry = NULL;
struct maple_enode *prev_node = mas->node;
}
/*
- * _mas_next() - Finds the next entry and sets @mas->index and @mas->last to the
- * range.
+ * _mas_find() - Finds the entry at @mas->index on MAS_START or the next entry
+ * and sets @mas->index and @mas->last to the range.
* @mas: The maple state
* @limit: The maximum value to check.
- *.
*
* Return: Point to the next entry or %NULL
- *
*/
-static void *_mas_next(struct ma_state *mas, unsigned long limit)
+static void *_mas_find(struct ma_state *mas, unsigned long limit)
{
if (unlikely(mas_is_start(mas))) {
/* First run */
unsigned long range_start;
mas_start(mas);
+ /* Retries on dead nodes handled by mas_range_load */
entry = mas_range_load(mas, &range_start, &range_max);
mas->last = range_max;
mas->index = range_start;
if (unlikely(!mas_searchable(mas)))
return NULL;
- return __mas_next(mas, limit);
+ /* Retries on dead nodes handled by _mas_next */
+ return _mas_next(mas, limit);
}
/*
entry = NULL;
while (mas_search_cont(&mas, range_start, max, entry)) {
- entry = _mas_next(&mas, max);
+ entry = _mas_find(&mas, max);
range_start = mas.index;
if (!entry || xa_is_zero(entry))
entry = NULL;
if (mas_is_start(mas)) {
mas->index = ++mas->last;
- return mas_find(mas, max);
+ /* Retries on dead nodes handled by _mas_find */
+ return _mas_find(mas, max);
}
- return __mas_next(mas, max);
+ /* Retries on dead nodes handled by _mas_next */
+ return _mas_next(mas, max);
}
EXPORT_SYMBOL_GPL(mas_next);
*/
void *mas_prev(struct ma_state *mas, unsigned long min)
{
- void *entry;
if (!mas->index) {
/* Nothing comes before 0 */
return NULL;
}
+ if (unlikely(mas_is_ptr(mas)))
+ return NULL;
+
if (mas_is_none(mas) || mas_is_paused(mas))
mas->node = MAS_START;
- if (!mas_searchable(mas))
- return NULL;
-
if (mas_is_start(mas)) {
+ void *entry;
+
+ mas->last = --mas->index;
mas_start(mas);
- mas_walk(mas);
+ entry = mas_walk(mas);
+ if (entry)
+ return entry;
}
- do {
- entry = _mas_prev(mas, min);
- } while (!mas_is_none(mas) && !entry);
-
- return entry;
+ return _mas_prev(mas, min);
}
EXPORT_SYMBOL_GPL(mas_prev);
}
EXPORT_SYMBOL_GPL(mas_pause);
-/*
- * mas_resume_fwd() - resume a forward search.
- * @mas: The maple state
- *
- * Returns: 0 on success, -EFAULT on overflow.
- */
-static inline int mas_resume_fwd(struct ma_state *mas) {
- if (mas_is_paused(mas)) {
- if (unlikely(mas->last == ULONG_MAX)) {
- mas->node = MAS_NONE;
- return -EFAULT;
- }
- mas->node = MAS_START;
- mas->index = ++mas->last;
- }
- return 0;
-}
-
/*
* mas_find: If mas->node == MAS_START, find the first
* non-NULL entry >= mas->index.
*/
void *mas_find(struct ma_state *mas, unsigned long max)
{
- void *entry = NULL;
- bool first = false;
- unsigned long index = mas->index;
-
- if (mas_is_start(mas) && (mas->index <= max))
- first = true;
- else if (mas_resume_fwd(mas))
- return NULL;
-
-retry:
- while (mas_search_cont(mas, mas->index, max, entry))
- entry = _mas_next(mas, max);
-
- if (unlikely(mas_dead_node(mas, index))) {
- if (first)
- mas->node = MAS_START;
-
- goto retry;
+ if (mas_is_paused(mas)) {
+ if (unlikely(mas->last == ULONG_MAX)) {
+ mas->node = MAS_NONE;
+ return NULL;
+ }
+ mas->node = MAS_START;
+ mas->index = ++mas->last;
}
- return entry;
+ return _mas_find(mas, max);
}
EXPORT_SYMBOL_GPL(mas_find);