]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
maple_tree: Add erase support.
authorLiam R. Howlett <Liam.Howlett@Oracle.com>
Thu, 10 Jan 2019 16:08:14 +0000 (11:08 -0500)
committerLiam R. Howlett <Liam.Howlett@Oracle.com>
Wed, 31 Jul 2019 14:52:35 +0000 (10:52 -0400)
Refactor replacing a node in a tree to its own function and use that
with the erase and insert functions.

Erase NULLs the range in which the index resides and coalesces adjacent
NULLs if allocation succeeds.

Signed-off-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
lib/maple_tree.c
lib/test_maple_tree.c

index 5fa94bf2aa39f12dde20c52d6a6cd8362d2730f2..f90fd7f5b0255c58bea66807f6974e7bf5ae13c9 100644 (file)
@@ -555,6 +555,29 @@ bool ma_reserved(void *entry)
 
        return false;
 }
+/* Private
+ * Replace mn with mas->node in the tree
+ */
+void mt_replace(struct ma_state *mas, void *p_entry, bool leaf)
+{
+       struct maple_node *mn = mt_to_node(mas->node);
+       mn->parent = mt_to_node(p_entry)->parent;
+       if (!leaf)
+               ma_adopt_children(mn);
+
+       if (ma_is_root(p_entry)) {
+               mn->parent = (struct maple_node *)
+                             ((unsigned long)mas->tree | MA_ROOT_PARENT);
+               rcu_assign_pointer(mas->tree->ma_root, mt_mk_root(mas->node));
+       } else {
+               struct maple_node *parent = mt_parent(mn->parent);
+               unsigned char slot = mt_parent_slot(mn);
+
+               RCU_INIT_POINTER(parent->slot[slot], mas->node);
+       }
+       mt_free(mt_to_node(p_entry));
+
+}
 void *ma_insert(struct ma_state *mas, void *entry)
 {
        void *p_entry; // Previous entry.
@@ -601,22 +624,8 @@ void *ma_insert(struct ma_state *mas, void *entry)
        if (mas_is_err(mas))
                goto error;
 
-       /* Insert into tree */
-       mn->parent = mas->node->parent;
-       if (!leaf)
-               ma_adopt_children(mn);
-
-       if (ma_is_root(p_entry)) {
-               mn->parent = (struct maple_node *)
-                             ((unsigned long)mas->tree | MA_ROOT_PARENT);
-               rcu_assign_pointer(mas->tree->ma_root, mt_mk_root(mas->node));
-       } else {
-               struct maple_node *parent = mt_parent(mn->parent);
-
-               slot = mt_parent_slot(mn);
-               RCU_INIT_POINTER(parent->slot[slot], mas->node);
-       }
-       mt_free(mt_to_node(p_entry));
+       /* Replace the node in the tree */
+       mt_replace(mas, p_entry, leaf);
        return NULL;
 
 error:
@@ -670,8 +679,44 @@ void *mas_walk(struct ma_state *mas)
  */
 int ma_erase(struct ma_state *mas)
 {
-       //bool leaf = _mas_walk(mas);
-       return -EINVAL;
+       bool leaf = _mas_walk(mas);
+       int slot = ma_get_slot(mas);
+       struct maple_range_64 *mr64 = &mt_to_node(mas->node)->mr64;
+       unsigned long piv_val;
+       int cnt = -EINVAL;
+       void *p_entry; // Previous entry.
+       struct maple_node *mn;
+
+       if (slot == MAPLE_NODE_SLOTS)
+               return cnt;
+       rcu_assign_pointer(mr64->slot[slot], NULL);
+       if ((slot >= MAPLE_RANGE64_SLOTS - 1))
+               return 1;
+
+       if ((slot < MAPLE_RANGE64_SLOTS - 2) &&
+           ((mr64->pivot[slot + 1] == 0) ||
+            (mr64->slot[slot + 1] == NULL))) {
+               piv_val = mr64->pivot[++slot];
+       } else {
+               piv_val = mr64->pivot[slot];
+       }
+
+       cnt = 1;
+       /* Walk down and set all the previous pivots with NULLs to piv_val */
+       while(--slot >= 0 && mr64->slot[slot] == NULL) {
+               mr64->pivot[slot] = piv_val;
+               cnt++;
+       }
+
+       mn = mas_coalesce(mas);
+       if (mas_is_err(mas))
+               goto error;
+       p_entry = mas->node;
+       mas->node = mt_mk_node(mn, maple_leaf_64);
+       mt_replace(mas, p_entry, leaf);
+
+error:
+       return cnt;
 }
 
 void ma_destroy_walk(struct ma_state *mas)
index 51d98a9fd06b9b2ceb1fdfef2136afcbede66531..b3dbdcd51db2f5c19163962e9fec034ebc2513b4 100644 (file)
@@ -53,6 +53,11 @@ static void *mtree_test_load(struct maple_tree *mt, unsigned long index)
        return mtree_load(mt, index);
 }
 
+static int mtree_test_erase(struct maple_tree *mt, unsigned long index)
+{
+       return mtree_erase(mt, index);
+}
+
 
 static noinline void check_insert_range(struct maple_tree *mt,
                unsigned long start, unsigned long end, void *ptr)
@@ -70,6 +75,12 @@ static noinline void check_insert(struct maple_tree *mt, unsigned long index,
        MT_BUG_ON(mt, ret != 0);
 }
 
+static noinline void check_erase(struct maple_tree *mt, unsigned long index)
+{
+       int ret = -EINVAL;
+       ret = mtree_test_erase(mt, index);
+       MT_BUG_ON(mt, ret < 0);
+}
 static noinline void check_dup_insert(struct maple_tree *mt,
                                      unsigned long index, void *ptr)
 {
@@ -307,6 +318,12 @@ static int maple_tree_seed(void)
        check_insert(&tree, set[1], &tree); // 14
        check_insert(&tree, set[2], ptr); // 17
        check_insert(&tree, set[3], &tree); // 25
+       check_load(&tree, set[0], ptr);
+       check_load(&tree, set[1], &tree);
+       check_load(&tree, set[2], ptr);
+       check_load(&tree, set[3], &tree);
+       check_erase(&tree, set[1]);
+       check_load(&tree, set[1], NULL);
        return 0;
        check_insert(&tree, set[4], ptr); // 1000 < Should split.
        check_load(&tree, set[0], ptr);