From: Liam R. Howlett <Liam.Howlett@Oracle.com>
Date: Fri, 4 Dec 2020 02:56:45 +0000 (-0500)
Subject: maple_tree: Add append operation
X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=0e77d768d80150e6c0f6324e64b7201f5c7606c4;p=users%2Fjedix%2Flinux-maple.git

maple_tree: Add append operation

Signed-off-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
---

diff --git a/lib/maple_tree.c b/lib/maple_tree.c
index 6b893447e2a7..a67bc3ea1e96 100644
--- a/lib/maple_tree.c
+++ b/lib/maple_tree.c
@@ -3216,6 +3216,45 @@ static inline int mas_spanning_store(struct ma_state *mas, void *entry)
 	return mas_spanning_rebalance(mas, &mast, height + 1);
 }
 
+static inline bool mas_append(struct ma_state *mas, void *entry,
+			      unsigned long min, unsigned char end,
+			      void *content, enum maple_type mt)
+{
+	void **slots = ma_slots(mas_mn(mas), mt);
+	unsigned long *pivots = ma_pivots(mas_mn(mas), mt);
+	unsigned char new_end;
+	unsigned char max_slots = mt_slots[mt];
+
+	/* slot store would happen if the last entry wasn't being split, so add
+	 * one.
+	 */
+	new_end = end + 1;
+	//printk("store %lu - %lu| %lu %lu\n", mas->index, mas->last, min, mas->max);
+	if (min < mas->index)
+		new_end++;
+
+	if (new_end >= max_slots)
+		return false;
+
+	//printk("move last to %u\n", new_end);
+	if (new_end < max_slots - 1)
+		pivots[new_end] = pivots[end];
+	slots[new_end--] = content;
+
+	//printk("store to %u\n", new_end);
+	if (new_end < max_slots - 1)
+		pivots[new_end] = mas->last;
+	slots[new_end--] = entry;
+
+	if (min < mas->index) {
+		//printk("fix min in %u\n", new_end);
+		pivots[new_end] = mas->index - 1;
+		mas->offset++;
+	}
+
+	mas_update_gap(mas);
+	return true;
+}
 static inline bool mas_node_store(struct ma_state *mas, void *entry,
 				  unsigned long min, unsigned long max,
 				  unsigned char end, void *content,
@@ -3339,8 +3378,13 @@ static inline bool mas_slot_store(struct ma_state *mas, void *entry,
 	if (offset + 1 >= mt_slots[mt]) // out of room.
 		return false;
 
-	if (max > mas->last) // going to split a single entry.
+	if (max > mas->last){ // going to split a single entry.
+		if ((offset == end) &&
+		    mas_append(mas, entry, min, end, content, mt))
+		    return true;
+
 		goto try_node_store;
+	}
 
 	lmax = mas_logical_pivot(mas, pivots, offset + 1, mt);
 	if (lmax < mas->last) // going to overwrite too many slots.