Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <lorenzo.stoakes@oracle.com>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Reviewed-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
Reviewed-by: Wei 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: Andrew Morton <akpm@linux-foundation.org>

authored by

Lorenzo Stoakes and committed by
Andrew Morton
e993457d bea07fd6

+84
+84
tools/testing/radix-tree/maple.c
··· 36432 36432 check_nomem(&tree); 36433 36433 } 36434 36434 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 + 36435 36518 void maple_tree_tests(void) 36436 36519 { 36437 36520 #if !defined(BENCH) 36521 + regression_tests(); 36438 36522 farmer_tests(); 36439 36523 #endif 36440 36524 maple_tree_seed();