maple_tree: reduce resets during store setup
authorLiam R. Howlett <Liam.Howlett@oracle.com>
Mon, 24 Jul 2023 18:31:56 +0000 (14:31 -0400)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 18 Aug 2023 17:12:50 +0000 (10:12 -0700)
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>
lib/maple_tree.c

index 4a111785360feff49829dc9a55117a8112a99763..a3d602cfd030290ba8dfccb39e404d094ff3a6d6 100644 (file)
@@ -5424,19 +5424,34 @@ static inline void mte_destroy_walk(struct maple_enode *enode,
 
 static void mas_wr_store_setup(struct ma_wr_state *wr_mas)
 {
+       if (mas_is_start(wr_mas->mas))
+               return;
+
        if (unlikely(mas_is_paused(wr_mas->mas)))
-               mas_reset(wr_mas->mas);
+               goto reset;
 
-       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_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 */