From: Liam R. Howlett Date: Mon, 5 Jul 2021 19:30:41 +0000 (-0400) Subject: maple_tree: Change mas_next() behaviour X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=6be6e70864e3ec42d3927ff07d5649c56d994f35;p=users%2Fjedix%2Flinux-maple.git maple_tree: Change mas_next() behaviour Signed-off-by: Liam R. Howlett --- diff --git a/include/linux/maple_tree.h b/include/linux/maple_tree.h index eea2d2a0e26e2..7ccca75d4e3bd 100644 --- a/include/linux/maple_tree.h +++ b/include/linux/maple_tree.h @@ -243,6 +243,7 @@ struct ma_state { #define MAS_START ((struct maple_enode *)1UL) #define MAS_ROOT ((struct maple_enode *)5UL) #define MAS_NONE ((struct maple_enode *)9UL) +#define MAS_PAUSE ((struct maple_enode *)17UL) #define MA_ERROR(err) \ ((struct maple_enode *)(((unsigned long)err << 2) | 2UL)) @@ -286,6 +287,12 @@ static inline bool mas_is_none(struct ma_state *mas) return mas->node == MAS_NONE; } +/* Checks if a mas has been paused */ +static inline bool mas_is_paused(struct ma_state *mas) +{ + return mas->node == MAS_PAUSE; +} + void mas_dup_tree(struct ma_state *oldmas, struct ma_state *mas); void mas_dup_store(struct ma_state *mas, void *entry); /* This finds an empty area from the highest address to the lowest. diff --git a/lib/maple_tree.c b/lib/maple_tree.c index e0e55c861a6e8..7e977ac2d6321 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -4800,7 +4800,7 @@ void *mas_walk(struct ma_state *mas) unsigned long index = mas->index; void *entry; - if (mas_is_none(mas)) + if (mas_is_none(mas) || mas_is_paused(mas)) mas->node = MAS_START; _mas_walk(mas, &range_min, &range_max); @@ -5197,7 +5197,7 @@ static inline void *mas_range_load(struct ma_state *mas, unsigned long index = mas->index; void *entry; - if (mas_is_none(mas)) + if (mas_is_none(mas) || mas_is_paused(mas)) mas->node = MAS_START; if (_mas_walk(mas, range_min, range_max)) @@ -5226,11 +5226,9 @@ retry: */ static void *_mas_next(struct ma_state *mas, unsigned long limit) { - void *entry = NULL; - - if (unlikely(mas_is_start(mas))) { /* First run */ + void *entry = NULL; unsigned long range_max; unsigned long range_start; @@ -5245,8 +5243,7 @@ static void *_mas_next(struct ma_state *mas, unsigned long limit) if (unlikely(!mas_searchable(mas))) return NULL; - entry = __mas_next(mas, limit); - return entry; + return __mas_next(mas, limit); } /* @@ -5585,6 +5582,7 @@ void mas_destroy(struct ma_state *mas) * @mas: The maple state * @max: The maximum index to check. * + * Returns the next entry after @mas->index. * Must hold rcu_read_lock or the write lock. * Can return the zero entry. * @@ -5592,14 +5590,29 @@ void mas_destroy(struct ma_state *mas) */ void *mas_next(struct ma_state *mas, unsigned long max) { - if (mas_is_none(mas)) + if (mas_is_none(mas) || mas_is_paused(mas)) mas->node = MAS_START; - return _mas_next(mas, max); + if (unlikely(!mas_searchable(mas))) + return NULL; + + if (mas_is_start(mas)) { + mas->index = ++mas->last; + return mas_find(mas, max); + } + + return __mas_next(mas, max); } EXPORT_SYMBOL_GPL(mas_next); - +/* + * mt_next() - get the next value in the maple tree + * @mt: The maple tree + * @index: The start index + * @max: The maximum index to check + * + * Returns: The entry at @index or higher, or %NULL if nothing is found. + */ void *mt_next(struct maple_tree *mt, unsigned long index, unsigned long max) { void *entry = NULL; @@ -5620,7 +5633,8 @@ EXPORT_SYMBOL_GPL(mt_next); * Must hold rcu_read_lock or the write lock. * Will reset mas to MAS_START if the node is MAS_NONE. Will stop on not * searchable nodes. If mas->node is MAS_START, it will first look up the - * index, then get the previous entry. + * index and return. If there is nothing at mas->index, then the prev entry + * will be returned. * * Return: the previous value or %NULL. */ @@ -5634,13 +5648,12 @@ void *mas_prev(struct ma_state *mas, unsigned long min) return NULL; } - if (mas_is_none(mas)) + if (mas_is_none(mas) || mas_is_paused(mas)) mas->node = MAS_START; if (!mas_searchable(mas)) return NULL; - if (mas_is_start(mas)) { mas_start(mas); mas_walk(mas); @@ -5654,6 +5667,14 @@ void *mas_prev(struct ma_state *mas, unsigned long min) } EXPORT_SYMBOL_GPL(mas_prev); +/* + * mt_prev() - get the previous value in the maple tree + * @mt: The maple tree + * @index: The start index + * @max: The minumum index to check + * + * Returns: The entry at @index or lower, or %NULL if nothing is found. + */ void *mt_prev(struct maple_tree *mt, unsigned long index, unsigned long min) { void *entry = NULL; @@ -5680,18 +5701,27 @@ EXPORT_SYMBOL_GPL(mt_prev); */ void mas_pause(struct ma_state *mas) { - /* Overflow protection */ - if (mas->last == ULONG_MAX) { - mas->node = MAS_NONE; - return; - } - - mas_reset(mas); - mas->last++; - mas->index = mas->last; + mas->node = MAS_PAUSE; } 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 @@ -5714,6 +5744,8 @@ void *mas_find(struct ma_state *mas, unsigned long max) 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))