From: Liam R. Howlett Date: Fri, 19 Jul 2024 20:25:02 +0000 (-0400) Subject: maple_tree: Use mas_topiary_subtree() in mas_topiary_replace() X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=6d92df6a2b51f23e07731ee02f495788e954a68c;p=users%2Fjedix%2Flinux-maple.git maple_tree: Use mas_topiary_subtree() in mas_topiary_replace() Instead of building a linked list of subtrees to later destroy, do the destroy once a subtree is identified as replaced. This will evict the readers sooner from the dead subtree, but since the common ancestor is already marked as dead, the transition to the new data will still occur giving the readers a consistent view of either old or new data. The readers will not be able to transition back from new to old data. Signed-off-by: Liam R. Howlett --- diff --git a/lib/maple_tree.c b/lib/maple_tree.c index 8f4044e39852..7128da25a4ff 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -933,52 +933,6 @@ static inline void ma_set_meta_gap(struct maple_node *mn, enum maple_type mt, meta->gap = offset; } -/* - * mat_add() - Add a @dead_enode to the ma_topiary of a list of dead nodes. - * @mat: the ma_topiary, a linked list of dead nodes. - * @dead_enode: the node to be marked as dead and added to the tail of the list - * - * Add the @dead_enode to the linked list in @mat. - */ -static inline void mat_add(struct ma_topiary *mat, - struct maple_enode *dead_enode) -{ - mte_set_node_dead(dead_enode); - mte_to_mat(dead_enode)->next = NULL; - if (!mat->tail) { - mat->tail = mat->head = dead_enode; - return; - } - - mte_to_mat(mat->tail)->next = dead_enode; - mat->tail = dead_enode; -} - -static void mt_free_walk(struct rcu_head *head); -static void mt_destroy_walk(struct maple_enode *enode, struct maple_tree *mt, - bool free); -/* - * mas_mat_destroy() - Free all nodes and subtrees in a dead list. - * @mas: the maple state - * @mat: the ma_topiary linked list of dead nodes to free. - * - * Destroy walk a dead list. - */ -static void mas_mat_destroy(struct ma_state *mas, struct ma_topiary *mat) -{ - struct maple_enode *next; - struct maple_node *node; - bool in_rcu = mt_in_rcu(mas->tree); - - while (mat->head) { - next = mte_to_mat(mat->head)->next; - node = mte_to_node(mat->head); - mt_destroy_walk(mat->head, mas->tree, !in_rcu); - if (in_rcu) - call_rcu(&node->rcu, mt_free_walk); - mat->head = next; - } -} /* * mas_descend() - Descend into the slot stored in the ma_state. * @mas: the maple state. @@ -1982,6 +1936,30 @@ void spanning_sib(struct ma_wr_state *l_wr_mas, WARN_ON_ONCE(1); } +static void mt_free_walk(struct rcu_head *head); +static void mt_destroy_walk(struct maple_enode *enode, struct maple_tree *mt, + bool free); +/* + * mas_topiary_subtree() - Dispose of a subtree + * @mas: The maple state for pushing nodes + * @tmp_mas: The temporary maple state + * @in_rcu: If the tree is in rcu mode + * + * The node will either be RCU freed or pushed back on the maple state. + */ +static inline void mas_topiary_subtree(struct ma_state *mas, + struct ma_state *tmp_mas, bool in_rcu) +{ + struct maple_node *tmp; + struct maple_enode *enode; + + enode = tmp_mas->node; + tmp = mte_to_node(enode); + mt_destroy_walk(enode, mas->tree, !in_rcu); + if (in_rcu) + call_rcu(&tmp->rcu, mt_free_walk); +} + /* * mas_topiary_node() - Dispose of a single node * @mas: The maple state for pushing nodes @@ -2030,7 +2008,6 @@ static inline void mas_topiary_replace(struct ma_state *mas, struct maple_enode *old_enode, unsigned char new_height) { struct ma_state tmp[3], tmp_next[3]; - MA_TOPIARY(subtrees, mas->tree); bool in_rcu; int i, n; @@ -2089,7 +2066,8 @@ static inline void mas_topiary_replace(struct ma_state *mas, if ((tmp_next[n].min >= tmp_next->index) && (tmp_next[n].max <= tmp_next->last)) { - mat_add(&subtrees, tmp_next[n].node); + mas_topiary_subtree(mas, &tmp_next[n], + in_rcu); tmp_next[n].status = ma_none; } else { n++; @@ -2111,8 +2089,6 @@ static inline void mas_topiary_replace(struct ma_state *mas, for (i = 0; i < 3; i++) mas_topiary_node(mas, &tmp[i], in_rcu); - - mas_mat_destroy(mas, &subtrees); } static inline void *mtree_range_walk(struct ma_state *mas)