From: Liam R. Howlett Date: Tue, 15 Oct 2019 02:40:35 +0000 (-0400) Subject: maple_tree: Fix check_find_2 testcase. X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=7ad745cc4487e5754a11c6e30594e57e85ad9346;p=users%2Fjedix%2Flinux-maple.git maple_tree: Fix check_find_2 testcase. The check_find_2 exposed issues when the tree was a simple pointer. The pointer case was not being handled correctly in mas_start, or _mas_walk. Fixing these two functions also required fixing calling functions to check for MAS_ROOT (a root pointer). There was also a bug in mas_next_entry where the next node was checked - which is not possible if it's the root node. Signed-off-by: Liam R. Howlett --- diff --git a/lib/maple_tree.c b/lib/maple_tree.c index 6f14ed658a0e..793f3e18bbf3 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -223,7 +223,7 @@ static inline bool _ma_is_root(struct maple_node *node) return ((unsigned long)node->parent & MA_ROOT_PARENT); } -static inline bool mte_is_root(struct maple_enode *node) +static inline bool mte_is_root(const struct maple_enode *node) { return _ma_is_root(mte_to_node(node)); } @@ -947,17 +947,21 @@ static inline struct maple_node *mas_node_cnt(struct ma_state *ms, int count) static inline struct maple_enode *mas_start(struct ma_state *mas) { - if (mas->node == MAS_START) { + if (mas_is_start(mas)) { + struct maple_enode *root; + mas->min = 0; + if (!mas->tree->ma_root) // empty tree. + return NULL; + if (!xa_is_node(mas->tree->ma_root)) { if (mas->index > 0) return NULL; mas->node = MAS_ROOT; mas_set_slot(mas, MAPLE_NODE_SLOTS); - return NULL; + return mas->node; } - struct maple_enode *root = mte_safe_root( - mas->tree->ma_root); + root = mte_safe_root(mas->tree->ma_root); mas->max = mt_node_max(root); return root; } @@ -2524,6 +2528,11 @@ static inline unsigned long mas_next_entry(struct ma_state *mas, if (mas_next_nentry(mas, max, &pivot)) break; + if (mte_is_root(mas->node)) { + mas->node = MAS_NONE; + break; + } + p_slot = mte_parent_slot(mas->node); mas_set_slot(mas, p_slot); mas_next_node(mas, max); @@ -3278,6 +3287,14 @@ done: static inline bool _mas_walk(struct ma_state *mas) { mas->node = mas_start(mas); + if (!mas->node) { + mas_set_slot(mas, MAPLE_NODE_SLOTS); + return false; + } + + if (mas->node == MAS_ROOT) + return true; + mas_set_slot(mas, 0); return __mas_walk(mas); } @@ -3305,6 +3322,7 @@ static inline int mas_dead_node(struct ma_state *mas, unsigned long index) { if (!mas->node) return 0; + if (!mte_dead_node(mas->node)) return 0; @@ -3339,10 +3357,16 @@ void *mas_find(struct ma_state *mas, unsigned long max) unsigned char slot = 0; if (!mas->node) - return MAS_NONE; + goto not_found; - if (mas->node == MAS_START) { + if (mas_is_start(mas)) { _mas_walk(mas); + if (!mas->node) + return NULL; + + if (mas->node == MAS_ROOT) + return mas->tree->ma_root; + do {} while (mas_dead_node(mas, mas->index)); slot = mas_get_slot(mas); @@ -3358,6 +3382,8 @@ void *mas_find(struct ma_state *mas, unsigned long max) goto done; } } + if (mas->node == MAS_ROOT) + goto not_found; last_piv = mas_safe_next_entry(mas, max); if (mas->node == MAS_NONE) @@ -3416,6 +3442,14 @@ void *mt_find(struct maple_tree *mt, unsigned long start, rcu_read_lock(); _mas_walk(&mas); + if (!mas.node) + goto done; + + if (mas.node == MAS_ROOT) { + entry = mas.tree->ma_root; + goto done; + } + do {} while (mas_dead_node(&mas, mas.index)); slot = mas_get_slot(&mas); @@ -3461,6 +3495,13 @@ void *mt_find_after(struct maple_tree *mt, unsigned long *index, rcu_read_lock(); _mas_walk(&mas); + if (!mas.node) + goto done; + + if (mas.node == MAS_ROOT) { + entry = mas.tree->ma_root; + goto done; + } retry: mas_set_slot(&mas, mas_get_slot(&mas) + 1); mas_safe_next_entry(&mas, max); @@ -3655,6 +3696,10 @@ static inline void mas_rev_awalk(struct ma_state *mas, unsigned long size) unsigned char slot, coalesce; mas->node = mas_start(mas); + if (!mas->node) { + mas_set_slot(mas, MAPLE_NODE_SLOTS); + return; + } slot = mas_data_end(mas, mte_node_type(mas->node), &last_piv, &coalesce); mas_set_slot(mas, slot); @@ -3678,6 +3723,9 @@ static inline void mas_awalk(struct ma_state *mas, unsigned long size) struct maple_enode *last = NULL; mas->node = mas_start(mas); + if (!mas->node) + return; + mas_set_slot(mas, 0); /* There are 4 options: @@ -3789,6 +3837,11 @@ static inline int ma_alloc(struct ma_state *mas, void *entry, unsigned long min; mas->node = mas_start(mas); + if (!mas->node) { + slot = 0; + goto empty_tree; + } + if (!xa_is_node(rcu_dereference(mas->tree->ma_root))) { ma_root_expand(mas, entry); if (!mas->index) @@ -3797,6 +3850,8 @@ static inline int ma_alloc(struct ma_state *mas, void *entry, } mas_awalk(mas, size); + // cannot be an empty tree here. + if (mas_is_err(mas)) return xa_err(mas->node); @@ -3813,6 +3868,7 @@ static inline int ma_alloc(struct ma_state *mas, void *entry, if (mas->index < min) mas->index = min; +empty_tree: return mas_fill_gap(mas, entry, slot, size, index); no_gap: @@ -3833,6 +3889,11 @@ static inline int ma_rev_alloc(struct ma_state *mas, void *entry, unsigned char slot = MAPLE_NODE_SLOTS; mas->node = mas_start(mas); + if (!mas->node) { + slot = 0; + goto empty_tree; + } + if (!xa_is_node(rcu_dereference(mas->tree->ma_root))) { ma_root_expand(mas, entry); if (!mas->index) @@ -3841,6 +3902,8 @@ static inline int ma_rev_alloc(struct ma_state *mas, void *entry, } mas_rev_awalk(mas, size); + // cannot be empty tree. + if (mas_is_err(mas)) return xa_err(mas->node); @@ -3859,6 +3922,7 @@ static inline int ma_rev_alloc(struct ma_state *mas, void *entry, mas->last = mas->index + size - 1; +empty_tree: return mas_fill_gap(mas, entry, slot, size, index); no_gap: