aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/radix-tree.c14
-rw-r--r--tools/testing/radix-tree/multiorder.c12
2 files changed, 22 insertions, 4 deletions
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index f14ada9830ca..ff460423ff4b 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -165,6 +165,11 @@ static inline int root_tag_get(struct radix_tree_root *root, unsigned int tag)
165 return (__force unsigned)root->gfp_mask & (1 << (tag + __GFP_BITS_SHIFT)); 165 return (__force unsigned)root->gfp_mask & (1 << (tag + __GFP_BITS_SHIFT));
166} 166}
167 167
168static inline unsigned root_tags_get(struct radix_tree_root *root)
169{
170 return (__force unsigned)root->gfp_mask >> __GFP_BITS_SHIFT;
171}
172
168/* 173/*
169 * Returns 1 if any slot in the node has this tag set. 174 * Returns 1 if any slot in the node has this tag set.
170 * Otherwise returns 0. 175 * Otherwise returns 0.
@@ -604,12 +609,13 @@ int __radix_tree_insert(struct radix_tree_root *root, unsigned long index,
604 rcu_assign_pointer(*slot, item); 609 rcu_assign_pointer(*slot, item);
605 610
606 if (node) { 611 if (node) {
612 unsigned offset = get_slot_offset(node, slot);
607 node->count++; 613 node->count++;
608 BUG_ON(tag_get(node, 0, index & RADIX_TREE_MAP_MASK)); 614 BUG_ON(tag_get(node, 0, offset));
609 BUG_ON(tag_get(node, 1, index & RADIX_TREE_MAP_MASK)); 615 BUG_ON(tag_get(node, 1, offset));
616 BUG_ON(tag_get(node, 2, offset));
610 } else { 617 } else {
611 BUG_ON(root_tag_get(root, 0)); 618 BUG_ON(root_tags_get(root));
612 BUG_ON(root_tag_get(root, 1));
613 } 619 }
614 620
615 return 0; 621 return 0;
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c
index 71f34a047002..0a311a5f39de 100644
--- a/tools/testing/radix-tree/multiorder.c
+++ b/tools/testing/radix-tree/multiorder.c
@@ -81,6 +81,17 @@ static void multiorder_shrink(unsigned long index, int order)
81 item_check_absent(&tree, i); 81 item_check_absent(&tree, i);
82} 82}
83 83
84static void multiorder_insert_bug(void)
85{
86 RADIX_TREE(tree, GFP_KERNEL);
87
88 item_insert(&tree, 0);
89 radix_tree_tag_set(&tree, 0, 0);
90 item_insert_order(&tree, 3 << 6, 6);
91
92 item_kill_tree(&tree);
93}
94
84void multiorder_checks(void) 95void multiorder_checks(void)
85{ 96{
86 int i; 97 int i;
@@ -94,4 +105,5 @@ void multiorder_checks(void)
94 for (i = 0; i < 15; i++) 105 for (i = 0; i < 15; i++)
95 multiorder_shrink((1UL << (i + RADIX_TREE_MAP_SHIFT)), i); 106 multiorder_shrink((1UL << (i + RADIX_TREE_MAP_SHIFT)), i);
96 107
108 multiorder_insert_bug();
97} 109}