From: Liam R. Howlett <Liam.Howlett@oracle.com> Date: Fri, 10 Feb 2023 21:36:28 +0000 (-0500) Subject: maple_tree: mas_next() and mas_find() state clean up X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=9b74b1c635cdb50aa97ef6bea1b573bfbc63924b;p=users%2Fjedix%2Flinux-maple.git maple_tree: mas_next() and mas_find() state clean up mas_next() and mas_find() were not properly setting the internal maple state when the limits of the search were reached. mas_find() was not treating MAS_NONE as MAS_PAUSE, so an entry could be skipped if mas_find() was used after a completed mas_prev() that was empty. mas_find() was not correctly setting the node to MAS_NONE on a second mas_find() on a single entry tree of 0 - 0. Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com> --- diff --git a/lib/maple_tree.c b/lib/maple_tree.c index eb26a2df4696..65e6b811f17a 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -4719,21 +4719,15 @@ retry: static inline void *mas_next_entry(struct ma_state *mas, unsigned long limit) { void *entry = NULL; - struct maple_enode *prev_node; struct maple_node *node; - unsigned char offset; unsigned long last; enum maple_type mt; - if (mas->index > limit) { - mas->index = mas->last = limit; - mas_pause(mas); - return NULL; - } + if (mas->index > limit) + goto limit_reached; + last = mas->last; retry: - offset = mas->offset; - prev_node = mas->node; node = mas_mn(mas); mt = mte_node_type(mas->node); mas->offset++; @@ -4753,11 +4747,9 @@ retry: return entry; if (unlikely((mas->index > limit))) - break; + goto limit_reached; next_node: - prev_node = mas->node; - offset = mas->offset; if (unlikely(mas_next_node(mas, node, limit))) { mas_rewalk(mas, last); goto retry; @@ -4767,9 +4759,9 @@ next_node: mt = mte_node_type(mas->node); } +limit_reached: + mas->node = MAS_NONE; mas->index = mas->last = limit; - mas->offset = offset; - mas->node = prev_node; return NULL; } @@ -5868,10 +5860,11 @@ void *mas_next(struct ma_state *mas, unsigned long max) mas->index = 1; mas->last = ULONG_MAX; } + mas->node = MAS_NONE; return NULL; } - if (mas->last == ULONG_MAX) + if (mas->last >= max) return NULL; /* Retries on dead nodes handled by mas_next_entry */ @@ -5997,8 +5990,16 @@ EXPORT_SYMBOL_GPL(mas_pause); */ void *mas_find(struct ma_state *mas, unsigned long max) { + if (unlikely(mas_is_none(mas))) { + if (mas->last >= max) + goto none; + + mas->index = mas->last; + mas->node = MAS_PAUSE; + } + if (unlikely(mas_is_paused(mas))) { - if (unlikely(mas->last == ULONG_MAX)) { + if (unlikely(mas->last >= max)) { mas->node = MAS_NONE; return NULL; } @@ -6006,8 +6007,12 @@ void *mas_find(struct ma_state *mas, unsigned long max) mas->index = ++mas->last; } - if (unlikely(mas_is_none(mas))) - mas->node = MAS_START; + + if (unlikely(mas_is_ptr(mas))) { + mas->index = 1; + mas->last = ULONG_MAX; + goto none; + } if (unlikely(mas_is_start(mas))) { /* First run or continue */ @@ -6022,10 +6027,17 @@ void *mas_find(struct ma_state *mas, unsigned long max) } if (unlikely(!mas_searchable(mas))) - return NULL; + goto none; + + if (mas->index == max) + goto none; /* Retries on dead nodes handled by mas_next_entry */ return mas_next_entry(mas, max); + +none: + mas->node = MAS_NONE; + return NULL; } EXPORT_SYMBOL_GPL(mas_find);