]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
maple_tree: mas_next() and mas_find() state clean up
authorLiam R. Howlett <Liam.Howlett@oracle.com>
Fri, 10 Feb 2023 21:36:28 +0000 (16:36 -0500)
committerLiam R. Howlett <Liam.Howlett@oracle.com>
Mon, 13 Feb 2023 13:42:04 +0000 (08:42 -0500)
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>
lib/maple_tree.c

index eb26a2df4696d2776967d4fa316072e8b0628ed6..65e6b811f17a6a1aa6e6581ab9106ff8e13d1fbb 100644 (file)
@@ -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);