From: Liam R. Howlett Date: Wed, 31 Jul 2019 18:52:04 +0000 (-0400) Subject: maple_tree: mt_for_each implementation X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=afb62484530cb0ae2ace7b556ff56550f9c2e404;p=users%2Fjedix%2Flinux-maple.git maple_tree: mt_for_each implementation Signed-off-by: Liam R. Howlett --- diff --git a/lib/maple_tree.c b/lib/maple_tree.c index 050675c7ce28..e88a09faaabf 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -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) diff --git a/lib/test_maple_tree.c b/lib/test_maple_tree.c index ea40c425fda0..103ac70cf239 100644 --- a/lib/test_maple_tree.c +++ b/lib/test_maple_tree.c @@ -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) {