]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
maple_tree: Add in_rcu flag support
authorLiam R. Howlett <Liam.Howlett@Oracle.com>
Fri, 28 Aug 2020 19:31:00 +0000 (15:31 -0400)
committerLiam R. Howlett <Liam.Howlett@Oracle.com>
Fri, 30 Oct 2020 19:09:31 +0000 (15:09 -0400)
Signed-off-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
include/linux/maple_tree.h
lib/maple_tree.c
lib/test_maple_tree.c

index acb218c1387101ecada99228acff03bd2fa0d7da..9e94d1d277c0f31b726bbcf1d3e1ccd93d0271d1 100644 (file)
@@ -442,6 +442,32 @@ static inline void mt_init(struct maple_tree *mt)
        mt_init_flags(mt, 0);
 }
 
+/**
+ * mt_clear_in_rcu() - Switch the tree to non-RCU mode.
+ */
+static inline void mt_clear_in_rcu(struct maple_tree *mt)
+{
+       if ((mt->ma_flags & MAPLE_USE_RCU) == 0)
+               return;
+
+       mtree_lock(mt);
+       mt->ma_flags &= ~MAPLE_USE_RCU;
+       mtree_unlock(mt);
+}
+
+/**
+ * mt_set_in_rcu() - Switch the tree to RCU safe mode.
+ */
+static inline void mt_set_in_rcu(struct maple_tree *mt)
+{
+       if (mt->ma_flags & MAPLE_USE_RCU)
+               return;
+
+       mtree_lock(mt);
+       mt->ma_flags |= MAPLE_USE_RCU;
+       mtree_unlock(mt);
+}
+
 void *mt_find(struct maple_tree *mt, unsigned long *index, unsigned long max);
 void *_mt_find(struct maple_tree *mt, unsigned long *index, unsigned long max,
                bool start);
index d4ffcd4b15501db3717f9180f4272d310502d245..7d3a85fa3711ec4e81180adff59fa15fd701ceaa 100644 (file)
@@ -147,6 +147,11 @@ static unsigned int mt_height(const struct maple_tree *mt)
        return (mt->ma_flags & MAPLE_HEIGHT_MASK) >> MAPLE_HEIGHT_OFFSET;
 }
 
+static bool mas_in_rcu(struct ma_state *mas)
+{
+       return mas->tree->ma_flags & MAPLE_USE_RCU;
+}
+
 static void mas_set_height(struct ma_state *mas)
 {
        unsigned int new_flags = mas->tree->ma_flags;
@@ -2651,8 +2656,34 @@ static inline int mas_cnt_positive(struct ma_state *mas)
                return mas->full_cnt * -1;
        return mas->full_cnt;
 }
+static inline bool mas_reuse_node(struct ma_state *mas,
+                                 struct maple_big_node *bn,
+                                 unsigned char end)
+{
+       int i;
+
+       if (mas_in_rcu(mas))
+               return false; // Need to be rcu safe.
+
+       mab_mas_cp(bn, 0, bn->b_end, mas);
+
+       if (end > bn->b_end) {
+               for (i = bn->b_end + 1; i < mt_slot_count(mas->node); i++) {
+                       mte_set_rcu_slot(mas->node, i, NULL);
+                       if (i < mt_pivot_count(mas->node))
+                               mte_set_pivot(mas->node, i, 0);
+
+                       //if (!mte_is_leaf(mas->node) && mt_is_alloc(mas->tree))
+                       //      mte_set_gap(mas->node, j, b_node->gap[i]);
+               }
+
+       }
+       return true;
+
+}
 static inline int mas_commit_b_node(struct ma_state *mas,
-                                   struct maple_big_node *b_node)
+                                   struct maple_big_node *b_node,
+                                   unsigned char end)
 {
        struct maple_enode *new_node;
 
@@ -2669,6 +2700,9 @@ static inline int mas_commit_b_node(struct ma_state *mas,
                return mas_split(mas, b_node);
        }
 
+       if (mas_reuse_node(mas, b_node, end))
+               goto reused_node;
+
        mas_node_cnt(mas, 1);
        if (mas_is_err(mas))
                return 0;
@@ -2679,6 +2713,7 @@ static inline int mas_commit_b_node(struct ma_state *mas,
 
        mab_mas_cp(b_node, 0, b_node->b_end, mas);
        mas_replace(mas, false);
+reused_node:
        mas_update_gap(mas);
        return 2;
 
@@ -3187,7 +3222,7 @@ static inline void *_mas_store(struct ma_state *mas, void *entry, bool overwrite
        else if (b_node.b_end < mt_min_slot_cnt(mas->node))
                mas_cnt_empty(mas);
 
-       if (!mas_commit_b_node(mas, &b_node))
+       if (!mas_commit_b_node(mas, &b_node, end))
                return NULL;
 
        if (ret > 2)
index cb1815287798e59e0e15737371d96c91d48446ca..8a87a161c68db4c9ff355732ee941b4a543276cc 100644 (file)
@@ -677,6 +677,7 @@ static noinline void check_erase_testset(struct maple_tree *mt)
        void *root_node;
 
 
+       mt_set_in_rcu(mt);
        for (int i = 0; i < 4; i++)
                erase_check_insert(mt, i);
        for (int i = 0; i < 4; i++)
@@ -32335,9 +32336,11 @@ static int maple_tree_seed(void)
        mtree_init(&tree, 0);
        check_seq(&tree, 16, false);
        mtree_destroy(&tree);
+
        mtree_init(&tree, 0);
        check_seq(&tree, 1000, true);
        mtree_destroy(&tree);
+
        mtree_init(&tree, MAPLE_ALLOC_RANGE);
        check_rev_seq(&tree, 1000, true);
        mtree_destroy(&tree);