diff options
author | Matthew Wilcox <willy@linux.intel.com> | 2016-12-14 18:09:04 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-14 19:04:10 -0500 |
commit | 2791653a6814d170fa893344618563a7b1da95c6 (patch) | |
tree | 635c8ca43b49ac15836e5d4b5786d64733661755 /tools | |
parent | e157b555945fb16ddc6cce605a1eb6b4135ea5f1 (diff) |
radix-tree: add radix_tree_split_preload()
Calculate how many nodes we need to allocate to split an old_order entry
into multiple entries, each of size new_order. The test suite checks
that we allocated exactly the right number of nodes; neither too many
(checked by rtp->nr == 0), nor too few (checked by comparing
nr_allocated before and after the call to radix_tree_split()).
Link: http://lkml.kernel.org/r/1480369871-5271-60-git-send-email-mawilcox@linuxonhyperv.com
Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
Tested-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Cc: Matthew Wilcox <mawilcox@microsoft.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/testing/radix-tree/multiorder.c | 42 | ||||
-rw-r--r-- | tools/testing/radix-tree/test.h | 5 |
2 files changed, 45 insertions, 2 deletions
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c index fa6effe997a3..5421f015f46c 100644 --- a/tools/testing/radix-tree/multiorder.c +++ b/tools/testing/radix-tree/multiorder.c | |||
@@ -389,35 +389,67 @@ static void multiorder_join(void) | |||
389 | } | 389 | } |
390 | } | 390 | } |
391 | 391 | ||
392 | static void check_mem(unsigned old_order, unsigned new_order, unsigned alloc) | ||
393 | { | ||
394 | struct radix_tree_preload *rtp = &radix_tree_preloads; | ||
395 | if (rtp->nr != 0) | ||
396 | printf("split(%u %u) remaining %u\n", old_order, new_order, | ||
397 | rtp->nr); | ||
398 | /* | ||
399 | * Can't check for equality here as some nodes may have been | ||
400 | * RCU-freed while we ran. But we should never finish with more | ||
401 | * nodes allocated since they should have all been preloaded. | ||
402 | */ | ||
403 | if (nr_allocated > alloc) | ||
404 | printf("split(%u %u) allocated %u %u\n", old_order, new_order, | ||
405 | alloc, nr_allocated); | ||
406 | } | ||
407 | |||
392 | static void __multiorder_split(int old_order, int new_order) | 408 | static void __multiorder_split(int old_order, int new_order) |
393 | { | 409 | { |
394 | RADIX_TREE(tree, GFP_KERNEL); | 410 | RADIX_TREE(tree, GFP_ATOMIC); |
395 | void **slot; | 411 | void **slot; |
396 | struct radix_tree_iter iter; | 412 | struct radix_tree_iter iter; |
397 | struct radix_tree_node *node; | 413 | struct radix_tree_node *node; |
398 | void *item; | 414 | void *item; |
415 | unsigned alloc; | ||
416 | |||
417 | radix_tree_preload(GFP_KERNEL); | ||
418 | assert(item_insert_order(&tree, 0, old_order) == 0); | ||
419 | radix_tree_preload_end(); | ||
420 | |||
421 | /* Wipe out the preloaded cache or it'll confuse check_mem() */ | ||
422 | radix_tree_cpu_dead(0); | ||
399 | 423 | ||
400 | item_insert_order(&tree, 0, old_order); | ||
401 | radix_tree_tag_set(&tree, 0, 2); | 424 | radix_tree_tag_set(&tree, 0, 2); |
425 | |||
426 | radix_tree_split_preload(old_order, new_order, GFP_KERNEL); | ||
427 | alloc = nr_allocated; | ||
402 | radix_tree_split(&tree, 0, new_order); | 428 | radix_tree_split(&tree, 0, new_order); |
429 | check_mem(old_order, new_order, alloc); | ||
403 | radix_tree_for_each_slot(slot, &tree, &iter, 0) { | 430 | radix_tree_for_each_slot(slot, &tree, &iter, 0) { |
404 | radix_tree_iter_replace(&tree, &iter, slot, | 431 | radix_tree_iter_replace(&tree, &iter, slot, |
405 | item_create(iter.index, new_order)); | 432 | item_create(iter.index, new_order)); |
406 | } | 433 | } |
434 | radix_tree_preload_end(); | ||
407 | 435 | ||
408 | item_kill_tree(&tree); | 436 | item_kill_tree(&tree); |
409 | 437 | ||
438 | radix_tree_preload(GFP_KERNEL); | ||
410 | __radix_tree_insert(&tree, 0, old_order, (void *)0x12); | 439 | __radix_tree_insert(&tree, 0, old_order, (void *)0x12); |
440 | radix_tree_preload_end(); | ||
411 | 441 | ||
412 | item = __radix_tree_lookup(&tree, 0, &node, NULL); | 442 | item = __radix_tree_lookup(&tree, 0, &node, NULL); |
413 | assert(item == (void *)0x12); | 443 | assert(item == (void *)0x12); |
414 | assert(node->exceptional > 0); | 444 | assert(node->exceptional > 0); |
415 | 445 | ||
446 | radix_tree_split_preload(old_order, new_order, GFP_KERNEL); | ||
416 | radix_tree_split(&tree, 0, new_order); | 447 | radix_tree_split(&tree, 0, new_order); |
417 | radix_tree_for_each_slot(slot, &tree, &iter, 0) { | 448 | radix_tree_for_each_slot(slot, &tree, &iter, 0) { |
418 | radix_tree_iter_replace(&tree, &iter, slot, | 449 | radix_tree_iter_replace(&tree, &iter, slot, |
419 | item_create(iter.index, new_order)); | 450 | item_create(iter.index, new_order)); |
420 | } | 451 | } |
452 | radix_tree_preload_end(); | ||
421 | 453 | ||
422 | item = __radix_tree_lookup(&tree, 0, &node, NULL); | 454 | item = __radix_tree_lookup(&tree, 0, &node, NULL); |
423 | assert(item != (void *)0x12); | 455 | assert(item != (void *)0x12); |
@@ -425,16 +457,20 @@ static void __multiorder_split(int old_order, int new_order) | |||
425 | 457 | ||
426 | item_kill_tree(&tree); | 458 | item_kill_tree(&tree); |
427 | 459 | ||
460 | radix_tree_preload(GFP_KERNEL); | ||
428 | __radix_tree_insert(&tree, 0, old_order, (void *)0x12); | 461 | __radix_tree_insert(&tree, 0, old_order, (void *)0x12); |
462 | radix_tree_preload_end(); | ||
429 | 463 | ||
430 | item = __radix_tree_lookup(&tree, 0, &node, NULL); | 464 | item = __radix_tree_lookup(&tree, 0, &node, NULL); |
431 | assert(item == (void *)0x12); | 465 | assert(item == (void *)0x12); |
432 | assert(node->exceptional > 0); | 466 | assert(node->exceptional > 0); |
433 | 467 | ||
468 | radix_tree_split_preload(old_order, new_order, GFP_KERNEL); | ||
434 | radix_tree_split(&tree, 0, new_order); | 469 | radix_tree_split(&tree, 0, new_order); |
435 | radix_tree_for_each_slot(slot, &tree, &iter, 0) { | 470 | radix_tree_for_each_slot(slot, &tree, &iter, 0) { |
436 | radix_tree_iter_replace(&tree, &iter, slot, (void *)0x16); | 471 | radix_tree_iter_replace(&tree, &iter, slot, (void *)0x16); |
437 | } | 472 | } |
473 | radix_tree_preload_end(); | ||
438 | 474 | ||
439 | item = __radix_tree_lookup(&tree, 0, &node, NULL); | 475 | item = __radix_tree_lookup(&tree, 0, &node, NULL); |
440 | assert(item == (void *)0x16); | 476 | assert(item == (void *)0x16); |
@@ -471,4 +507,6 @@ void multiorder_checks(void) | |||
471 | multiorder_tagged_iteration(); | 507 | multiorder_tagged_iteration(); |
472 | multiorder_join(); | 508 | multiorder_join(); |
473 | multiorder_split(); | 509 | multiorder_split(); |
510 | |||
511 | radix_tree_cpu_dead(0); | ||
474 | } | 512 | } |
diff --git a/tools/testing/radix-tree/test.h b/tools/testing/radix-tree/test.h index e11e4d260b4e..7c2611caa6d2 100644 --- a/tools/testing/radix-tree/test.h +++ b/tools/testing/radix-tree/test.h | |||
@@ -52,3 +52,8 @@ int root_tag_get(struct radix_tree_root *root, unsigned int tag); | |||
52 | unsigned long node_maxindex(struct radix_tree_node *); | 52 | unsigned long node_maxindex(struct radix_tree_node *); |
53 | unsigned long shift_maxindex(unsigned int shift); | 53 | unsigned long shift_maxindex(unsigned int shift); |
54 | int radix_tree_cpu_dead(unsigned int cpu); | 54 | int radix_tree_cpu_dead(unsigned int cpu); |
55 | struct radix_tree_preload { | ||
56 | unsigned nr; | ||
57 | struct radix_tree_node *nodes; | ||
58 | }; | ||
59 | extern struct radix_tree_preload radix_tree_preloads; | ||