FROMGIT: maple_tree: try harder to keep active node after mas_next()
Clean up the mas_next() call to try and keep a node reference when possible. This will avoid re-walking the tree in most cases. Also clean up the single entry tree handling to ensure index/last are consistent with what one would expect. (returning NULL with limit of 1-oo). Link: https://lkml.kernel.org/r/20230518145544.1722059-24-Liam.Howlett@oracle.com Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com> Cc: David Binderman <dcb314@hotmail.com> Cc: Peng Zhang <zhangpeng.00@bytedance.com> Cc: Sergey Senozhatsky <senozhatsky@chromium.org> Cc: Vernon Yang <vernon2gm@gmail.com> Cc: Wei Yang <richard.weiyang@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> (cherry picked from commit f7741cbb138e4cd8586e45806313561cec44f9b6 git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm mm-unstable) Bug: 274059236 Change-Id: I61c7e9e1575b5f5400f9fc2eec08ae4a1eaefa5e Signed-off-by: Suren Baghdasaryan <surenb@google.com>
This commit is contained in:
parent
5ff9438fe1
commit
cb6d9fa6ad
1 changed files with 48 additions and 43 deletions
|
|
@ -4754,33 +4754,25 @@ static inline void *mas_next_nentry(struct ma_state *mas,
|
||||||
if (ma_dead_node(node))
|
if (ma_dead_node(node))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
mas->last = pivot;
|
||||||
if (entry)
|
if (entry)
|
||||||
goto found;
|
return entry;
|
||||||
|
|
||||||
if (pivot >= max)
|
if (pivot >= max)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (pivot >= mas->max)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
mas->index = pivot + 1;
|
mas->index = pivot + 1;
|
||||||
mas->offset++;
|
mas->offset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mas->index > mas->max) {
|
pivot = mas_logical_pivot(mas, pivots, mas->offset, type);
|
||||||
mas->index = mas->last;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pivot = mas_safe_pivot(mas, pivots, mas->offset, type);
|
|
||||||
entry = mas_slot(mas, slots, mas->offset);
|
entry = mas_slot(mas, slots, mas->offset);
|
||||||
if (ma_dead_node(node))
|
if (ma_dead_node(node))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!pivot)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (!entry)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
found:
|
|
||||||
mas->last = pivot;
|
mas->last = pivot;
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
@ -4813,21 +4805,15 @@ retry:
|
||||||
static inline void *mas_next_entry(struct ma_state *mas, unsigned long limit)
|
static inline void *mas_next_entry(struct ma_state *mas, unsigned long limit)
|
||||||
{
|
{
|
||||||
void *entry = NULL;
|
void *entry = NULL;
|
||||||
struct maple_enode *prev_node;
|
|
||||||
struct maple_node *node;
|
struct maple_node *node;
|
||||||
unsigned char offset;
|
|
||||||
unsigned long last;
|
unsigned long last;
|
||||||
enum maple_type mt;
|
enum maple_type mt;
|
||||||
|
|
||||||
if (mas->index > limit) {
|
if (mas->last >= limit)
|
||||||
mas->index = mas->last = limit;
|
|
||||||
mas_pause(mas);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
last = mas->last;
|
last = mas->last;
|
||||||
retry:
|
retry:
|
||||||
offset = mas->offset;
|
|
||||||
prev_node = mas->node;
|
|
||||||
node = mas_mn(mas);
|
node = mas_mn(mas);
|
||||||
mt = mte_node_type(mas->node);
|
mt = mte_node_type(mas->node);
|
||||||
mas->offset++;
|
mas->offset++;
|
||||||
|
|
@ -4846,12 +4832,10 @@ retry:
|
||||||
if (likely(entry))
|
if (likely(entry))
|
||||||
return entry;
|
return entry;
|
||||||
|
|
||||||
if (unlikely((mas->index > limit)))
|
if (unlikely((mas->last >= limit)))
|
||||||
break;
|
return NULL;
|
||||||
|
|
||||||
next_node:
|
next_node:
|
||||||
prev_node = mas->node;
|
|
||||||
offset = mas->offset;
|
|
||||||
if (unlikely(mas_next_node(mas, node, limit))) {
|
if (unlikely(mas_next_node(mas, node, limit))) {
|
||||||
mas_rewalk(mas, last);
|
mas_rewalk(mas, last);
|
||||||
goto retry;
|
goto retry;
|
||||||
|
|
@ -4861,9 +4845,6 @@ next_node:
|
||||||
mt = mte_node_type(mas->node);
|
mt = mte_node_type(mas->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
mas->index = mas->last = limit;
|
|
||||||
mas->offset = offset;
|
|
||||||
mas->node = prev_node;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5998,6 +5979,8 @@ EXPORT_SYMBOL_GPL(mas_expected_entries);
|
||||||
*/
|
*/
|
||||||
void *mas_next(struct ma_state *mas, unsigned long max)
|
void *mas_next(struct ma_state *mas, unsigned long max)
|
||||||
{
|
{
|
||||||
|
bool was_none = mas_is_none(mas);
|
||||||
|
|
||||||
if (mas_is_none(mas) || mas_is_paused(mas))
|
if (mas_is_none(mas) || mas_is_paused(mas))
|
||||||
mas->node = MAS_START;
|
mas->node = MAS_START;
|
||||||
|
|
||||||
|
|
@ -6005,16 +5988,16 @@ void *mas_next(struct ma_state *mas, unsigned long max)
|
||||||
mas_walk(mas); /* Retries on dead nodes handled by mas_walk */
|
mas_walk(mas); /* Retries on dead nodes handled by mas_walk */
|
||||||
|
|
||||||
if (mas_is_ptr(mas)) {
|
if (mas_is_ptr(mas)) {
|
||||||
if (!mas->index) {
|
if (was_none && mas->index == 0) {
|
||||||
mas->index = 1;
|
mas->index = mas->last = 0;
|
||||||
mas->last = ULONG_MAX;
|
return mas_root(mas);
|
||||||
}
|
}
|
||||||
|
mas->index = 1;
|
||||||
|
mas->last = ULONG_MAX;
|
||||||
|
mas->node = MAS_NONE;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mas->last == ULONG_MAX)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Retries on dead nodes handled by mas_next_entry */
|
/* Retries on dead nodes handled by mas_next_entry */
|
||||||
return mas_next_entry(mas, max);
|
return mas_next_entry(mas, max);
|
||||||
}
|
}
|
||||||
|
|
@ -6138,17 +6121,25 @@ EXPORT_SYMBOL_GPL(mas_pause);
|
||||||
*/
|
*/
|
||||||
void *mas_find(struct ma_state *mas, unsigned long max)
|
void *mas_find(struct ma_state *mas, unsigned long max)
|
||||||
{
|
{
|
||||||
if (unlikely(mas_is_paused(mas))) {
|
if (unlikely(mas_is_none(mas))) {
|
||||||
if (unlikely(mas->last == ULONG_MAX)) {
|
if (unlikely(mas->last >= max))
|
||||||
mas->node = MAS_NONE;
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
mas->index = mas->last;
|
||||||
|
mas->node = MAS_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(mas_is_paused(mas))) {
|
||||||
|
if (unlikely(mas->last >= max))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
mas->node = MAS_START;
|
mas->node = MAS_START;
|
||||||
mas->index = ++mas->last;
|
mas->index = ++mas->last;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(mas_is_none(mas)))
|
|
||||||
mas->node = MAS_START;
|
if (unlikely(mas_is_ptr(mas)))
|
||||||
|
goto ptr_out_of_range;
|
||||||
|
|
||||||
if (unlikely(mas_is_start(mas))) {
|
if (unlikely(mas_is_start(mas))) {
|
||||||
/* First run or continue */
|
/* First run or continue */
|
||||||
|
|
@ -6160,13 +6151,27 @@ void *mas_find(struct ma_state *mas, unsigned long max)
|
||||||
entry = mas_walk(mas);
|
entry = mas_walk(mas);
|
||||||
if (entry)
|
if (entry)
|
||||||
return entry;
|
return entry;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!mas_searchable(mas)))
|
if (unlikely(!mas_searchable(mas))) {
|
||||||
|
if (unlikely(mas_is_ptr(mas)))
|
||||||
|
goto ptr_out_of_range;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mas->index == max)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Retries on dead nodes handled by mas_next_entry */
|
/* Retries on dead nodes handled by mas_next_entry */
|
||||||
return mas_next_entry(mas, max);
|
return mas_next_entry(mas, max);
|
||||||
|
|
||||||
|
ptr_out_of_range:
|
||||||
|
mas->node = MAS_NONE;
|
||||||
|
mas->index = 1;
|
||||||
|
mas->last = ULONG_MAX;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mas_find);
|
EXPORT_SYMBOL_GPL(mas_find);
|
||||||
|
|
||||||
|
|
@ -6597,7 +6602,7 @@ retry:
|
||||||
if (entry)
|
if (entry)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
while (mas_searchable(&mas) && (mas.index < max)) {
|
while (mas_searchable(&mas) && (mas.last < max)) {
|
||||||
entry = mas_next_entry(&mas, max);
|
entry = mas_next_entry(&mas, max);
|
||||||
if (likely(entry && !xa_is_zero(entry)))
|
if (likely(entry && !xa_is_zero(entry)))
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue