maple_tree: reduce resets during store setup

JIRA: https://issues.redhat.com/browse/RHEL-27743

This patch is a backport of the following upstream commit:
commit fec29364348fec535c55708b1f4025b321aba572
Author: Liam R. Howlett <Liam.Howlett@oracle.com>
Date:   Mon Jul 24 14:31:56 2023 -0400

    maple_tree: reduce resets during store setup

    mas_prealloc() may walk partially down the tree before finding that a
    split or spanning store is needed.  When the write occurs, relax the
    logic on resetting the walk so that partial walks will not restart, but
    walks that have gone too far (a store that affects beyond the current
    node) should be restarted.

    Link: https://lkml.kernel.org/r/20230724183157.3939892-15-Liam.Howlett@oracle.com
    Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
    Cc: Peng Zhang <zhangpeng.00@bytedance.com>
    Cc: Suren Baghdasaryan <surenb@google.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

Signed-off-by: Rafael Aquini <raquini@redhat.com>
This commit is contained in:
Rafael Aquini 2024-09-27 10:44:00 -04:00
parent e096f6abaa
commit d201512b82
1 changed files with 27 additions and 12 deletions

View File

@ -5438,19 +5438,34 @@ static inline void mte_destroy_walk(struct maple_enode *enode,
static void mas_wr_store_setup(struct ma_wr_state *wr_mas)
{
if (unlikely(mas_is_paused(wr_mas->mas)))
mas_reset(wr_mas->mas);
if (mas_is_start(wr_mas->mas))
return;
if (!mas_is_start(wr_mas->mas)) {
if (mas_is_none(wr_mas->mas)) {
mas_reset(wr_mas->mas);
} else {
wr_mas->r_max = wr_mas->mas->max;
wr_mas->type = mte_node_type(wr_mas->mas->node);
if (mas_is_span_wr(wr_mas))
mas_reset(wr_mas->mas);
}
}
if (unlikely(mas_is_paused(wr_mas->mas)))
goto reset;
if (unlikely(mas_is_none(wr_mas->mas)))
goto reset;
/*
* A less strict version of mas_is_span_wr() where we allow spanning
* writes within this node. This is to stop partial walks in
* mas_prealloc() from being reset.
*/
if (wr_mas->mas->last > wr_mas->mas->max)
goto reset;
if (wr_mas->entry)
return;
if (mte_is_leaf(wr_mas->mas->node) &&
wr_mas->mas->last == wr_mas->mas->max)
goto reset;
return;
reset:
mas_reset(wr_mas->mas);
}
/* Interface */