]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
maple_tree: Detangle part 1 of many
authorLiam R. Howlett <Liam.Howlett@oracle.com>
Thu, 16 Sep 2021 15:04:39 +0000 (11:04 -0400)
committerLiam R. Howlett <Liam.Howlett@oracle.com>
Thu, 16 Sep 2021 15:04:39 +0000 (11:04 -0400)
Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
lib/maple_tree.c

index 820285e3b4327ce23d7fbba899912d90739e637f..27d61ce2b4f6c420352b9cf30c6256dfd4fd24a8 100644 (file)
@@ -3917,16 +3917,6 @@ static inline bool mas_slot_store(struct ma_state *mas, void *entry,
        unsigned long lmax; /* Logical max. */
        unsigned char offset = mas->offset;
 
-       if (min == mas->index && max == mas->last) {
-               /* exact fit. */
-               rcu_assign_pointer(slots[offset], entry);
-               goto done;
-       }
-
-       /* out of room. */
-       if (unlikely(offset + 1 >= mt_slots[mt]))
-               return false;
-
        if (max > mas->last) {
                if ((min != mas->index) || (offset != end))
                        goto try_node_store;
@@ -3998,13 +3988,16 @@ try_node_store:
  */
 static inline void *_mas_store(struct ma_state *mas, void *entry, bool overwrite)
 {
-       unsigned long r_max, r_min;
+       unsigned long r_max, r_min; /* Ranges */
+       unsigned long end_piv;
        unsigned char end, zero;
        void *content = NULL;
        struct maple_big_node b_node;
        void __rcu **slots;
        enum maple_type mt;
        struct maple_node *node;
+       unsigned long *pivots;
+       unsigned char offset_end;
 
        int ret = 0;
 
@@ -4039,32 +4032,36 @@ static inline void *_mas_store(struct ma_state *mas, void *entry, bool overwrite
                mas_set_err(mas, -EEXIST);
                return content;
        }
+
+       pivots = ma_pivots(node, mt);
+       offset_end = mas->offset;
+       end_piv = r_max;
+       end = mas_data_end(mas);
+       while ((mas->last > end_piv) && (offset_end < end))
+               end_piv = pivots[++offset_end];
+
+       if (mas->last > end_piv)
+               end_piv = mas->max;
+
+
        // FIXME: Try finding end offset out here and passing it through.
        // Maybe a struct for writes?
        // lmax and offset_end ?
 
        if (!entry) {
-               unsigned char offset_end = mas->offset;
+               /* Check next slot(s) if we are overwriting the end */
+               if ((mas->last == end_piv) && !slots[offset_end + 1]) {
+                       if (offset_end + 1 == end)
+                               mas->last = mas->max;
+                       else
+                               mas->last = pivots[offset_end + 1];
+               } else if ((mas->last > end_piv) && !slots[offset_end])
+                       mas->last = end_piv;
 
                if (!content) {
                        /* If this one is null, the next and prev are not */
                        mas->index = r_min;
-                       if (mas->last < r_max)
-                               mas->last = r_max;
                } else {
-                       unsigned long *pivots = ma_pivots(node, mt);
-                       unsigned long piv = r_max;
-
-                       /* Check next slot(s) if we are overwriting the end */
-                       if (mas->last >= piv) {
-                               while (mas->last >= piv && mas->last != ULONG_MAX)
-                                       piv = mas_logical_pivot(mas, pivots,
-                                                             ++offset_end, mt);
-
-                               if (!slots[offset_end])
-                                       mas->last = piv;
-                       }
-
                        /* Check prev slot if we are overwriting the start */
                        if (mas->index == r_min && mas->offset &&
                            !slots[mas->offset - 1]) {
@@ -4076,14 +4073,27 @@ static inline void *_mas_store(struct ma_state *mas, void *entry, bool overwrite
                }
        }
 
-       end = mas_data_end(mas);
-       if (mas_slot_store(mas, entry, r_min, r_max, end, content, mt, slots))
+       if (r_min == mas->index && r_max == mas->last) {
+               rcu_assign_pointer(slots[mas->offset], entry);
+               if (!!entry ^ !!content)
+                       mas_update_gap(mas);
+               return content;
+       }
+
+       if (unlikely(mas->offset + 1 >= mt_slots[mt]))
+               goto slow_path;
+
+       if ((offset_end - mas->offset <= 1) &&
+           mas_slot_store(mas, entry, r_min, r_max, end, content, mt, slots))
                return content;
+       else if ((mas->offset + 1 >= mt_slots[mt]) &&
+                mas_node_store(mas, entry, r_min, r_max, end, content, mt, slots, pivots))
+                return content;
 
        if (mas_is_err(mas))
                return content;
 
-       /* Slow path. */
+slow_path:
        b_node.type = mte_node_type(mas->node);
        b_node.b_end = mas_store_b_node(mas, &b_node, entry, end);
        b_node.min = mas->min;