Skip to content

Commit e993457

Browse files
lorenzo-stoakesakpm00
authored andcommitted
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.com Signed-off-by: Lorenzo Stoakes <[email protected]> Acked-by: Vlastimil Babka <[email protected]> Reviewed-by: Liam R. Howlett <[email protected]> Reviewed-by: Wei Yang <[email protected]> Cc: Bert Karwatzki <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Mikhail Gavrilov <[email protected]> Cc: Sidhartha Kumar <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent bea07fd commit e993457

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

tools/testing/radix-tree/maple.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36432,9 +36432,93 @@ void farmer_tests(void)
3643236432
check_nomem(&tree);
3643336433
}
3643436434

36435+
static unsigned long get_last_index(struct ma_state *mas)
36436+
{
36437+
struct maple_node *node = mas_mn(mas);
36438+
enum maple_type mt = mte_node_type(mas->node);
36439+
unsigned long *pivots = ma_pivots(node, mt);
36440+
unsigned long last_index = mas_data_end(mas);
36441+
36442+
BUG_ON(last_index == 0);
36443+
36444+
return pivots[last_index - 1] + 1;
36445+
}
36446+
36447+
/*
36448+
* Assert that we handle spanning stores that consume the entirety of the right
36449+
* leaf node correctly.
36450+
*/
36451+
static void test_spanning_store_regression(void)
36452+
{
36453+
unsigned long from = 0, to = 0;
36454+
DEFINE_MTREE(tree);
36455+
MA_STATE(mas, &tree, 0, 0);
36456+
36457+
/*
36458+
* Build a 3-level tree. We require a parent node below the root node
36459+
* and 2 leaf nodes under it, so we can span the entirety of the right
36460+
* hand node.
36461+
*/
36462+
build_full_tree(&tree, 0, 3);
36463+
36464+
/* Descend into position at depth 2. */
36465+
mas_reset(&mas);
36466+
mas_start(&mas);
36467+
mas_descend(&mas);
36468+
mas_descend(&mas);
36469+
36470+
/*
36471+
* We need to establish a tree like the below.
36472+
*
36473+
* Then we can try a store in [from, to] which results in a spanned
36474+
* store across nodes B and C, with the maple state at the time of the
36475+
* write being such that only the subtree at A and below is considered.
36476+
*
36477+
* Height
36478+
* 0 Root Node
36479+
* / \
36480+
* pivot = to / \ pivot = ULONG_MAX
36481+
* / \
36482+
* 1 A [-----] ...
36483+
* / \
36484+
* pivot = from / \ pivot = to
36485+
* / \
36486+
* 2 (LEAVES) B [-----] [-----] C
36487+
* ^--- Last pivot to.
36488+
*/
36489+
while (true) {
36490+
unsigned long tmp = get_last_index(&mas);
36491+
36492+
if (mas_next_sibling(&mas)) {
36493+
from = tmp;
36494+
to = mas.max;
36495+
} else {
36496+
break;
36497+
}
36498+
}
36499+
36500+
BUG_ON(from == 0 && to == 0);
36501+
36502+
/* Perform the store. */
36503+
mas_set_range(&mas, from, to);
36504+
mas_store_gfp(&mas, xa_mk_value(0xdead), GFP_KERNEL);
36505+
36506+
/* If the regression occurs, the validation will fail. */
36507+
mt_validate(&tree);
36508+
36509+
/* Cleanup. */
36510+
__mt_destroy(&tree);
36511+
}
36512+
36513+
static void regression_tests(void)
36514+
{
36515+
test_spanning_store_regression();
36516+
}
36517+
3643536518
void maple_tree_tests(void)
3643636519
{
3643736520
#if !defined(BENCH)
36521+
regression_tests();
3643836522
farmer_tests();
3643936523
#endif
3644036524
maple_tree_seed();

0 commit comments

Comments
 (0)