Commit e993457d authored by Lorenzo Stoakes's avatar Lorenzo Stoakes Committed by Andrew Morton

maple_tree: add regression test for spanning store bug

Add a regression test to assert that, when performing a spanning store
which consumes the entirety of the rightmost right leaf node does not
result in maple tree corruption when doing so.

This achieves this by building a test tree of 3 levels and establishing a
store which ultimately results in a spanned store of this nature.

Link: https://lkml.kernel.org/r/30cdc101a700d16e03ba2f9aa5d83f2efa894168.1728314403.git.lorenzo.stoakes@oracle.comSigned-off-by: default avatarLorenzo Stoakes <lorenzo.stoakes@oracle.com>
Acked-by: default avatarVlastimil Babka <vbabka@suse.cz>
Reviewed-by: default avatarLiam R. Howlett <Liam.Howlett@Oracle.com>
Reviewed-by: default avatarWei Yang <richard.weiyang@gmail.com>
Cc: Bert Karwatzki <spasswolf@web.de>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
Cc: Sidhartha Kumar <sidhartha.kumar@oracle.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent bea07fd6
......@@ -36432,9 +36432,93 @@ void farmer_tests(void)
check_nomem(&tree);
}
static unsigned long get_last_index(struct ma_state *mas)
{
struct maple_node *node = mas_mn(mas);
enum maple_type mt = mte_node_type(mas->node);
unsigned long *pivots = ma_pivots(node, mt);
unsigned long last_index = mas_data_end(mas);
BUG_ON(last_index == 0);
return pivots[last_index - 1] + 1;
}
/*
* Assert that we handle spanning stores that consume the entirety of the right
* leaf node correctly.
*/
static void test_spanning_store_regression(void)
{
unsigned long from = 0, to = 0;
DEFINE_MTREE(tree);
MA_STATE(mas, &tree, 0, 0);
/*
* Build a 3-level tree. We require a parent node below the root node
* and 2 leaf nodes under it, so we can span the entirety of the right
* hand node.
*/
build_full_tree(&tree, 0, 3);
/* Descend into position at depth 2. */
mas_reset(&mas);
mas_start(&mas);
mas_descend(&mas);
mas_descend(&mas);
/*
* We need to establish a tree like the below.
*
* Then we can try a store in [from, to] which results in a spanned
* store across nodes B and C, with the maple state at the time of the
* write being such that only the subtree at A and below is considered.
*
* Height
* 0 Root Node
* / \
* pivot = to / \ pivot = ULONG_MAX
* / \
* 1 A [-----] ...
* / \
* pivot = from / \ pivot = to
* / \
* 2 (LEAVES) B [-----] [-----] C
* ^--- Last pivot to.
*/
while (true) {
unsigned long tmp = get_last_index(&mas);
if (mas_next_sibling(&mas)) {
from = tmp;
to = mas.max;
} else {
break;
}
}
BUG_ON(from == 0 && to == 0);
/* Perform the store. */
mas_set_range(&mas, from, to);
mas_store_gfp(&mas, xa_mk_value(0xdead), GFP_KERNEL);
/* If the regression occurs, the validation will fail. */
mt_validate(&tree);
/* Cleanup. */
__mt_destroy(&tree);
}
static void regression_tests(void)
{
test_spanning_store_regression();
}
void maple_tree_tests(void)
{
#if !defined(BENCH)
regression_tests();
farmer_tests();
#endif
maple_tree_seed();
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment