From: "Liam R. Howlett" <Liam.Howlett@oracle.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: maple-tree@lists.infradead.org, linux-mm@kvack.org,
linux-kernel@vger.kernel.org,
"Liam R. Howlett" <Liam.Howlett@oracle.com>
Subject: [PATCH v4 30/35] maple_tree: Introduce mas_prev_slot() interface
Date: Thu, 18 May 2023 10:55:39 -0400 [thread overview]
Message-ID: <20230518145544.1722059-31-Liam.Howlett@oracle.com> (raw)
In-Reply-To: <20230518145544.1722059-1-Liam.Howlett@oracle.com>
Sometimes the user needs to revert to the previous slot, regardless of
if it is empty or not. Add an interface to go to the previous slot.
Since there can't be two consecutive NULLs in the tree, the mas_prev()
function can be implemented by calling mas_prev_slot() a maximum of 2
times. Change the underlying interface to use mas_prev_slot() to align
the code.
Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
---
lib/maple_tree.c | 232 ++++++++++++++++++-----------------------------
1 file changed, 90 insertions(+), 142 deletions(-)
diff --git a/lib/maple_tree.c b/lib/maple_tree.c
index 25748014fe34..f0e9ce5b0515 100644
--- a/lib/maple_tree.c
+++ b/lib/maple_tree.c
@@ -4531,15 +4531,19 @@ static inline int mas_prev_node(struct ma_state *mas, unsigned long min)
int offset, level;
void __rcu **slots;
struct maple_node *node;
- struct maple_enode *enode;
unsigned long *pivots;
+ unsigned long max;
- if (mas_is_none(mas))
- return 0;
+ node = mas_mn(mas);
+ if (!mas->min)
+ goto no_entry;
+
+ max = mas->min - 1;
+ if (max < min)
+ goto no_entry;
level = 0;
do {
- node = mas_mn(mas);
if (ma_is_root(node))
goto no_entry;
@@ -4548,64 +4552,41 @@ static inline int mas_prev_node(struct ma_state *mas, unsigned long min)
return 1;
offset = mas->offset;
level++;
+ node = mas_mn(mas);
} while (!offset);
offset--;
mt = mte_node_type(mas->node);
- node = mas_mn(mas);
- slots = ma_slots(node, mt);
- pivots = ma_pivots(node, mt);
- if (unlikely(ma_dead_node(node)))
- return 1;
-
- mas->max = pivots[offset];
- if (offset)
- mas->min = pivots[offset - 1] + 1;
- if (unlikely(ma_dead_node(node)))
- return 1;
-
- if (mas->max < min)
- goto no_entry_min;
-
while (level > 1) {
level--;
- enode = mas_slot(mas, slots, offset);
+ slots = ma_slots(node, mt);
+ mas->node = mas_slot(mas, slots, offset);
if (unlikely(ma_dead_node(node)))
return 1;
- mas->node = enode;
mt = mte_node_type(mas->node);
node = mas_mn(mas);
- slots = ma_slots(node, mt);
pivots = ma_pivots(node, mt);
- offset = ma_data_end(node, mt, pivots, mas->max);
+ offset = ma_data_end(node, mt, pivots, max);
if (unlikely(ma_dead_node(node)))
return 1;
-
- if (offset)
- mas->min = pivots[offset - 1] + 1;
-
- if (offset < mt_pivots[mt])
- mas->max = pivots[offset];
-
- if (mas->max < min)
- goto no_entry;
}
+ slots = ma_slots(node, mt);
mas->node = mas_slot(mas, slots, offset);
+ pivots = ma_pivots(node, mt);
if (unlikely(ma_dead_node(node)))
return 1;
+ if (likely(offset))
+ mas->min = pivots[offset - 1] + 1;
+ mas->max = max;
mas->offset = mas_data_end(mas);
if (unlikely(mte_dead_node(mas->node)))
return 1;
return 0;
-no_entry_min:
- mas->offset = offset;
- if (offset)
- mas->min = pivots[offset - 1] + 1;
no_entry:
if (unlikely(ma_dead_node(node)))
return 1;
@@ -4614,6 +4595,76 @@ static inline int mas_prev_node(struct ma_state *mas, unsigned long min)
return 0;
}
+/*
+ * mas_prev_slot() - Get the entry in the previous slot
+ *
+ * @mas: The maple state
+ * @max: The minimum starting range
+ *
+ * Return: The entry in the previous slot which is possibly NULL
+ */
+static void *mas_prev_slot(struct ma_state *mas, unsigned long min, bool empty)
+{
+ void *entry;
+ void __rcu **slots;
+ unsigned long pivot;
+ enum maple_type type;
+ unsigned long *pivots;
+ struct maple_node *node;
+ unsigned long save_point = mas->index;
+
+retry:
+ node = mas_mn(mas);
+ type = mte_node_type(mas->node);
+ pivots = ma_pivots(node, type);
+ if (unlikely(mas_rewalk_if_dead(mas, node, save_point)))
+ goto retry;
+
+again:
+ if (mas->min <= min) {
+ pivot = mas_safe_min(mas, pivots, mas->offset);
+
+ if (unlikely(mas_rewalk_if_dead(mas, node, save_point)))
+ goto retry;
+
+ if (pivot <= min)
+ return NULL;
+ }
+
+ if (likely(mas->offset)) {
+ mas->offset--;
+ mas->last = mas->index - 1;
+ mas->index = mas_safe_min(mas, pivots, mas->offset);
+ } else {
+ if (mas_prev_node(mas, min)) {
+ mas_rewalk(mas, save_point);
+ goto retry;
+ }
+
+ if (mas_is_none(mas))
+ return NULL;
+
+ mas->last = mas->max;
+ node = mas_mn(mas);
+ type = mte_node_type(mas->node);
+ pivots = ma_pivots(node, type);
+ mas->index = pivots[mas->offset - 1] + 1;
+ }
+
+ slots = ma_slots(node, type);
+ entry = mas_slot(mas, slots, mas->offset);
+ if (unlikely(mas_rewalk_if_dead(mas, node, save_point)))
+ goto retry;
+
+ if (likely(entry))
+ return entry;
+
+ if (!empty)
+ goto again;
+
+ return entry;
+}
+
/*
* mas_next_node() - Get the next node at the same level in the tree.
* @mas: The maple state
@@ -4798,109 +4849,6 @@ static inline void *mas_next_entry(struct ma_state *mas, unsigned long limit)
return mas_next_slot(mas, limit, false);
}
-/*
- * mas_prev_nentry() - Get the previous node entry.
- * @mas: The maple state.
- * @limit: The lower limit to check for a value.
- *
- * Return: the entry, %NULL otherwise.
- */
-static inline void *mas_prev_nentry(struct ma_state *mas, unsigned long limit,
- unsigned long index)
-{
- unsigned long pivot, min;
- unsigned char offset, count;
- struct maple_node *mn;
- enum maple_type mt;
- unsigned long *pivots;
- void __rcu **slots;
- void *entry;
-
-retry:
- if (!mas->offset)
- return NULL;
-
- mn = mas_mn(mas);
- mt = mte_node_type(mas->node);
- offset = mas->offset - 1;
- slots = ma_slots(mn, mt);
- pivots = ma_pivots(mn, mt);
- count = ma_data_end(mn, mt, pivots, mas->max);
- if (unlikely(mas_rewalk_if_dead(mas, mn, index)))
- goto retry;
-
- offset = mas->offset - 1;
- if (offset >= mt_slots[mt])
- offset = mt_slots[mt] - 1;
-
- if (offset >= count) {
- pivot = mas->max;
- offset = count;
- } else {
- pivot = pivots[offset];
- }
-
- if (unlikely(mas_rewalk_if_dead(mas, mn, index)))
- goto retry;
-
- while (offset && !mas_slot(mas, slots, offset)) {
- pivot = pivots[--offset];
- if (pivot >= limit)
- break;
- }
-
- /*
- * If the slot was null but we've shifted outside the limits, then set
- * the range to the last NULL.
- */
- if (unlikely((pivot < limit) && (offset < mas->offset)))
- pivot = pivots[++offset];
-
- min = mas_safe_min(mas, pivots, offset);
- entry = mas_slot(mas, slots, offset);
- if (unlikely(mas_rewalk_if_dead(mas, mn, index)))
- goto retry;
-
- mas->offset = offset;
- mas->last = pivot;
- mas->index = min;
- return entry;
-}
-
-static inline void *mas_prev_entry(struct ma_state *mas, unsigned long min)
-{
- void *entry;
- struct maple_enode *prev_enode;
- unsigned char prev_offset;
-
- if (mas->index < min)
- return NULL;
-
-retry:
- prev_enode = mas->node;
- prev_offset = mas->offset;
- while (likely(!mas_is_none(mas))) {
- entry = mas_prev_nentry(mas, min, mas->index);
-
- if (likely(entry))
- return entry;
-
- if (unlikely(mas->index <= min))
- return NULL;
-
- if (unlikely(mas_prev_node(mas, min))) {
- mas_rewalk(mas, mas->index);
- goto retry;
- }
-
- mas->offset++;
- }
-
- mas->node = prev_enode;
- mas->offset = prev_offset;
- return NULL;
-}
-
/*
* mas_rev_awalk() - Internal function. Reverse allocation walk. Find the
* highest gap address of a given size in a given node and descend.
@@ -6017,7 +5965,7 @@ void *mas_prev(struct ma_state *mas, unsigned long min)
}
return NULL;
}
- return mas_prev_entry(mas, min);
+ return mas_prev_slot(mas, min, false);
none:
mas->node = MAS_NONE;
@@ -6232,8 +6180,8 @@ void *mas_find_rev(struct ma_state *mas, unsigned long min)
if (mas->index < min)
return NULL;
- /* Retries on dead nodes handled by mas_prev_entry */
- return mas_prev_entry(mas, min);
+ /* Retries on dead nodes handled by mas_prev_slot */
+ return mas_prev_slot(mas, min, false);
none:
mas->node = MAS_NONE;
--
2.39.2
next prev parent reply other threads:[~2023-05-18 18:44 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-18 14:55 [PATCH v4 00/35] Maple tree mas_{next,prev}_range() and cleanup Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 01/35] maple_tree: Fix static analyser cppcheck issue Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 02/35] maple_tree: Clean up mas_parent_enum() and rename to mas_parent_type() Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 03/35] maple_tree: Avoid unnecessary ascending Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 04/35] maple_tree: Clean up mas_dfs_postorder() Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 05/35] maple_tree: Add format option to mt_dump() Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 06/35] maple_tree: Add debug BUG_ON and WARN_ON variants Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 07/35] maple_tree: Convert BUG_ON() to MT_BUG_ON() Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 08/35] maple_tree: Change RCU checks to WARN_ON() instead of BUG_ON() Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 09/35] maple_tree: Convert debug code to use MT_WARN_ON() and MAS_WARN_ON() Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 10/35] maple_tree: Use MAS_BUG_ON() when setting a leaf node as a parent Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 11/35] maple_tree: Use MAS_BUG_ON() in mas_set_height() Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 12/35] maple_tree: Use MAS_BUG_ON() from mas_topiary_range() Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 13/35] maple_tree: Use MAS_WR_BUG_ON() in mas_store_prealloc() Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 14/35] maple_tree: Use MAS_BUG_ON() prior to calling mas_meta_gap() Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 15/35] maple_tree: Return error on mte_pivots() out of range Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 16/35] maple_tree: Make test code work without debug enabled Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 17/35] mm: Update validate_mm() to use vma iterator Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 18/35] mm: Update vma_iter_store() to use MAS_WARN_ON() Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 19/35] maple_tree: Add __init and __exit to test module Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 20/35] maple_tree: Remove unnecessary check from mas_destroy() Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 21/35] maple_tree: mas_start() reset depth on dead node Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 22/35] mm/mmap: Change do_vmi_align_munmap() for maple tree iterator changes Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 23/35] maple_tree: Try harder to keep active node after mas_next() Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 24/35] maple_tree: Try harder to keep active node with mas_prev() Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 25/35] maple_tree: Revise limit checks in mas_empty_area{_rev}() Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 26/35] maple_tree: Fix testing mas_empty_area() Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 27/35] maple_tree: Introduce mas_next_slot() interface Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 28/35] maple_tree: Add mas_next_range() and mas_find_range() interfaces Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 29/35] maple_tree: Relocate mas_rewalk() and mas_rewalk_if_dead() Liam R. Howlett
2023-05-18 14:55 ` Liam R. Howlett [this message]
2023-05-18 14:55 ` [PATCH v4 31/35] maple_tree: Add mas_prev_range() and mas_find_range_rev interface Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 32/35] maple_tree: Clear up index and last setting in single entry tree Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 33/35] maple_tree: Update testing code for mas_{next,prev,walk} Liam R. Howlett
2023-07-02 18:20 ` Geert Uytterhoeven
2023-07-04 15:11 ` Peng Zhang
2023-07-04 15:22 ` Liam R. Howlett
2023-07-07 19:28 ` Liam R. Howlett
2023-07-10 15:03 ` Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 34/35] mm: Add vma_iter_{next,prev}_range() to vma iterator Liam R. Howlett
2023-05-18 14:55 ` [PATCH v4 35/35] mm: Avoid rewalk in mmap_region Liam R. Howlett
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230518145544.1722059-31-Liam.Howlett@oracle.com \
--to=liam.howlett@oracle.com \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=maple-tree@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox