diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig.debug | 18 | ||||
-rw-r--r-- | lib/radix-tree.c | 132 |
2 files changed, 118 insertions, 32 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 396c38b3cb69..7d16e6433302 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -413,6 +413,24 @@ config FORCED_INLINING | |||
413 | become the default in the future, until then this option is there to | 413 | become the default in the future, until then this option is there to |
414 | test gcc for this. | 414 | test gcc for this. |
415 | 415 | ||
416 | config BOOT_PRINTK_DELAY | ||
417 | bool "Delay each boot printk message by N milliseconds" | ||
418 | depends on DEBUG_KERNEL && PRINTK && GENERIC_CALIBRATE_DELAY | ||
419 | help | ||
420 | This build option allows you to read kernel boot messages | ||
421 | by inserting a short delay after each one. The delay is | ||
422 | specified in milliseconds on the kernel command line, | ||
423 | using "boot_delay=N". | ||
424 | |||
425 | It is likely that you would also need to use "lpj=M" to preset | ||
426 | the "loops per jiffie" value. | ||
427 | See a previous boot log for the "lpj" value to use for your | ||
428 | system, and then set "lpj=M" before setting "boot_delay=N". | ||
429 | NOTE: Using this option may adversely affect SMP systems. | ||
430 | I.e., processors other than the first one may not boot up. | ||
431 | BOOT_PRINTK_DELAY also may cause DETECT_SOFTLOCKUP to detect | ||
432 | what it believes to be lockup conditions. | ||
433 | |||
416 | config RCU_TORTURE_TEST | 434 | config RCU_TORTURE_TEST |
417 | tristate "torture tests for RCU" | 435 | tristate "torture tests for RCU" |
418 | depends on DEBUG_KERNEL | 436 | depends on DEBUG_KERNEL |
diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 514efb200be6..6b26f9d39800 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c | |||
@@ -60,9 +60,14 @@ struct radix_tree_path { | |||
60 | }; | 60 | }; |
61 | 61 | ||
62 | #define RADIX_TREE_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(unsigned long)) | 62 | #define RADIX_TREE_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(unsigned long)) |
63 | #define RADIX_TREE_MAX_PATH (RADIX_TREE_INDEX_BITS/RADIX_TREE_MAP_SHIFT + 2) | 63 | #define RADIX_TREE_MAX_PATH (DIV_ROUND_UP(RADIX_TREE_INDEX_BITS, \ |
64 | RADIX_TREE_MAP_SHIFT)) | ||
64 | 65 | ||
65 | static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH] __read_mostly; | 66 | /* |
67 | * The height_to_maxindex array needs to be one deeper than the maximum | ||
68 | * path as height 0 holds only 1 entry. | ||
69 | */ | ||
70 | static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH + 1] __read_mostly; | ||
66 | 71 | ||
67 | /* | 72 | /* |
68 | * Radix tree node cache. | 73 | * Radix tree node cache. |
@@ -93,7 +98,8 @@ radix_tree_node_alloc(struct radix_tree_root *root) | |||
93 | struct radix_tree_node *ret; | 98 | struct radix_tree_node *ret; |
94 | gfp_t gfp_mask = root_gfp_mask(root); | 99 | gfp_t gfp_mask = root_gfp_mask(root); |
95 | 100 | ||
96 | ret = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask); | 101 | ret = kmem_cache_alloc(radix_tree_node_cachep, |
102 | set_migrateflags(gfp_mask, __GFP_RECLAIMABLE)); | ||
97 | if (ret == NULL && !(gfp_mask & __GFP_WAIT)) { | 103 | if (ret == NULL && !(gfp_mask & __GFP_WAIT)) { |
98 | struct radix_tree_preload *rtp; | 104 | struct radix_tree_preload *rtp; |
99 | 105 | ||
@@ -104,7 +110,7 @@ radix_tree_node_alloc(struct radix_tree_root *root) | |||
104 | rtp->nr--; | 110 | rtp->nr--; |
105 | } | 111 | } |
106 | } | 112 | } |
107 | BUG_ON(radix_tree_is_direct_ptr(ret)); | 113 | BUG_ON(radix_tree_is_indirect_ptr(ret)); |
108 | return ret; | 114 | return ret; |
109 | } | 115 | } |
110 | 116 | ||
@@ -137,7 +143,8 @@ int radix_tree_preload(gfp_t gfp_mask) | |||
137 | rtp = &__get_cpu_var(radix_tree_preloads); | 143 | rtp = &__get_cpu_var(radix_tree_preloads); |
138 | while (rtp->nr < ARRAY_SIZE(rtp->nodes)) { | 144 | while (rtp->nr < ARRAY_SIZE(rtp->nodes)) { |
139 | preempt_enable(); | 145 | preempt_enable(); |
140 | node = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask); | 146 | node = kmem_cache_alloc(radix_tree_node_cachep, |
147 | set_migrateflags(gfp_mask, __GFP_RECLAIMABLE)); | ||
141 | if (node == NULL) | 148 | if (node == NULL) |
142 | goto out; | 149 | goto out; |
143 | preempt_disable(); | 150 | preempt_disable(); |
@@ -240,7 +247,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) | |||
240 | return -ENOMEM; | 247 | return -ENOMEM; |
241 | 248 | ||
242 | /* Increase the height. */ | 249 | /* Increase the height. */ |
243 | node->slots[0] = radix_tree_direct_to_ptr(root->rnode); | 250 | node->slots[0] = radix_tree_indirect_to_ptr(root->rnode); |
244 | 251 | ||
245 | /* Propagate the aggregated tag info into the new root */ | 252 | /* Propagate the aggregated tag info into the new root */ |
246 | for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { | 253 | for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) { |
@@ -251,6 +258,7 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) | |||
251 | newheight = root->height+1; | 258 | newheight = root->height+1; |
252 | node->height = newheight; | 259 | node->height = newheight; |
253 | node->count = 1; | 260 | node->count = 1; |
261 | node = radix_tree_ptr_to_indirect(node); | ||
254 | rcu_assign_pointer(root->rnode, node); | 262 | rcu_assign_pointer(root->rnode, node); |
255 | root->height = newheight; | 263 | root->height = newheight; |
256 | } while (height > root->height); | 264 | } while (height > root->height); |
@@ -274,7 +282,7 @@ int radix_tree_insert(struct radix_tree_root *root, | |||
274 | int offset; | 282 | int offset; |
275 | int error; | 283 | int error; |
276 | 284 | ||
277 | BUG_ON(radix_tree_is_direct_ptr(item)); | 285 | BUG_ON(radix_tree_is_indirect_ptr(item)); |
278 | 286 | ||
279 | /* Make sure the tree is high enough. */ | 287 | /* Make sure the tree is high enough. */ |
280 | if (index > radix_tree_maxindex(root->height)) { | 288 | if (index > radix_tree_maxindex(root->height)) { |
@@ -283,7 +291,8 @@ int radix_tree_insert(struct radix_tree_root *root, | |||
283 | return error; | 291 | return error; |
284 | } | 292 | } |
285 | 293 | ||
286 | slot = root->rnode; | 294 | slot = radix_tree_indirect_to_ptr(root->rnode); |
295 | |||
287 | height = root->height; | 296 | height = root->height; |
288 | shift = (height-1) * RADIX_TREE_MAP_SHIFT; | 297 | shift = (height-1) * RADIX_TREE_MAP_SHIFT; |
289 | 298 | ||
@@ -298,7 +307,8 @@ int radix_tree_insert(struct radix_tree_root *root, | |||
298 | rcu_assign_pointer(node->slots[offset], slot); | 307 | rcu_assign_pointer(node->slots[offset], slot); |
299 | node->count++; | 308 | node->count++; |
300 | } else | 309 | } else |
301 | rcu_assign_pointer(root->rnode, slot); | 310 | rcu_assign_pointer(root->rnode, |
311 | radix_tree_ptr_to_indirect(slot)); | ||
302 | } | 312 | } |
303 | 313 | ||
304 | /* Go a level down */ | 314 | /* Go a level down */ |
@@ -318,7 +328,7 @@ int radix_tree_insert(struct radix_tree_root *root, | |||
318 | BUG_ON(tag_get(node, 0, offset)); | 328 | BUG_ON(tag_get(node, 0, offset)); |
319 | BUG_ON(tag_get(node, 1, offset)); | 329 | BUG_ON(tag_get(node, 1, offset)); |
320 | } else { | 330 | } else { |
321 | rcu_assign_pointer(root->rnode, radix_tree_ptr_to_direct(item)); | 331 | rcu_assign_pointer(root->rnode, item); |
322 | BUG_ON(root_tag_get(root, 0)); | 332 | BUG_ON(root_tag_get(root, 0)); |
323 | BUG_ON(root_tag_get(root, 1)); | 333 | BUG_ON(root_tag_get(root, 1)); |
324 | } | 334 | } |
@@ -350,11 +360,12 @@ void **radix_tree_lookup_slot(struct radix_tree_root *root, unsigned long index) | |||
350 | if (node == NULL) | 360 | if (node == NULL) |
351 | return NULL; | 361 | return NULL; |
352 | 362 | ||
353 | if (radix_tree_is_direct_ptr(node)) { | 363 | if (!radix_tree_is_indirect_ptr(node)) { |
354 | if (index > 0) | 364 | if (index > 0) |
355 | return NULL; | 365 | return NULL; |
356 | return (void **)&root->rnode; | 366 | return (void **)&root->rnode; |
357 | } | 367 | } |
368 | node = radix_tree_indirect_to_ptr(node); | ||
358 | 369 | ||
359 | height = node->height; | 370 | height = node->height; |
360 | if (index > radix_tree_maxindex(height)) | 371 | if (index > radix_tree_maxindex(height)) |
@@ -398,11 +409,12 @@ void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index) | |||
398 | if (node == NULL) | 409 | if (node == NULL) |
399 | return NULL; | 410 | return NULL; |
400 | 411 | ||
401 | if (radix_tree_is_direct_ptr(node)) { | 412 | if (!radix_tree_is_indirect_ptr(node)) { |
402 | if (index > 0) | 413 | if (index > 0) |
403 | return NULL; | 414 | return NULL; |
404 | return radix_tree_direct_to_ptr(node); | 415 | return node; |
405 | } | 416 | } |
417 | node = radix_tree_indirect_to_ptr(node); | ||
406 | 418 | ||
407 | height = node->height; | 419 | height = node->height; |
408 | if (index > radix_tree_maxindex(height)) | 420 | if (index > radix_tree_maxindex(height)) |
@@ -447,7 +459,7 @@ void *radix_tree_tag_set(struct radix_tree_root *root, | |||
447 | height = root->height; | 459 | height = root->height; |
448 | BUG_ON(index > radix_tree_maxindex(height)); | 460 | BUG_ON(index > radix_tree_maxindex(height)); |
449 | 461 | ||
450 | slot = root->rnode; | 462 | slot = radix_tree_indirect_to_ptr(root->rnode); |
451 | shift = (height - 1) * RADIX_TREE_MAP_SHIFT; | 463 | shift = (height - 1) * RADIX_TREE_MAP_SHIFT; |
452 | 464 | ||
453 | while (height > 0) { | 465 | while (height > 0) { |
@@ -487,7 +499,11 @@ EXPORT_SYMBOL(radix_tree_tag_set); | |||
487 | void *radix_tree_tag_clear(struct radix_tree_root *root, | 499 | void *radix_tree_tag_clear(struct radix_tree_root *root, |
488 | unsigned long index, unsigned int tag) | 500 | unsigned long index, unsigned int tag) |
489 | { | 501 | { |
490 | struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path; | 502 | /* |
503 | * The radix tree path needs to be one longer than the maximum path | ||
504 | * since the "list" is null terminated. | ||
505 | */ | ||
506 | struct radix_tree_path path[RADIX_TREE_MAX_PATH + 1], *pathp = path; | ||
491 | struct radix_tree_node *slot = NULL; | 507 | struct radix_tree_node *slot = NULL; |
492 | unsigned int height, shift; | 508 | unsigned int height, shift; |
493 | 509 | ||
@@ -497,7 +513,7 @@ void *radix_tree_tag_clear(struct radix_tree_root *root, | |||
497 | 513 | ||
498 | shift = (height - 1) * RADIX_TREE_MAP_SHIFT; | 514 | shift = (height - 1) * RADIX_TREE_MAP_SHIFT; |
499 | pathp->node = NULL; | 515 | pathp->node = NULL; |
500 | slot = root->rnode; | 516 | slot = radix_tree_indirect_to_ptr(root->rnode); |
501 | 517 | ||
502 | while (height > 0) { | 518 | while (height > 0) { |
503 | int offset; | 519 | int offset; |
@@ -562,8 +578,9 @@ int radix_tree_tag_get(struct radix_tree_root *root, | |||
562 | if (node == NULL) | 578 | if (node == NULL) |
563 | return 0; | 579 | return 0; |
564 | 580 | ||
565 | if (radix_tree_is_direct_ptr(node)) | 581 | if (!radix_tree_is_indirect_ptr(node)) |
566 | return (index == 0); | 582 | return (index == 0); |
583 | node = radix_tree_indirect_to_ptr(node); | ||
567 | 584 | ||
568 | height = node->height; | 585 | height = node->height; |
569 | if (index > radix_tree_maxindex(height)) | 586 | if (index > radix_tree_maxindex(height)) |
@@ -599,6 +616,42 @@ int radix_tree_tag_get(struct radix_tree_root *root, | |||
599 | EXPORT_SYMBOL(radix_tree_tag_get); | 616 | EXPORT_SYMBOL(radix_tree_tag_get); |
600 | #endif | 617 | #endif |
601 | 618 | ||
619 | /** | ||
620 | * radix_tree_next_hole - find the next hole (not-present entry) | ||
621 | * @root: tree root | ||
622 | * @index: index key | ||
623 | * @max_scan: maximum range to search | ||
624 | * | ||
625 | * Search the set [index, min(index+max_scan-1, MAX_INDEX)] for the lowest | ||
626 | * indexed hole. | ||
627 | * | ||
628 | * Returns: the index of the hole if found, otherwise returns an index | ||
629 | * outside of the set specified (in which case 'return - index >= max_scan' | ||
630 | * will be true). | ||
631 | * | ||
632 | * radix_tree_next_hole may be called under rcu_read_lock. However, like | ||
633 | * radix_tree_gang_lookup, this will not atomically search a snapshot of the | ||
634 | * tree at a single point in time. For example, if a hole is created at index | ||
635 | * 5, then subsequently a hole is created at index 10, radix_tree_next_hole | ||
636 | * covering both indexes may return 10 if called under rcu_read_lock. | ||
637 | */ | ||
638 | unsigned long radix_tree_next_hole(struct radix_tree_root *root, | ||
639 | unsigned long index, unsigned long max_scan) | ||
640 | { | ||
641 | unsigned long i; | ||
642 | |||
643 | for (i = 0; i < max_scan; i++) { | ||
644 | if (!radix_tree_lookup(root, index)) | ||
645 | break; | ||
646 | index++; | ||
647 | if (index == 0) | ||
648 | break; | ||
649 | } | ||
650 | |||
651 | return index; | ||
652 | } | ||
653 | EXPORT_SYMBOL(radix_tree_next_hole); | ||
654 | |||
602 | static unsigned int | 655 | static unsigned int |
603 | __lookup(struct radix_tree_node *slot, void **results, unsigned long index, | 656 | __lookup(struct radix_tree_node *slot, void **results, unsigned long index, |
604 | unsigned int max_items, unsigned long *next_index) | 657 | unsigned int max_items, unsigned long *next_index) |
@@ -680,13 +733,13 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results, | |||
680 | if (!node) | 733 | if (!node) |
681 | return 0; | 734 | return 0; |
682 | 735 | ||
683 | if (radix_tree_is_direct_ptr(node)) { | 736 | if (!radix_tree_is_indirect_ptr(node)) { |
684 | if (first_index > 0) | 737 | if (first_index > 0) |
685 | return 0; | 738 | return 0; |
686 | node = radix_tree_direct_to_ptr(node); | 739 | results[0] = node; |
687 | results[0] = rcu_dereference(node); | ||
688 | return 1; | 740 | return 1; |
689 | } | 741 | } |
742 | node = radix_tree_indirect_to_ptr(node); | ||
690 | 743 | ||
691 | max_index = radix_tree_maxindex(node->height); | 744 | max_index = radix_tree_maxindex(node->height); |
692 | 745 | ||
@@ -808,13 +861,13 @@ radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results, | |||
808 | if (!node) | 861 | if (!node) |
809 | return 0; | 862 | return 0; |
810 | 863 | ||
811 | if (radix_tree_is_direct_ptr(node)) { | 864 | if (!radix_tree_is_indirect_ptr(node)) { |
812 | if (first_index > 0) | 865 | if (first_index > 0) |
813 | return 0; | 866 | return 0; |
814 | node = radix_tree_direct_to_ptr(node); | 867 | results[0] = node; |
815 | results[0] = rcu_dereference(node); | ||
816 | return 1; | 868 | return 1; |
817 | } | 869 | } |
870 | node = radix_tree_indirect_to_ptr(node); | ||
818 | 871 | ||
819 | max_index = radix_tree_maxindex(node->height); | 872 | max_index = radix_tree_maxindex(node->height); |
820 | 873 | ||
@@ -844,12 +897,22 @@ EXPORT_SYMBOL(radix_tree_gang_lookup_tag); | |||
844 | static inline void radix_tree_shrink(struct radix_tree_root *root) | 897 | static inline void radix_tree_shrink(struct radix_tree_root *root) |
845 | { | 898 | { |
846 | /* try to shrink tree height */ | 899 | /* try to shrink tree height */ |
847 | while (root->height > 0 && | 900 | while (root->height > 0) { |
848 | root->rnode->count == 1 && | ||
849 | root->rnode->slots[0]) { | ||
850 | struct radix_tree_node *to_free = root->rnode; | 901 | struct radix_tree_node *to_free = root->rnode; |
851 | void *newptr; | 902 | void *newptr; |
852 | 903 | ||
904 | BUG_ON(!radix_tree_is_indirect_ptr(to_free)); | ||
905 | to_free = radix_tree_indirect_to_ptr(to_free); | ||
906 | |||
907 | /* | ||
908 | * The candidate node has more than one child, or its child | ||
909 | * is not at the leftmost slot, we cannot shrink. | ||
910 | */ | ||
911 | if (to_free->count != 1) | ||
912 | break; | ||
913 | if (!to_free->slots[0]) | ||
914 | break; | ||
915 | |||
853 | /* | 916 | /* |
854 | * We don't need rcu_assign_pointer(), since we are simply | 917 | * We don't need rcu_assign_pointer(), since we are simply |
855 | * moving the node from one part of the tree to another. If | 918 | * moving the node from one part of the tree to another. If |
@@ -858,8 +921,8 @@ static inline void radix_tree_shrink(struct radix_tree_root *root) | |||
858 | * one (root->rnode). | 921 | * one (root->rnode). |
859 | */ | 922 | */ |
860 | newptr = to_free->slots[0]; | 923 | newptr = to_free->slots[0]; |
861 | if (root->height == 1) | 924 | if (root->height > 1) |
862 | newptr = radix_tree_ptr_to_direct(newptr); | 925 | newptr = radix_tree_ptr_to_indirect(newptr); |
863 | root->rnode = newptr; | 926 | root->rnode = newptr; |
864 | root->height--; | 927 | root->height--; |
865 | /* must only free zeroed nodes into the slab */ | 928 | /* must only free zeroed nodes into the slab */ |
@@ -882,7 +945,11 @@ static inline void radix_tree_shrink(struct radix_tree_root *root) | |||
882 | */ | 945 | */ |
883 | void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) | 946 | void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) |
884 | { | 947 | { |
885 | struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path; | 948 | /* |
949 | * The radix tree path needs to be one longer than the maximum path | ||
950 | * since the "list" is null terminated. | ||
951 | */ | ||
952 | struct radix_tree_path path[RADIX_TREE_MAX_PATH + 1], *pathp = path; | ||
886 | struct radix_tree_node *slot = NULL; | 953 | struct radix_tree_node *slot = NULL; |
887 | struct radix_tree_node *to_free; | 954 | struct radix_tree_node *to_free; |
888 | unsigned int height, shift; | 955 | unsigned int height, shift; |
@@ -894,12 +961,12 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) | |||
894 | goto out; | 961 | goto out; |
895 | 962 | ||
896 | slot = root->rnode; | 963 | slot = root->rnode; |
897 | if (height == 0 && root->rnode) { | 964 | if (height == 0) { |
898 | slot = radix_tree_direct_to_ptr(slot); | ||
899 | root_tag_clear_all(root); | 965 | root_tag_clear_all(root); |
900 | root->rnode = NULL; | 966 | root->rnode = NULL; |
901 | goto out; | 967 | goto out; |
902 | } | 968 | } |
969 | slot = radix_tree_indirect_to_ptr(slot); | ||
903 | 970 | ||
904 | shift = (height - 1) * RADIX_TREE_MAP_SHIFT; | 971 | shift = (height - 1) * RADIX_TREE_MAP_SHIFT; |
905 | pathp->node = NULL; | 972 | pathp->node = NULL; |
@@ -941,7 +1008,8 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index) | |||
941 | radix_tree_node_free(to_free); | 1008 | radix_tree_node_free(to_free); |
942 | 1009 | ||
943 | if (pathp->node->count) { | 1010 | if (pathp->node->count) { |
944 | if (pathp->node == root->rnode) | 1011 | if (pathp->node == |
1012 | radix_tree_indirect_to_ptr(root->rnode)) | ||
945 | radix_tree_shrink(root); | 1013 | radix_tree_shrink(root); |
946 | goto out; | 1014 | goto out; |
947 | } | 1015 | } |