From 7fa5b0ef09efa8fbc42414b8ead96608b43d8cdf Mon Sep 17 00:00:00 2001 From: "Liam R. Howlett" Date: Tue, 25 Aug 2020 13:56:13 -0400 Subject: [PATCH] maple_tree: Alloc at most 1 page of nodes during fork. Also fix a corner case of root + children being 17 and thus failing out during a fork Signed-off-by: Liam R. Howlett --- include/linux/maple_tree.h | 2 ++ lib/maple_tree.c | 13 +++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/include/linux/maple_tree.h b/include/linux/maple_tree.h index 105731e081e3..20cb7c6cf4d7 100644 --- a/include/linux/maple_tree.h +++ b/include/linux/maple_tree.h @@ -37,6 +37,7 @@ #define MAPLE_SPARSE16_SLOTS 24 /* 248 bytes */ #define MAPLE_SPARSE9_SLOTS 27 /* 256 bytes */ #define MAPLE_SPARSE6_SLOTS 30 /* 256 bytes */ +#define MA_NODE_PER_PAGE 16 #else #define MAPLE_NODE_SLOTS 15 /* 128 bytes including ->parent */ #define MAPLE_RANGE64_SLOTS 8 /* 128 bytes */ @@ -49,6 +50,7 @@ #define MAPLE_SPARSE16_SLOTS 12 /* 128 bytes */ #define MAPLE_SPARSE9_SLOTS 13 /* 127 bytes */ #define MAPLE_SPARSE6_SLOTS 14 /* 128 bytes */ +#define MA_NODE_PER_PAGE 32 #endif // End NODE256 #else diff --git a/lib/maple_tree.c b/lib/maple_tree.c index 0d15a5cc99fa..6733ab06e13f 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -22,9 +22,6 @@ #define ma_parent_ptr(x) ((struct maple_pnode *)(x)) #define ma_mnode_ptr(x) ((struct maple_node *)(x)) #define ma_enode_ptr(x) ((struct maple_enode *)(x)) -#undef XA_RETRY_ENTRY -#undef XA_SKIP_ENTRY -#undef XA_DELETED_ENTRY static struct kmem_cache *maple_node_cache; @@ -572,6 +569,7 @@ static inline struct maple_enode *ma_get_rcu_slot( const struct maple_node *mn, unsigned char slot, enum maple_type type, struct maple_tree *mtree) { + switch (type) { case maple_range_64: case maple_leaf_64: @@ -4357,7 +4355,7 @@ static inline struct maple_enode *mas_dup_node(struct ma_state *oldmas, static inline void mas_dup_alloc(struct ma_state *mas, int *node_cnt) { - int alloc_cnt = min(*node_cnt, 127); + int alloc_cnt = min(*node_cnt, MA_NODE_PER_PAGE); /* Allocate nodes for new tree. Maximum will be 16 ** height */ *node_cnt -= alloc_cnt; mas_node_cnt(mas, alloc_cnt); @@ -4411,6 +4409,9 @@ static inline void mas_dup_tree_start(struct ma_state *oldmas, struct ma_state *mas, int *node_cnt) { + if (xa_is_node(mas->tree->ma_root)) + goto dup_children; + if (mas->alloc) goto allocated; @@ -4435,8 +4436,12 @@ allocated: mte_to_node(mas->node)->parent = ma_parent_ptr( ((unsigned long)mas->tree | MA_ROOT_PARENT)); rcu_assign_pointer(mas->tree->ma_root, mte_mk_root(mas->node)); + +dup_children: if (!mte_is_leaf(oldmas->node)) { mas_dup_children(mas, node_cnt); + if (mas_is_err(mas)) + return; mas_adopt_children(mas, mas->node); } } -- 2.50.1