From: Liam R. Howlett Date: Tue, 8 Mar 2022 14:45:49 +0000 (-0500) Subject: maple_tree: Fix potential metadata off by one in mas_mab_cp() on final node X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=7d35a4a5611bfeebd075cb82b8af47a79ee8f3f6;p=users%2Fjedix%2Flinux-maple.git maple_tree: Fix potential metadata off by one in mas_mab_cp() on final node Signed-off-by: Liam R. Howlett --- diff --git a/lib/maple_tree.c b/lib/maple_tree.c index 8449d21118bd..556cdbd0db81 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -1915,6 +1915,33 @@ complete: } } +/* + * mas_leaf_set_meta() - Set the metadata of a leaf if possible. + * @mas: The maple state + * @node: The maple node + * @pivots: pointer to the maple node pivots + * @mt: The maple type + * @end: The assumed end + * + * Note, end may be incremented within this function but not modified at the + * source. This is fine since the metadata is the last thing to be stored in a + * node during a write. + */ +static inline void mas_leaf_set_meta(struct ma_state *mas, + struct maple_node *node, unsigned long *pivots, + enum maple_type mt, unsigned char end) +{ + /* There is no room for metadata already */ + if (mt_pivots[mt] <= end) + return; + + if (pivots[end] && pivots[end] < mas->max) + end++; + + if (end < mt_slots[mt] - 1) + ma_set_meta(node, mt, 0, end); +} + /* * mab_mas_cp() - Copy data from maple_big_node to a maple encoded node. * @b_node: the maple_big_node that has the data @@ -1967,12 +1994,8 @@ static inline void mab_mas_cp(struct maple_big_node *b_node, } while (j); ma_set_meta(node, mt, offset, end); - } else if (end <= mt_pivots[mt] - 1) { - if (pivots[end] != mas->max) - end++; - - if (end < mt_slots[mt] - 1) - ma_set_meta(node, mt, 0, end); + } else { + mas_leaf_set_meta(mas, node, pivots, mt, end); } } @@ -3925,7 +3948,6 @@ static inline bool mas_wr_node_store(struct ma_wr_state *wr_mas) unsigned char new_end = wr_mas->node_end; unsigned char offset; unsigned char node_slots = mt_slots[wr_mas->type]; - unsigned char node_pivots = mt_pivots[wr_mas->type]; struct maple_node reuse, *newnode; unsigned char copy_size, max_piv = mt_pivots[wr_mas->type]; bool in_rcu = mt_in_rcu(mas->tree); @@ -4016,12 +4038,7 @@ done: if ((wr_mas->node_end == node_slots - 1) && (new_end < node_slots - 1)) dst_pivots[new_end] = mas->max; - if (!dst_pivots[node_pivots - 1] || dst_pivots[node_pivots - 1] == mas->max) { - if (dst_pivots[new_end] && dst_pivots[new_end] < mas->max) - new_end++; - ma_set_meta(newnode, maple_leaf_64, 0, new_end); - } - + mas_leaf_set_meta(mas, newnode, dst_pivots, maple_leaf_64, new_end); if (in_rcu) { mas->node = mt_mk_node(newnode, wr_mas->type); mas_replace(mas, false);