From: Liam R. Howlett Date: Thu, 10 Jan 2019 16:08:14 +0000 (-0500) Subject: maple_tree: Add erase support. X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=f87bbf608dce19235c5edebabaffe1872420d83e;p=users%2Fjedix%2Flinux-maple.git maple_tree: Add erase support. 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 --- diff --git a/lib/maple_tree.c b/lib/maple_tree.c index 5fa94bf2aa39..f90fd7f5b025 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -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) diff --git a/lib/test_maple_tree.c b/lib/test_maple_tree.c index 51d98a9fd06b..b3dbdcd51db2 100644 --- a/lib/test_maple_tree.c +++ b/lib/test_maple_tree.c @@ -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);