diff options
Diffstat (limited to 'lib/maple_tree.c')
| -rw-r--r-- | lib/maple_tree.c | 812 | 
1 files changed, 428 insertions, 384 deletions
| diff --git a/lib/maple_tree.c b/lib/maple_tree.c index aa3a5df15b8e..20990ecba2dd 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -348,17 +348,17 @@ static inline void *mte_safe_root(const struct maple_enode *node)  	return (void *)((unsigned long)node & ~MAPLE_ROOT_NODE);  } -static inline void *mte_set_full(const struct maple_enode *node) +static inline void __maybe_unused *mte_set_full(const struct maple_enode *node)  {  	return (void *)((unsigned long)node & ~MAPLE_ENODE_NULL);  } -static inline void *mte_clear_full(const struct maple_enode *node) +static inline void __maybe_unused *mte_clear_full(const struct maple_enode *node)  {  	return (void *)((unsigned long)node | MAPLE_ENODE_NULL);  } -static inline bool mte_has_null(const struct maple_enode *node) +static inline bool __maybe_unused mte_has_null(const struct maple_enode *node)  {  	return (unsigned long)node & MAPLE_ENODE_NULL;  } @@ -474,6 +474,7 @@ enum maple_type mas_parent_type(struct ma_state *mas, struct maple_enode *enode)  /*   * mas_set_parent() - Set the parent node and encode the slot + * @mas: The maple state   * @enode: The encoded maple node.   * @parent: The encoded maple node that is the parent of @enode.   * @slot: The slot that @enode resides in @parent. @@ -534,7 +535,7 @@ unsigned int mte_parent_slot(const struct maple_enode *enode)  /*   * mte_parent() - Get the parent of @node. - * @node: The encoded maple node. + * @enode: The encoded maple node.   *   * Return: The parent maple node.   */ @@ -641,8 +642,8 @@ static inline unsigned int mas_alloc_req(const struct ma_state *mas)  /*   * ma_pivots() - Get a pointer to the maple node pivots. - * @node - the maple node - * @type - the node type + * @node: the maple node + * @type: the node type   *   * In the event of a dead node, this array may be %NULL   * @@ -665,8 +666,8 @@ static inline unsigned long *ma_pivots(struct maple_node *node,  /*   * ma_gaps() - Get a pointer to the maple node gaps. - * @node - the maple node - * @type - the node type + * @node: the maple node + * @type: the node type   *   * Return: A pointer to the maple node gaps   */ @@ -880,8 +881,6 @@ static inline void ma_set_meta(struct maple_node *mn, enum maple_type mt,   * @mt: The maple tree   * @mn: The maple node   * @type: The maple node type - * @offset: The offset of the highest sub-gap in this node. - * @end: The end of the data in this node.   */  static inline void mt_clear_meta(struct maple_tree *mt, struct maple_node *mn,  				  enum maple_type type) @@ -939,7 +938,7 @@ static inline unsigned char ma_meta_gap(struct maple_node *mn)  /*   * ma_set_meta_gap() - Set the largest gap location in a nodes metadata   * @mn: The maple node - * @mn: The maple node type + * @mt: The maple node type   * @offset: The location of the largest gap.   */  static inline void ma_set_meta_gap(struct maple_node *mn, enum maple_type mt, @@ -953,8 +952,8 @@ static inline void ma_set_meta_gap(struct maple_node *mn, enum maple_type mt,  /*   * 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 + * @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.   */ @@ -977,8 +976,8 @@ 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. + * @mas: the maple state + * @mat: the ma_topiary linked list of dead nodes to free.   *   * Destroy walk a dead list.   */ @@ -999,7 +998,7 @@ static void mas_mat_destroy(struct ma_state *mas, struct ma_topiary *mat)  }  /*   * mas_descend() - Descend into the slot stored in the ma_state. - * @mas - the maple state. + * @mas: the maple state.   *   * Note: Not RCU safe, only use in write side or debug code.   */ @@ -1346,8 +1345,8 @@ static void mas_node_count(struct ma_state *mas, int count)   * Return:   * - If mas->node is an error or not mas_start, return NULL.   * - If it's an empty tree:     NULL & mas->status == ma_none - * - If it's a single entry:    The entry & mas->status == mas_root - * - If it's a tree:            NULL & mas->status == safe root node. + * - If it's a single entry:    The entry & mas->status == ma_root + * - If it's a tree:            NULL & mas->status == ma_active   */  static inline struct maple_enode *mas_start(struct ma_state *mas)  { @@ -1372,9 +1371,9 @@ retry:  			return NULL;  		} +		mas->node = NULL;  		/* empty tree */  		if (unlikely(!root)) { -			mas->node = NULL;  			mas->status = ma_none;  			mas->offset = MAPLE_NODE_SLOTS;  			return NULL; @@ -1462,7 +1461,7 @@ static inline unsigned char mas_data_end(struct ma_state *mas)  /*   * mas_leaf_max_gap() - Returns the largest gap in a leaf node - * @mas - the maple state + * @mas: the maple state   *   * Return: The maximum gap in the leaf.   */ @@ -1544,7 +1543,7 @@ static unsigned long mas_leaf_max_gap(struct ma_state *mas)   * @node: The maple node   * @gaps: The pointer to the gaps   * @mt: The maple node type - * @*off: Pointer to store the offset location of the gap. + * @off: Pointer to store the offset location of the gap.   *   * Uses the metadata data end to scan backwards across set gaps.   * @@ -1651,7 +1650,7 @@ ascend:  /*   * mas_update_gap() - Update a nodes gaps and propagate up if necessary. - * @mas - the maple state. + * @mas: the maple state.   */  static inline void mas_update_gap(struct ma_state *mas)  { @@ -1678,8 +1677,8 @@ static inline void mas_update_gap(struct ma_state *mas)  /*   * mas_adopt_children() - Set the parent pointer of all nodes in @parent to   * @parent with the slot encoded. - * @mas - the maple state (for the tree) - * @parent - the maple encoded node containing the children. + * @mas: the maple state (for the tree) + * @parent: the maple encoded node containing the children.   */  static inline void mas_adopt_children(struct ma_state *mas,  		struct maple_enode *parent) @@ -1701,8 +1700,8 @@ static inline void mas_adopt_children(struct ma_state *mas,  /*   * mas_put_in_tree() - Put a new node in the tree, smp_wmb(), and mark the old   * node as dead. - * @mas - the maple state with the new node - * @old_enode - The old maple encoded node to replace. + * @mas: the maple state with the new node + * @old_enode: The old maple encoded node to replace.   */  static inline void mas_put_in_tree(struct ma_state *mas,  		struct maple_enode *old_enode) @@ -1730,8 +1729,8 @@ static inline void mas_put_in_tree(struct ma_state *mas,   * mas_replace_node() - Replace a node by putting it in the tree, marking it   * dead, and freeing it.   * the parent encoding to locate the maple node in the tree. - * @mas - the ma_state with @mas->node pointing to the new node. - * @old_enode - The old maple encoded node. + * @mas: the ma_state with @mas->node pointing to the new node. + * @old_enode: The old maple encoded node.   */  static inline void mas_replace_node(struct ma_state *mas,  		struct maple_enode *old_enode) @@ -1796,7 +1795,6 @@ static inline void mab_shift_right(struct maple_big_node *b_node,  /*   * mab_middle_node() - Check if a middle node is needed (unlikely)   * @b_node: the maple_big_node that contains the data. - * @size: the amount of data in the b_node   * @split: the potential split location   * @slot_count: the size that can be stored in a single node being considered.   * @@ -1844,6 +1842,7 @@ static inline int mab_no_null_split(struct maple_big_node *b_node,  /*   * mab_calc_split() - Calculate the split location and if there needs to be two   * splits. + * @mas: The maple state   * @bn: The maple_big_node with the data   * @mid_split: The second split, if required.  0 otherwise.   * @@ -2177,7 +2176,8 @@ static inline bool mas_next_sibling(struct ma_state *mas)  }  /* - * mte_node_or_none() - Set the enode and state. + * mas_node_or_none() - Set the enode and state. + * @mas: the maple state   * @enode: The encoded maple node.   *   * Set the node to the enode and the status. @@ -2228,7 +2228,6 @@ static inline void mas_wr_node_walk(struct ma_wr_state *wr_mas)  /*   * mast_rebalance_next() - Rebalance against the next node   * @mast: The maple subtree state - * @old_r: The encoded maple node to the right (next node).   */  static inline void mast_rebalance_next(struct maple_subtree_state *mast)  { @@ -2242,7 +2241,6 @@ static inline void mast_rebalance_next(struct maple_subtree_state *mast)  /*   * mast_rebalance_prev() - Rebalance against the previous node   * @mast: The maple subtree state - * @old_l: The encoded maple node to the left (previous node)   */  static inline void mast_rebalance_prev(struct maple_subtree_state *mast)  { @@ -2393,9 +2391,9 @@ static inline unsigned char mas_mab_to_node(struct ma_state *mas,  /*   * mab_set_b_end() - Add entry to b_node at b_node->b_end and increment the end   * pointer. - * @b_node - the big node to add the entry - * @mas - the maple state to get the pivot (mas->max) - * @entry - the entry to add, if NULL nothing happens. + * @b_node: the big node to add the entry + * @mas: the maple state to get the pivot (mas->max) + * @entry: the entry to add, if NULL nothing happens.   */  static inline void mab_set_b_end(struct maple_big_node *b_node,  				 struct ma_state *mas, @@ -2414,11 +2412,11 @@ static inline void mab_set_b_end(struct maple_big_node *b_node,   * mas_set_split_parent() - combine_then_separate helper function.  Sets the parent   * of @mas->node to either @left or @right, depending on @slot and @split   * - * @mas - the maple state with the node that needs a parent - * @left - possible parent 1 - * @right - possible parent 2 - * @slot - the slot the mas->node was placed - * @split - the split location between @left and @right + * @mas: the maple state with the node that needs a parent + * @left: possible parent 1 + * @right: possible parent 2 + * @slot: the slot the mas->node was placed + * @split: the split location between @left and @right   */  static inline void mas_set_split_parent(struct ma_state *mas,  					struct maple_enode *left, @@ -2438,11 +2436,11 @@ static inline void mas_set_split_parent(struct ma_state *mas,  /*   * mte_mid_split_check() - Check if the next node passes the mid-split - * @**l: Pointer to left encoded maple node. - * @**m: Pointer to middle encoded maple node. - * @**r: Pointer to right encoded maple node. + * @l: Pointer to left encoded maple node. + * @m: Pointer to middle encoded maple node. + * @r: Pointer to right encoded maple node.   * @slot: The offset - * @*split: The split location. + * @split: The split location.   * @mid_split: The middle split.   */  static inline void mte_mid_split_check(struct maple_enode **l, @@ -2466,10 +2464,10 @@ static inline void mte_mid_split_check(struct maple_enode **l,  /*   * mast_set_split_parents() - Helper function to set three nodes parents.  Slot   * is taken from @mast->l. - * @mast - the maple subtree state - * @left - the left node - * @right - the right node - * @split - the split location. + * @mast: the maple subtree state + * @left: the left node + * @right: the right node + * @split: the split location.   */  static inline void mast_set_split_parents(struct maple_subtree_state *mast,  					  struct maple_enode *left, @@ -2503,7 +2501,6 @@ static inline void mast_set_split_parents(struct maple_subtree_state *mast,  /*   * mas_topiary_node() - Dispose of a single node   * @mas: The maple state for pushing nodes - * @enode: The encoded maple node   * @in_rcu: If the tree is in rcu mode   *   * The node will either be RCU freed or pushed back on the maple state. @@ -2635,7 +2632,7 @@ static inline void mas_topiary_replace(struct ma_state *mas,  /*   * mas_wmb_replace() - Write memory barrier and replace   * @mas: The maple state - * @old: The old maple encoded node that is being replaced. + * @old_enode: The old maple encoded node that is being replaced.   *   * Updates gap as necessary.   */ @@ -2823,10 +2820,8 @@ dead_node:   * orig_l_mas->last is used in mas_consume to find the slots that will need to   * be either freed or destroyed.  orig_l_mas->depth keeps track of the height of   * the new sub-tree in case the sub-tree becomes the full tree. - * - * Return: the number of elements in b_node during the last loop.   */ -static int mas_spanning_rebalance(struct ma_state *mas, +static void mas_spanning_rebalance(struct ma_state *mas,  		struct maple_subtree_state *mast, unsigned char count)  {  	unsigned char split, mid_split; @@ -2942,7 +2937,7 @@ new_root:  	mas->offset = l_mas.offset;  	mas_wmb_replace(mas, old_enode);  	mtree_range_walk(mas); -	return mast->bn->b_end; +	return;  }  /* @@ -2952,10 +2947,8 @@ new_root:   *   * Rebalance two nodes into a single node or two new nodes that are sufficient.   * Continue upwards until tree is sufficient. - * - * Return: the number of elements in b_node during the last loop.   */ -static inline int mas_rebalance(struct ma_state *mas, +static inline void mas_rebalance(struct ma_state *mas,  				struct maple_big_node *b_node)  {  	char empty_count = mas_mt_height(mas); @@ -2976,9 +2969,6 @@ static inline int mas_rebalance(struct ma_state *mas,  	 * tries to combine the data in the same way.  If one node contains the  	 * entire range of the tree, then that node is used as a new root node.  	 */ -	mas_node_count(mas, empty_count * 2 - 1); -	if (mas_is_err(mas)) -		return 0;  	mast.orig_l = &l_mas;  	mast.orig_r = &r_mas; @@ -3029,11 +3019,6 @@ static inline void mas_destroy_rebalance(struct ma_state *mas, unsigned char end  	/* set up node. */  	if (in_rcu) { -		/* Allocate for both left and right as well as parent. */ -		mas_node_count(mas, 3); -		if (mas_is_err(mas)) -			return; -  		newnode = mas_pop_node(mas);  	} else {  		newnode = &reuse; @@ -3308,9 +3293,8 @@ static inline bool mas_push_data(struct ma_state *mas, int height,   * mas_split() - Split data that is too big for one node into two.   * @mas: The maple state   * @b_node: The maple big node - * Return: 1 on success, 0 on failure.   */ -static int mas_split(struct ma_state *mas, struct maple_big_node *b_node) +static void mas_split(struct ma_state *mas, struct maple_big_node *b_node)  {  	struct maple_subtree_state mast;  	int height = 0; @@ -3341,10 +3325,6 @@ static int mas_split(struct ma_state *mas, struct maple_big_node *b_node)  	trace_ma_op(__func__, mas);  	mas->depth = mas_mt_height(mas); -	/* Allocation failures will happen early. */ -	mas_node_count(mas, 1 + mas->depth * 2); -	if (mas_is_err(mas)) -		return 0;  	mast.l = &l_mas;  	mast.r = &r_mas; @@ -3392,75 +3372,25 @@ static int mas_split(struct ma_state *mas, struct maple_big_node *b_node)  	mas->node = l_mas.node;  	mas_wmb_replace(mas, old);  	mtree_range_walk(mas); -	return 1; -} - -/* - * mas_reuse_node() - Reuse the node to store the data. - * @wr_mas: The maple write state - * @bn: The maple big node - * @end: The end of the data. - * - * Will always return false in RCU mode. - * - * Return: True if node was reused, false otherwise. - */ -static inline bool mas_reuse_node(struct ma_wr_state *wr_mas, -			  struct maple_big_node *bn, unsigned char end) -{ -	/* Need to be rcu safe. */ -	if (mt_in_rcu(wr_mas->mas->tree)) -		return false; - -	if (end > bn->b_end) { -		int clear = mt_slots[wr_mas->type] - bn->b_end; - -		memset(wr_mas->slots + bn->b_end, 0, sizeof(void *) * clear--); -		memset(wr_mas->pivots + bn->b_end, 0, sizeof(void *) * clear); -	} -	mab_mas_cp(bn, 0, bn->b_end, wr_mas->mas, false); -	return true; +	return;  }  /*   * mas_commit_b_node() - Commit the big node into the tree.   * @wr_mas: The maple write state   * @b_node: The maple big node - * @end: The end of the data.   */ -static noinline_for_kasan int mas_commit_b_node(struct ma_wr_state *wr_mas, -			    struct maple_big_node *b_node, unsigned char end) +static noinline_for_kasan void mas_commit_b_node(struct ma_wr_state *wr_mas, +			    struct maple_big_node *b_node)  { -	struct maple_node *node; -	struct maple_enode *old_enode; -	unsigned char b_end = b_node->b_end; -	enum maple_type b_type = b_node->type; - -	old_enode = wr_mas->mas->node; -	if ((b_end < mt_min_slots[b_type]) && -	    (!mte_is_root(old_enode)) && -	    (mas_mt_height(wr_mas->mas) > 1)) -		return mas_rebalance(wr_mas->mas, b_node); - -	if (b_end >= mt_slots[b_type]) -		return mas_split(wr_mas->mas, b_node); +	enum store_type type = wr_mas->mas->store_type; -	if (mas_reuse_node(wr_mas, b_node, end)) -		goto reuse_node; +	WARN_ON_ONCE(type != wr_rebalance && type != wr_split_store); -	mas_node_count(wr_mas->mas, 1); -	if (mas_is_err(wr_mas->mas)) -		return 0; +	if (type == wr_rebalance) +		return mas_rebalance(wr_mas->mas, b_node); -	node = mas_pop_node(wr_mas->mas); -	node->parent = mas_mn(wr_mas->mas)->parent; -	wr_mas->mas->node = mt_mk_node(node, b_type); -	mab_mas_cp(b_node, 0, b_end, wr_mas->mas, false); -	mas_replace_node(wr_mas->mas, old_enode); -reuse_node: -	mas_update_gap(wr_mas->mas); -	wr_mas->mas->end = b_end; -	return 1; +	return mas_split(wr_mas->mas, b_node);  }  /* @@ -3477,10 +3407,6 @@ static inline int mas_root_expand(struct ma_state *mas, void *entry)  	unsigned long *pivots;  	int slot = 0; -	mas_node_count(mas, 1); -	if (unlikely(mas_is_err(mas))) -		return 0; -  	node = mas_pop_node(mas);  	pivots = ma_pivots(node, type);  	slots = ma_slots(node, type); @@ -3526,10 +3452,7 @@ static inline void mas_store_root(struct ma_state *mas, void *entry)  /*   * mas_is_span_wr() - Check if the write needs to be treated as a write that   * spans the node. - * @mas: The maple state - * @piv: The pivot value being written - * @type: The maple node type - * @entry: The data to write + * @wr_mas: The maple write state   *   * Spanning writes are writes that start in one node and end in another OR if   * the write of a %NULL will cause the node to end with a %NULL. @@ -3730,10 +3653,8 @@ static void mte_destroy_walk(struct maple_enode *, struct maple_tree *);   * @entry: The entry to store.   *   * Only valid when the index == 0 and the last == ULONG_MAX - * - * Return 0 on error, 1 on success.   */ -static inline int mas_new_root(struct ma_state *mas, void *entry) +static inline void mas_new_root(struct ma_state *mas, void *entry)  {  	struct maple_enode *root = mas_root_locked(mas);  	enum maple_type type = maple_leaf_64; @@ -3749,10 +3670,6 @@ static inline int mas_new_root(struct ma_state *mas, void *entry)  		goto done;  	} -	mas_node_count(mas, 1); -	if (mas_is_err(mas)) -		return 0; -  	node = mas_pop_node(mas);  	pivots = ma_pivots(node, type);  	slots = ma_slots(node, type); @@ -3769,7 +3686,7 @@ done:  	if (xa_is_node(root))  		mte_destroy_walk(root, mas->tree); -	return 1; +	return;  }  /*   * mas_wr_spanning_store() - Create a subtree with the store operation completed @@ -3777,10 +3694,8 @@ done:   * Note that mas is expected to point to the node which caused the store to   * span.   * @wr_mas: The maple write state - * - * Return: 0 on error, positive on success.   */ -static inline int mas_wr_spanning_store(struct ma_wr_state *wr_mas) +static noinline void mas_wr_spanning_store(struct ma_wr_state *wr_mas)  {  	struct maple_subtree_state mast;  	struct maple_big_node b_node; @@ -3815,9 +3730,6 @@ static inline int mas_wr_spanning_store(struct ma_wr_state *wr_mas)  	 * entries per level plus a new root.  	 */  	height = mas_mt_height(mas); -	mas_node_count(mas, 1 + height * 3); -	if (mas_is_err(mas)) -		return 0;  	/*  	 * Set up right side.  Need to get to the next offset after the spanning @@ -3875,10 +3787,8 @@ static inline int mas_wr_spanning_store(struct ma_wr_state *wr_mas)   * @wr_mas: The maple write state   *   * Attempts to reuse the node, but may allocate. - * - * Return: True if stored, false otherwise   */ -static inline bool mas_wr_node_store(struct ma_wr_state *wr_mas, +static inline void mas_wr_node_store(struct ma_wr_state *wr_mas,  				     unsigned char new_end)  {  	struct ma_state *mas = wr_mas->mas; @@ -3889,11 +3799,6 @@ static inline bool mas_wr_node_store(struct ma_wr_state *wr_mas,  	unsigned char copy_size, node_pivots = mt_pivots[wr_mas->type];  	bool in_rcu = mt_in_rcu(mas->tree); -	/* Check if there is enough data. The room is enough. */ -	if (!mte_is_root(mas->node) && (new_end <= mt_min_slots[wr_mas->type]) && -	    !(mas->mas_flags & MA_STATE_BULK)) -		return false; -  	if (mas->last == wr_mas->end_piv)  		offset_end++; /* don't copy this offset */  	else if (unlikely(wr_mas->r_max == ULONG_MAX)) @@ -3901,10 +3806,6 @@ static inline bool mas_wr_node_store(struct ma_wr_state *wr_mas,  	/* set up node. */  	if (in_rcu) { -		mas_node_count(mas, 1); -		if (mas_is_err(mas)) -			return false; -  		newnode = mas_pop_node(mas);  	} else {  		memset(&reuse, 0, sizeof(struct maple_node)); @@ -3960,16 +3861,14 @@ done:  	trace_ma_write(__func__, mas, 0, wr_mas->entry);  	mas_update_gap(mas);  	mas->end = new_end; -	return true; +	return;  }  /*   * mas_wr_slot_store: Attempt to store a value in a slot.   * @wr_mas: the maple write state - * - * Return: True if stored, false otherwise   */ -static inline bool mas_wr_slot_store(struct ma_wr_state *wr_mas) +static inline void mas_wr_slot_store(struct ma_wr_state *wr_mas)  {  	struct ma_state *mas = wr_mas->mas;  	unsigned char offset = mas->offset; @@ -4001,7 +3900,7 @@ static inline bool mas_wr_slot_store(struct ma_wr_state *wr_mas)  		wr_mas->pivots[offset + 1] = mas->last;  		mas->offset++; /* Keep mas accurate. */  	} else { -		return false; +		return;  	}  	trace_ma_write(__func__, mas, 0, wr_mas->entry); @@ -4012,7 +3911,7 @@ static inline bool mas_wr_slot_store(struct ma_wr_state *wr_mas)  	if (!wr_mas->entry || gap)  		mas_update_gap(mas); -	return true; +	return;  }  static inline void mas_wr_extend_null(struct ma_wr_state *wr_mas) @@ -4061,9 +3960,6 @@ static inline void mas_wr_end_piv(struct ma_wr_state *wr_mas)  		wr_mas->end_piv = wr_mas->pivots[wr_mas->offset_end];  	else  		wr_mas->end_piv = wr_mas->mas->max; - -	if (!wr_mas->entry) -		mas_wr_extend_null(wr_mas);  }  static inline unsigned char mas_wr_new_end(struct ma_wr_state *wr_mas) @@ -4089,23 +3985,13 @@ static inline unsigned char mas_wr_new_end(struct ma_wr_state *wr_mas)   * This is currently unsafe in rcu mode since the end of the node may be cached   * by readers while the node contents may be updated which could result in   * inaccurate information. - * - * Return: True if appended, false otherwise   */ -static inline bool mas_wr_append(struct ma_wr_state *wr_mas, +static inline void mas_wr_append(struct ma_wr_state *wr_mas,  		unsigned char new_end)  { -	struct ma_state *mas; +	struct ma_state *mas = wr_mas->mas;  	void __rcu **slots; -	unsigned char end; - -	mas = wr_mas->mas; -	if (mt_in_rcu(mas->tree)) -		return false; - -	end = mas->end; -	if (mas->offset != end) -		return false; +	unsigned char end = mas->end;  	if (new_end < mt_pivots[wr_mas->type]) {  		wr_mas->pivots[new_end] = wr_mas->pivots[end]; @@ -4139,7 +4025,7 @@ static inline bool mas_wr_append(struct ma_wr_state *wr_mas,  	mas->end = new_end;  	trace_ma_write(__func__, mas, new_end, wr_mas->entry); -	return  true; +	return;  }  /* @@ -4155,76 +4041,235 @@ static void mas_wr_bnode(struct ma_wr_state *wr_mas)  	trace_ma_write(__func__, wr_mas->mas, 0, wr_mas->entry);  	memset(&b_node, 0, sizeof(struct maple_big_node));  	mas_store_b_node(wr_mas, &b_node, wr_mas->offset_end); -	mas_commit_b_node(wr_mas, &b_node, wr_mas->mas->end); +	mas_commit_b_node(wr_mas, &b_node);  } -static inline void mas_wr_modify(struct ma_wr_state *wr_mas) +/* + * mas_wr_store_entry() - Internal call to store a value + * @wr_mas: The maple write state + */ +static inline void mas_wr_store_entry(struct ma_wr_state *wr_mas)  {  	struct ma_state *mas = wr_mas->mas; -	unsigned char new_end; +	unsigned char new_end = mas_wr_new_end(wr_mas); -	/* Direct replacement */ -	if (wr_mas->r_min == mas->index && wr_mas->r_max == mas->last) { +	switch (mas->store_type) { +	case wr_invalid: +		MT_BUG_ON(mas->tree, 1); +		return; +	case wr_new_root: +		mas_new_root(mas, wr_mas->entry); +		break; +	case wr_store_root: +		mas_store_root(mas, wr_mas->entry); +		break; +	case wr_exact_fit:  		rcu_assign_pointer(wr_mas->slots[mas->offset], wr_mas->entry);  		if (!!wr_mas->entry ^ !!wr_mas->content)  			mas_update_gap(mas); -		return; +		break; +	case wr_append: +		mas_wr_append(wr_mas, new_end); +		break; +	case wr_slot_store: +		mas_wr_slot_store(wr_mas); +		break; +	case wr_node_store: +		mas_wr_node_store(wr_mas, new_end); +		break; +	case wr_spanning_store: +		mas_wr_spanning_store(wr_mas); +		break; +	case wr_split_store: +	case wr_rebalance: +		mas_wr_bnode(wr_mas); +		break; +	} + +	return; +} + +static inline void mas_wr_prealloc_setup(struct ma_wr_state *wr_mas) +{ +	struct ma_state *mas = wr_mas->mas; + +	if (!mas_is_active(mas)) { +		if (mas_is_start(mas)) +			goto set_content; + +		if (unlikely(mas_is_paused(mas))) +			goto reset; + +		if (unlikely(mas_is_none(mas))) +			goto reset; + +		if (unlikely(mas_is_overflow(mas))) +			goto reset; + +		if (unlikely(mas_is_underflow(mas))) +			goto reset;  	}  	/* -	 * new_end exceeds the size of the maple node and cannot enter the fast -	 * path. +	 * A less strict version of mas_is_span_wr() where we allow spanning +	 * writes within this node.  This is to stop partial walks in +	 * mas_prealloc() from being reset.  	 */ -	new_end = mas_wr_new_end(wr_mas); -	if (new_end >= mt_slots[wr_mas->type]) -		goto slow_path; - -	/* Attempt to append */ -	if (mas_wr_append(wr_mas, new_end)) -		return; +	if (mas->last > mas->max) +		goto reset; -	if (new_end == mas->end && mas_wr_slot_store(wr_mas)) -		return; +	if (wr_mas->entry) +		goto set_content; -	if (mas_wr_node_store(wr_mas, new_end)) -		return; +	if (mte_is_leaf(mas->node) && mas->last == mas->max) +		goto reset; -	if (mas_is_err(mas)) -		return; +	goto set_content; -slow_path: -	mas_wr_bnode(wr_mas); +reset: +	mas_reset(mas); +set_content: +	wr_mas->content = mas_start(mas);  } -/* - * mas_wr_store_entry() - Internal call to store a value +/** + * mas_prealloc_calc() - Calculate number of nodes needed for a + * given store oepration   * @mas: The maple state - * @entry: The entry to store. + * @entry: The entry to store into the tree   * - * Return: The contents that was stored at the index. + * Return: Number of nodes required for preallocation.   */ -static inline void mas_wr_store_entry(struct ma_wr_state *wr_mas) +static inline int mas_prealloc_calc(struct ma_state *mas, void *entry) +{ +	int ret = mas_mt_height(mas) * 3 + 1; + +	switch (mas->store_type) { +	case wr_invalid: +		WARN_ON_ONCE(1); +		break; +	case wr_new_root: +		ret = 1; +		break; +	case wr_store_root: +		if (likely((mas->last != 0) || (mas->index != 0))) +			ret = 1; +		else if (((unsigned long) (entry) & 3) == 2) +			ret = 1; +		else +			ret = 0; +		break; +	case wr_spanning_store: +		ret =  mas_mt_height(mas) * 3 + 1; +		break; +	case wr_split_store: +		ret =  mas_mt_height(mas) * 2 + 1; +		break; +	case wr_rebalance: +		ret =  mas_mt_height(mas) * 2 - 1; +		break; +	case wr_node_store: +		ret = mt_in_rcu(mas->tree) ? 1 : 0; +		break; +	case wr_append: +	case wr_exact_fit: +	case wr_slot_store: +		ret = 0; +	} + +	return ret; +} + +/* + * mas_wr_store_type() - Set the store type for a given + * store operation. + * @wr_mas: The maple write state + */ +static inline void mas_wr_store_type(struct ma_wr_state *wr_mas)  {  	struct ma_state *mas = wr_mas->mas; +	unsigned char new_end; -	wr_mas->content = mas_start(mas); -	if (mas_is_none(mas) || mas_is_ptr(mas)) { -		mas_store_root(mas, wr_mas->entry); +	if (unlikely(mas_is_none(mas) || mas_is_ptr(mas))) { +		mas->store_type = wr_store_root;  		return;  	}  	if (unlikely(!mas_wr_walk(wr_mas))) { -		mas_wr_spanning_store(wr_mas); +		mas->store_type = wr_spanning_store;  		return;  	}  	/* At this point, we are at the leaf node that needs to be altered. */  	mas_wr_end_piv(wr_mas); -	/* New root for a single pointer */ -	if (unlikely(!mas->index && mas->last == ULONG_MAX)) -		mas_new_root(mas, wr_mas->entry); -	else -		mas_wr_modify(wr_mas); +	if (!wr_mas->entry) +		mas_wr_extend_null(wr_mas); + +	new_end = mas_wr_new_end(wr_mas); +	if ((wr_mas->r_min == mas->index) && (wr_mas->r_max == mas->last)) { +		mas->store_type = wr_exact_fit; +		return; +	} + +	if (unlikely(!mas->index && mas->last == ULONG_MAX)) { +		mas->store_type = wr_new_root; +		return; +	} + +	/* Potential spanning rebalance collapsing a node */ +	if (new_end < mt_min_slots[wr_mas->type]) { +		if (!mte_is_root(mas->node)) { +			mas->store_type = wr_rebalance; +			return; +		} +		mas->store_type = wr_node_store; +		return; +	} + +	if (new_end >= mt_slots[wr_mas->type]) { +		mas->store_type = wr_split_store; +		return; +	} + +	if (!mt_in_rcu(mas->tree) && (mas->offset == mas->end)) { +		mas->store_type = wr_append; +		return; +	} + +	if ((new_end == mas->end) && (!mt_in_rcu(mas->tree) || +		(wr_mas->offset_end - mas->offset == 1))) { +		mas->store_type = wr_slot_store; +		return; +	} + +	if (mte_is_root(mas->node) || (new_end >= mt_min_slots[wr_mas->type]) || +		(mas->mas_flags & MA_STATE_BULK)) { +		mas->store_type = wr_node_store; +		return; +	} + +	mas->store_type = wr_invalid; +	MAS_WARN_ON(mas, 1); +} + +/** + * mas_wr_preallocate() - Preallocate enough nodes for a store operation + * @wr_mas: The maple write state + * @entry: The entry that will be stored + * + */ +static inline void mas_wr_preallocate(struct ma_wr_state *wr_mas, void *entry) +{ +	struct ma_state *mas = wr_mas->mas; +	int request; + +	mas_wr_prealloc_setup(wr_mas); +	mas_wr_store_type(wr_mas); +	request = mas_prealloc_calc(mas, entry); +	if (!request) +		return; + +	mas_node_count(mas, request);  }  /** @@ -4257,26 +4302,24 @@ static inline void *mas_insert(struct ma_state *mas, void *entry)  	if (wr_mas.content)  		goto exists; -	if (mas_is_none(mas) || mas_is_ptr(mas)) { -		mas_store_root(mas, entry); +	mas_wr_preallocate(&wr_mas, entry); +	if (mas_is_err(mas))  		return NULL; -	}  	/* spanning writes always overwrite something */ -	if (!mas_wr_walk(&wr_mas)) +	if (mas->store_type == wr_spanning_store)  		goto exists;  	/* At this point, we are at the leaf node that needs to be altered. */ -	wr_mas.offset_end = mas->offset; -	wr_mas.end_piv = wr_mas.r_max; - -	if (wr_mas.content || (mas->last > wr_mas.r_max)) -		goto exists; +	if (mas->store_type != wr_new_root && mas->store_type != wr_store_root) { +		wr_mas.offset_end = mas->offset; +		wr_mas.end_piv = wr_mas.r_max; -	if (!entry) -		return NULL; +		if (wr_mas.content || (mas->last > wr_mas.r_max)) +			goto exists; +	} -	mas_wr_modify(&wr_mas); +	mas_wr_store_entry(&wr_mas);  	return wr_mas.content;  exists: @@ -4331,6 +4374,7 @@ int mas_alloc_cyclic(struct ma_state *mas, unsigned long *startp,  	if (*next == 0)  		mas->tree->ma_flags |= MT_FLAGS_ALLOC_WRAPPED; +	mas_destroy(mas);  	return ret;  }  EXPORT_SYMBOL(mas_alloc_cyclic); @@ -4440,9 +4484,8 @@ no_entry:   * mas_prev_slot() - Get the entry in the previous slot   *   * @mas: The maple state - * @max: The minimum starting range + * @min: The minimum starting range   * @empty: Can be empty - * @set_underflow: Set the @mas->node to underflow state on limit.   *   * Return: The entry in the previous slot which is possibly NULL   */ @@ -4525,6 +4568,7 @@ underflow:  /*   * mas_next_node() - Get the next node at the same level in the tree.   * @mas: The maple state + * @node: The maple node   * @max: The maximum pivot value to check.   *   * The next value will be mas->node[mas->offset] or the status will have @@ -4615,8 +4659,6 @@ overflow:   * @mas: The maple state   * @max: The maximum starting range   * @empty: Can be empty - * @set_overflow: Should @mas->node be set to overflow when the limit is - * reached.   *   * Return: The entry in the next slot which is possibly NULL   */ @@ -5150,9 +5192,9 @@ EXPORT_SYMBOL_GPL(mas_empty_area_rev);  /*   * mte_dead_leaves() - Mark all leaves of a node as dead. - * @mas: The maple state + * @enode: the encoded node + * @mt: the maple tree   * @slots: Pointer to the slot array - * @type: The maple node type   *   * Must hold the write lock.   * @@ -5358,47 +5400,6 @@ static inline void mte_destroy_walk(struct maple_enode *enode,  		mt_destroy_walk(enode, mt, true);  	}  } - -static void mas_wr_store_setup(struct ma_wr_state *wr_mas) -{ -	if (!mas_is_active(wr_mas->mas)) { -		if (mas_is_start(wr_mas->mas)) -			return; - -		if (unlikely(mas_is_paused(wr_mas->mas))) -			goto reset; - -		if (unlikely(mas_is_none(wr_mas->mas))) -			goto reset; - -		if (unlikely(mas_is_overflow(wr_mas->mas))) -			goto reset; - -		if (unlikely(mas_is_underflow(wr_mas->mas))) -			goto reset; -	} - -	/* -	 * A less strict version of mas_is_span_wr() where we allow spanning -	 * writes within this node.  This is to stop partial walks in -	 * mas_prealloc() from being reset. -	 */ -	if (wr_mas->mas->last > wr_mas->mas->max) -		goto reset; - -	if (wr_mas->entry) -		return; - -	if (mte_is_leaf(wr_mas->mas->node) && -	    wr_mas->mas->last == wr_mas->mas->max) -		goto reset; - -	return; - -reset: -	mas_reset(wr_mas->mas); -} -  /* Interface */  /** @@ -5407,13 +5408,12 @@ reset:   * @entry: The entry to store.   *   * The @mas->index and @mas->last is used to set the range for the @entry. - * Note: The @mas should have pre-allocated entries to ensure there is memory to - * store the entry.  Please see mas_expected_entries()/mas_destroy() for more details.   *   * Return: the first entry between mas->index and mas->last or %NULL.   */  void *mas_store(struct ma_state *mas, void *entry)  { +	int request;  	MA_WR_STATE(wr_mas, mas, entry);  	trace_ma_write(__func__, mas, 0, entry); @@ -5434,8 +5434,25 @@ void *mas_store(struct ma_state *mas, void *entry)  	 * want to examine what happens if a single store operation was to  	 * overwrite multiple entries within a self-balancing B-Tree.  	 */ -	mas_wr_store_setup(&wr_mas); +	mas_wr_prealloc_setup(&wr_mas); +	mas_wr_store_type(&wr_mas); +	if (mas->mas_flags & MA_STATE_PREALLOC) { +		mas_wr_store_entry(&wr_mas); +		MAS_WR_BUG_ON(&wr_mas, mas_is_err(mas)); +		return wr_mas.content; +	} + +	request = mas_prealloc_calc(mas, entry); +	if (!request) +		goto store; + +	mas_node_count(mas, request); +	if (mas_is_err(mas)) +		return NULL; + +store:  	mas_wr_store_entry(&wr_mas); +	mas_destroy(mas);  	return wr_mas.content;  }  EXPORT_SYMBOL_GPL(mas_store); @@ -5451,19 +5468,28 @@ EXPORT_SYMBOL_GPL(mas_store);   */  int mas_store_gfp(struct ma_state *mas, void *entry, gfp_t gfp)  { +	unsigned long index = mas->index; +	unsigned long last = mas->last;  	MA_WR_STATE(wr_mas, mas, entry); +	int ret = 0; -	mas_wr_store_setup(&wr_mas); -	trace_ma_write(__func__, mas, 0, entry);  retry: -	mas_wr_store_entry(&wr_mas); -	if (unlikely(mas_nomem(mas, gfp))) +	mas_wr_preallocate(&wr_mas, entry); +	if (unlikely(mas_nomem(mas, gfp))) { +		if (!entry) +			__mas_set_range(mas, index, last);  		goto retry; +	} -	if (unlikely(mas_is_err(mas))) -		return xa_err(mas->node); +	if (mas_is_err(mas)) { +		ret = xa_err(mas->node); +		goto out; +	} -	return 0; +	mas_wr_store_entry(&wr_mas); +out: +	mas_destroy(mas); +	return ret;  }  EXPORT_SYMBOL_GPL(mas_store_gfp); @@ -5477,7 +5503,19 @@ void mas_store_prealloc(struct ma_state *mas, void *entry)  {  	MA_WR_STATE(wr_mas, mas, entry); -	mas_wr_store_setup(&wr_mas); +	if (mas->store_type == wr_store_root) { +		mas_wr_prealloc_setup(&wr_mas); +		goto store; +	} + +	mas_wr_walk_descend(&wr_mas); +	if (mas->store_type != wr_spanning_store) { +		/* set wr_mas->content to current slot */ +		wr_mas.content = mas_slot_locked(mas, wr_mas.slots, mas->offset); +		mas_wr_end_piv(&wr_mas); +	} + +store:  	trace_ma_write(__func__, mas, 0, entry);  	mas_wr_store_entry(&wr_mas);  	MAS_WR_BUG_ON(&wr_mas, mas_is_err(mas)); @@ -5496,70 +5534,25 @@ EXPORT_SYMBOL_GPL(mas_store_prealloc);  int mas_preallocate(struct ma_state *mas, void *entry, gfp_t gfp)  {  	MA_WR_STATE(wr_mas, mas, entry); -	unsigned char node_size; -	int request = 1; -	int ret; - - -	if (unlikely(!mas->index && mas->last == ULONG_MAX)) -		goto ask_now; - -	mas_wr_store_setup(&wr_mas); -	wr_mas.content = mas_start(mas); -	/* Root expand */ -	if (unlikely(mas_is_none(mas) || mas_is_ptr(mas))) -		goto ask_now; - -	if (unlikely(!mas_wr_walk(&wr_mas))) { -		/* Spanning store, use worst case for now */ -		request = 1 + mas_mt_height(mas) * 3; -		goto ask_now; -	} - -	/* At this point, we are at the leaf node that needs to be altered. */ -	/* Exact fit, no nodes needed. */ -	if (wr_mas.r_min == mas->index && wr_mas.r_max == mas->last) -		return 0; - -	mas_wr_end_piv(&wr_mas); -	node_size = mas_wr_new_end(&wr_mas); +	int ret = 0; +	int request; -	/* Slot store, does not require additional nodes */ -	if (node_size == mas->end) { -		/* reuse node */ -		if (!mt_in_rcu(mas->tree)) -			return 0; -		/* shifting boundary */ -		if (wr_mas.offset_end - mas->offset == 1) -			return 0; -	} +	mas_wr_prealloc_setup(&wr_mas); +	mas_wr_store_type(&wr_mas); +	request = mas_prealloc_calc(mas, entry); +	if (!request) +		return ret; -	if (node_size >= mt_slots[wr_mas.type]) { -		/* Split, worst case for now. */ -		request = 1 + mas_mt_height(mas) * 2; -		goto ask_now; +	mas_node_count_gfp(mas, request, gfp); +	if (mas_is_err(mas)) { +		mas_set_alloc_req(mas, 0); +		ret = xa_err(mas->node); +		mas_destroy(mas); +		mas_reset(mas); +		return ret;  	} -	/* New root needs a single node */ -	if (unlikely(mte_is_root(mas->node))) -		goto ask_now; - -	/* Potential spanning rebalance collapsing a node, use worst-case */ -	if (node_size  - 1 <= mt_min_slots[wr_mas.type]) -		request = mas_mt_height(mas) * 2 - 1; - -	/* node store, slot store needs one node */ -ask_now: -	mas_node_count_gfp(mas, request, gfp);  	mas->mas_flags |= MA_STATE_PREALLOC; -	if (likely(!mas_is_err(mas))) -		return 0; - -	mas_set_alloc_req(mas, 0); -	ret = xa_err(mas->node); -	mas_reset(mas); -	mas_destroy(mas); -	mas_reset(mas);  	return ret;  }  EXPORT_SYMBOL_GPL(mas_preallocate); @@ -5585,7 +5578,8 @@ void mas_destroy(struct ma_state *mas)  	 */  	if (mas->mas_flags & MA_STATE_REBALANCE) {  		unsigned char end; - +		if (mas_is_err(mas)) +			mas_reset(mas);  		mas_start(mas);  		mtree_range_walk(mas);  		end = mas->end + 1; @@ -6245,24 +6239,32 @@ EXPORT_SYMBOL_GPL(mas_find_range_rev);  void *mas_erase(struct ma_state *mas)  {  	void *entry; +	unsigned long index = mas->index;  	MA_WR_STATE(wr_mas, mas, NULL);  	if (!mas_is_active(mas) || !mas_is_start(mas))  		mas->status = ma_start; -	/* Retry unnecessary when holding the write lock. */ +write_retry:  	entry = mas_state_walk(mas);  	if (!entry)  		return NULL; -write_retry:  	/* Must reset to ensure spanning writes of last slot are detected */  	mas_reset(mas); -	mas_wr_store_setup(&wr_mas); -	mas_wr_store_entry(&wr_mas); -	if (mas_nomem(mas, GFP_KERNEL)) +	mas_wr_preallocate(&wr_mas, NULL); +	if (mas_nomem(mas, GFP_KERNEL)) { +		/* in case the range of entry changed when unlocked */ +		mas->index = mas->last = index;  		goto write_retry; +	} +	if (mas_is_err(mas)) +		goto out; + +	mas_wr_store_entry(&wr_mas); +out: +	mas_destroy(mas);  	return entry;  }  EXPORT_SYMBOL_GPL(mas_erase); @@ -6277,10 +6279,8 @@ EXPORT_SYMBOL_GPL(mas_erase);  bool mas_nomem(struct ma_state *mas, gfp_t gfp)  	__must_hold(mas->tree->ma_lock)  { -	if (likely(mas->node != MA_ERROR(-ENOMEM))) { -		mas_destroy(mas); +	if (likely(mas->node != MA_ERROR(-ENOMEM)))  		return false; -	}  	if (gfpflags_allow_blocking(gfp) && !mt_external_lock(mas->tree)) {  		mtree_unlock(mas->tree); @@ -6357,7 +6357,7 @@ int mtree_store_range(struct maple_tree *mt, unsigned long index,  		unsigned long last, void *entry, gfp_t gfp)  {  	MA_STATE(mas, mt, index, last); -	MA_WR_STATE(wr_mas, &mas, entry); +	int ret = 0;  	trace_ma_write(__func__, &mas, 0, entry);  	if (WARN_ON_ONCE(xa_is_advanced(entry))) @@ -6367,16 +6367,10 @@ int mtree_store_range(struct maple_tree *mt, unsigned long index,  		return -EINVAL;  	mtree_lock(mt); -retry: -	mas_wr_store_entry(&wr_mas); -	if (mas_nomem(&mas, gfp)) -		goto retry; - +	ret = mas_store_gfp(&mas, entry, gfp);  	mtree_unlock(mt); -	if (mas_is_err(&mas)) -		return xa_err(mas.node); -	return 0; +	return ret;  }  EXPORT_SYMBOL(mtree_store_range); @@ -6412,6 +6406,7 @@ int mtree_insert_range(struct maple_tree *mt, unsigned long first,  		unsigned long last, void *entry, gfp_t gfp)  {  	MA_STATE(ms, mt, first, last); +	int ret = 0;  	if (WARN_ON_ONCE(xa_is_advanced(entry)))  		return -EINVAL; @@ -6427,9 +6422,10 @@ retry:  	mtree_unlock(mt);  	if (mas_is_err(&ms)) -		return xa_err(ms.node); +		ret = xa_err(ms.node); -	return 0; +	mas_destroy(&ms); +	return ret;  }  EXPORT_SYMBOL(mtree_insert_range); @@ -6484,6 +6480,7 @@ retry:  unlock:  	mtree_unlock(mt); +	mas_destroy(&mas);  	return ret;  }  EXPORT_SYMBOL(mtree_alloc_range); @@ -6565,6 +6562,7 @@ retry:  unlock:  	mtree_unlock(mt); +	mas_destroy(&mas);  	return ret;  }  EXPORT_SYMBOL(mtree_alloc_rrange); @@ -6997,6 +6995,19 @@ void mt_set_non_kernel(unsigned int val)  	kmem_cache_set_non_kernel(maple_node_cache, val);  } +extern void kmem_cache_set_callback(struct kmem_cache *cachep, +		void (*callback)(void *)); +void mt_set_callback(void (*callback)(void *)) +{ +	kmem_cache_set_callback(maple_node_cache, callback); +} + +extern void kmem_cache_set_private(struct kmem_cache *cachep, void *private); +void mt_set_private(void *private) +{ +	kmem_cache_set_private(maple_node_cache, private); +} +  extern unsigned long kmem_cache_get_alloc(struct kmem_cache *);  unsigned long mt_get_alloc_size(void)  { @@ -7181,7 +7192,6 @@ static void mt_dump_arange64(const struct maple_tree *mt, void *entry,  	enum mt_dump_format format)  {  	struct maple_arange_64 *node = &mte_to_node(entry)->ma64; -	bool leaf = mte_is_leaf(entry);  	unsigned long first = min;  	int i; @@ -7215,19 +7225,22 @@ static void mt_dump_arange64(const struct maple_tree *mt, void *entry,  			break;  		if (last == 0 && i > 0)  			break; -		if (leaf) -			mt_dump_entry(mt_slot(mt, node->slot, i), -					first, last, depth + 1, format); -		else if (node->slot[i]) +		if (node->slot[i])  			mt_dump_node(mt, mt_slot(mt, node->slot, i),  					first, last, depth + 1, format);  		if (last == max)  			break;  		if (last > max) { -			pr_err("node %p last (%lu) > max (%lu) at pivot %d!\n", +			switch(format) { +			case mt_dump_hex: +				pr_err("node %p last (%lx) > max (%lx) at pivot %d!\n",  					node, last, max, i); -			break; +				break; +			case mt_dump_dec: +				pr_err("node %p last (%lu) > max (%lu) at pivot %d!\n", +					node, last, max, i); +			}  		}  		first = last + 1;  	} @@ -7566,14 +7579,14 @@ static void mt_validate_nulls(struct maple_tree *mt)   * 2. The gap is correctly set in the parents   */  void mt_validate(struct maple_tree *mt) +	__must_hold(mas->tree->ma_lock)  {  	unsigned char end;  	MA_STATE(mas, mt, 0, 0); -	rcu_read_lock();  	mas_start(&mas);  	if (!mas_is_active(&mas)) -		goto done; +		return;  	while (!mte_is_leaf(mas.node))  		mas_descend(&mas); @@ -7594,9 +7607,6 @@ void mt_validate(struct maple_tree *mt)  		mas_dfs_postorder(&mas, ULONG_MAX);  	}  	mt_validate_nulls(mt); -done: -	rcu_read_unlock(); -  }  EXPORT_SYMBOL_GPL(mt_validate); @@ -7630,6 +7640,40 @@ void mas_dump(const struct ma_state *mas)  		break;  	} +	pr_err("Store Type: "); +	switch (mas->store_type) { +	case wr_invalid: +		pr_err("invalid store type\n"); +		break; +	case wr_new_root: +		pr_err("new_root\n"); +		break; +	case wr_store_root: +		pr_err("store_root\n"); +		break; +	case wr_exact_fit: +		pr_err("exact_fit\n"); +		break; +	case wr_split_store: +		pr_err("split_store\n"); +		break; +	case wr_slot_store: +		pr_err("slot_store\n"); +		break; +	case wr_append: +		pr_err("append\n"); +		break; +	case wr_node_store: +		pr_err("node_store\n"); +		break; +	case wr_spanning_store: +		pr_err("spanning_store\n"); +		break; +	case wr_rebalance: +		pr_err("rebalance\n"); +		break; +	} +  	pr_err("[%u/%u] index=%lx last=%lx\n", mas->offset, mas->end,  	       mas->index, mas->last);  	pr_err("     min=%lx max=%lx alloc=%p, depth=%u, flags=%x\n", | 
