]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
maple_tree: mt_for_each implementation
authorLiam R. Howlett <Liam.Howlett@Oracle.com>
Wed, 31 Jul 2019 18:52:04 +0000 (14:52 -0400)
committerLiam R. Howlett <Liam.Howlett@Oracle.com>
Wed, 31 Jul 2019 18:52:04 +0000 (14:52 -0400)
Signed-off-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
lib/maple_tree.c
lib/test_maple_tree.c

index 050675c7ce28ae603a41c3f821a0f376cf7d7a8f..e88a09faaabfd9c45975ffab9d70d7e85d8037f4 100644 (file)
@@ -22,6 +22,9 @@
  * @entry: Entry retrieved from the tree
  * @max: maximum index to retrieve from the tree
  *
+ * When returned, mas->index and mas->last will hold the entire range for the
+ * entry.
+ *
  * Note: may return the zero entry.
  *
  */
@@ -29,7 +32,7 @@
        while ((entry = mas_find(mas, max)) != NULL)
 
 /**
- * mt_for_each - Iterate over a range of the tree.
+ * mt_for_each - Searches for an entry starting at index until max.
  *
  *
  *
@@ -37,7 +40,9 @@
  *
  *
  */
-#define mt_for_each(tree, entry, index, last, max) \
+#define mt_for_each(tree, entry, index, max) \
+       for (entry = mt_find(mt, index, max); \
+            entry; entry = mt_find_after(mt, &index, max))
 
 
 
@@ -2202,6 +2207,7 @@ mas_next_nentry (struct ma_state *mas, unsigned long max, unsigned long *piv)
        unsigned char slot = ma_get_slot(mas);
        unsigned char count = mt_slot_count(mas->node);
        void *entry;
+       bool ret = false;
 
        while (slot < count) {
                pivot = ma_get_safe_pivot(mas, slot);
@@ -2214,8 +2220,10 @@ mas_next_nentry (struct ma_state *mas, unsigned long max, unsigned long *piv)
                /* Valid pivot */;
 
                entry = ma_get_rcu_slot(mas->node, slot);
-               if (entry)
+               if (entry) {
+                       ret = true;
                        break;
+               }
 
                /* Ran over the limit, this is was the last slot to try */
                if (pivot >= max)
@@ -2224,7 +2232,7 @@ mas_next_nentry (struct ma_state *mas, unsigned long max, unsigned long *piv)
                slot++;
        }
        ma_set_slot(mas, slot);
-       return true;
+       return ret;
 
 no_entry:
        return false;
@@ -2727,12 +2735,76 @@ not_found:
 
 }
 
-void *mt_find_after(struct ma_state *mas, unsigned long max)
+/* mt_find() - Search from start up until an entry is found.
+ *
+ * Note: Does not return the zero entry.
+ * returns an entry.
+ */
+static inline void *mt_find(struct maple_tree *mt, unsigned long start,
+               unsigned long max)
 {
-       void *entry = mas_find(mas, max);
+       MA_STATE(mas, mt, start, start);
+       unsigned char slot;
+       void *entry = NULL;
+
+       rcu_read_lock();
+       _mas_walk(&mas);
+       slot = ma_get_slot(&mas);
+       if (slot != MAPLE_NODE_SLOTS)
+               entry = ma_get_rcu_slot(mas.node, slot);
+
        if (xa_is_zero(entry))
-               return NULL;
+               entry = NULL;
+
+       if (entry)
+               goto done;
+
+retry:
+       mas_next_entry(&mas, max);
+       if (mas.node == MAS_NONE)
+               goto done;
+
+       slot = ma_get_slot(&mas);
+       entry = ma_get_rcu_slot(mas.node, slot);
+       if (xa_is_zero(entry))
+               goto retry;
+
+done:
+       rcu_read_unlock();
+
+       return entry;
+}
+
+/* mt_find_after() - Search up from the entry of index until an entry is
+ * found.
+ *
+ * Modifies index and last to point to the newly found range.
+ */
+static inline void *mt_find_after(struct maple_tree *mt, unsigned long *index,
+               unsigned long max)
+{
+       MA_STATE(mas, mt, *index, *index);
+       unsigned char slot;
+       void *entry = NULL;
+
+       rcu_read_lock();
+       _mas_walk(&mas);
+retry:
+       ma_set_slot(&mas, ma_get_slot(&mas) + 1);
+       mas_next_entry(&mas, max);
+       if (mas.node == MAS_NONE)
+               goto done;
+
+       slot = ma_get_slot(&mas);
+       entry = ma_get_rcu_slot(mas.node, slot);
+       if (xa_is_zero(entry))
+               goto retry;
+
+       *index = ma_get_safe_pivot(&mas, slot);
+done:
+       rcu_read_unlock();
        return entry;
+
 }
 static inline void ma_inactive_insert(struct ma_state *mas, void *entry);
 static inline int mas_replace_tree(struct ma_state *mas, void *new_entry)
index ea40c425fda06e6251dbbccadab7a5118a29132c..103ac70cf239b479893c5a9f80db53db252936a1 100644 (file)
@@ -364,6 +364,8 @@ static noinline void check_find(struct maple_tree *mt)
 {
        unsigned long val = 0;
        unsigned long count = 20;
+       unsigned long max;
+       unsigned long index = 0;
        void *entry;
        MA_STATE(mas, mt, 0, 0);
 
@@ -410,6 +412,12 @@ static noinline void check_find(struct maple_tree *mt)
                        val = 1;
        }
 
+       max = 300; // A value big enough to include XA_ZERO_ENTRY at 64.
+       mt_for_each(mt, entry, index, max) {
+               MT_BUG_ON(mt, xa_mk_value(val) != entry);
+       }
+
+
 }
 static noinline void check_alloc_rev_range(struct maple_tree *mt)
 {