Commit 8c1244de authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Linus Torvalds

radix-tree: tidy up next_chunk

Convert radix_tree_next_chunk to use 'child' instead of 'slot' as the
name of the child node.  Also use node_maxindex() where it makes sense.

The 'rnode' variable was unnecessary; it doesn't overlap in usage with
'node', so we can just use 'node' the whole way through the function.

Improve the testcase to start the walk from every index in the carefully
constructed tree, and to accept any index within the range covered by
the entry.
Signed-off-by: default avatarMatthew Wilcox <willy@linux.intel.com>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Cc: Kirill Shutemov <kirill.shutemov@linux.intel.com>
Cc: Jan Kara <jack@suse.com>
Cc: Neil Brown <neilb@suse.de>
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent af49a63e
...@@ -876,7 +876,7 @@ void **radix_tree_next_chunk(struct radix_tree_root *root, ...@@ -876,7 +876,7 @@ void **radix_tree_next_chunk(struct radix_tree_root *root,
struct radix_tree_iter *iter, unsigned flags) struct radix_tree_iter *iter, unsigned flags)
{ {
unsigned shift, tag = flags & RADIX_TREE_ITER_TAG_MASK; unsigned shift, tag = flags & RADIX_TREE_ITER_TAG_MASK;
struct radix_tree_node *rnode, *node; struct radix_tree_node *node, *child;
unsigned long index, offset, maxindex; unsigned long index, offset, maxindex;
if ((flags & RADIX_TREE_ITER_TAGGED) && !root_tag_get(root, tag)) if ((flags & RADIX_TREE_ITER_TAGGED) && !root_tag_get(root, tag))
...@@ -896,38 +896,29 @@ void **radix_tree_next_chunk(struct radix_tree_root *root, ...@@ -896,38 +896,29 @@ void **radix_tree_next_chunk(struct radix_tree_root *root,
return NULL; return NULL;
restart: restart:
shift = radix_tree_load_root(root, &rnode, &maxindex); shift = radix_tree_load_root(root, &child, &maxindex);
if (index > maxindex) if (index > maxindex)
return NULL; return NULL;
if (!child)
return NULL;
if (radix_tree_is_internal_node(rnode)) { if (!radix_tree_is_internal_node(child)) {
rnode = entry_to_node(rnode);
} else if (rnode) {
/* Single-slot tree */ /* Single-slot tree */
iter->index = index; iter->index = index;
iter->next_index = maxindex + 1; iter->next_index = maxindex + 1;
iter->tags = 1; iter->tags = 1;
__set_iter_shift(iter, shift); __set_iter_shift(iter, 0);
return (void **)&root->rnode; return (void **)&root->rnode;
} else }
return NULL;
do {
node = entry_to_node(child);
shift -= RADIX_TREE_MAP_SHIFT; shift -= RADIX_TREE_MAP_SHIFT;
offset = index >> shift; offset = (index >> shift) & RADIX_TREE_MAP_MASK;
offset = radix_tree_descend(node, &child, offset);
node = rnode;
while (1) {
struct radix_tree_node *slot;
unsigned new_off = radix_tree_descend(node, &slot, offset);
if (new_off < offset) {
offset = new_off;
index &= ~((RADIX_TREE_MAP_SIZE << shift) - 1);
index |= offset << shift;
}
if ((flags & RADIX_TREE_ITER_TAGGED) ? if ((flags & RADIX_TREE_ITER_TAGGED) ?
!tag_get(node, tag, offset) : !slot) { !tag_get(node, tag, offset) : !child) {
/* Hole detected */ /* Hole detected */
if (flags & RADIX_TREE_ITER_CONTIG) if (flags & RADIX_TREE_ITER_CONTIG)
return NULL; return NULL;
...@@ -945,29 +936,23 @@ void **radix_tree_next_chunk(struct radix_tree_root *root, ...@@ -945,29 +936,23 @@ void **radix_tree_next_chunk(struct radix_tree_root *root,
if (slot) if (slot)
break; break;
} }
index &= ~((RADIX_TREE_MAP_SIZE << shift) - 1); index &= ~node_maxindex(node);
index += offset << shift; index += offset << shift;
/* Overflow after ~0UL */ /* Overflow after ~0UL */
if (!index) if (!index)
return NULL; return NULL;
if (offset == RADIX_TREE_MAP_SIZE) if (offset == RADIX_TREE_MAP_SIZE)
goto restart; goto restart;
slot = rcu_dereference_raw(node->slots[offset]); child = rcu_dereference_raw(node->slots[offset]);
} }
if ((slot == NULL) || (slot == RADIX_TREE_RETRY)) if ((child == NULL) || (child == RADIX_TREE_RETRY))
goto restart; goto restart;
if (!radix_tree_is_internal_node(slot)) } while (radix_tree_is_internal_node(child));
break;
node = entry_to_node(slot);
shift -= RADIX_TREE_MAP_SHIFT;
offset = (index >> shift) & RADIX_TREE_MAP_MASK;
}
/* Update the iterator state */ /* Update the iterator state */
iter->index = index & ~((1 << shift) - 1); iter->index = (index &~ node_maxindex(node)) | (offset << node->shift);
iter->next_index = (index | ((RADIX_TREE_MAP_SIZE << shift) - 1)) + 1; iter->next_index = (index | node_maxindex(node)) + 1;
__set_iter_shift(iter, shift); __set_iter_shift(iter, shift);
/* Construct iter->tags bit-mask from node->tags[tag] array */ /* Construct iter->tags bit-mask from node->tags[tag] array */
......
...@@ -202,7 +202,7 @@ void multiorder_iteration(void) ...@@ -202,7 +202,7 @@ void multiorder_iteration(void)
RADIX_TREE(tree, GFP_KERNEL); RADIX_TREE(tree, GFP_KERNEL);
struct radix_tree_iter iter; struct radix_tree_iter iter;
void **slot; void **slot;
int i, err; int i, j, err;
printf("Multiorder iteration test\n"); printf("Multiorder iteration test\n");
...@@ -215,30 +215,22 @@ void multiorder_iteration(void) ...@@ -215,30 +215,22 @@ void multiorder_iteration(void)
assert(!err); assert(!err);
} }
i = 0; for (j = 0; j < 256; j++) {
/* start from index 1 to verify we find the multi-order entry at 0 */ for (i = 0; i < NUM_ENTRIES; i++)
radix_tree_for_each_slot(slot, &tree, &iter, 1) { if (j <= (index[i] | ((1 << order[i]) - 1)))
int height = order[i] / RADIX_TREE_MAP_SHIFT; break;
int shift = height * RADIX_TREE_MAP_SHIFT;
assert(iter.index == index[i]);
assert(iter.shift == shift);
i++;
}
/* radix_tree_for_each_slot(slot, &tree, &iter, j) {
* Now iterate through the tree starting at an elevated multi-order
* entry, beginning at an index in the middle of the range.
*/
i = 8;
radix_tree_for_each_slot(slot, &tree, &iter, 70) {
int height = order[i] / RADIX_TREE_MAP_SHIFT; int height = order[i] / RADIX_TREE_MAP_SHIFT;
int shift = height * RADIX_TREE_MAP_SHIFT; int shift = height * RADIX_TREE_MAP_SHIFT;
int mask = (1 << order[i]) - 1;
assert(iter.index == index[i]); assert(iter.index >= (index[i] &~ mask));
assert(iter.index <= (index[i] | mask));
assert(iter.shift == shift); assert(iter.shift == shift);
i++; i++;
} }
}
item_kill_tree(&tree); item_kill_tree(&tree);
} }
...@@ -249,7 +241,7 @@ void multiorder_tagged_iteration(void) ...@@ -249,7 +241,7 @@ void multiorder_tagged_iteration(void)
struct radix_tree_iter iter; struct radix_tree_iter iter;
void **slot; void **slot;
unsigned long first = 0; unsigned long first = 0;
int i; int i, j;
printf("Multiorder tagged iteration test\n"); printf("Multiorder tagged iteration test\n");
...@@ -268,31 +260,50 @@ void multiorder_tagged_iteration(void) ...@@ -268,31 +260,50 @@ void multiorder_tagged_iteration(void)
for (i = 0; i < TAG_ENTRIES; i++) for (i = 0; i < TAG_ENTRIES; i++)
assert(radix_tree_tag_set(&tree, tag_index[i], 1)); assert(radix_tree_tag_set(&tree, tag_index[i], 1));
i = 0; for (j = 0; j < 256; j++) {
/* start from index 1 to verify we find the multi-order entry at 0 */ int mask, k;
radix_tree_for_each_tagged(slot, &tree, &iter, 1, 1) {
assert(iter.index == tag_index[i]); for (i = 0; i < TAG_ENTRIES; i++) {
i++; for (k = i; index[k] < tag_index[i]; k++)
;
if (j <= (index[k] | ((1 << order[k]) - 1)))
break;
} }
/* radix_tree_for_each_tagged(slot, &tree, &iter, j, 1) {
* Now iterate through the tree starting at an elevated multi-order for (k = i; index[k] < tag_index[i]; k++)
* entry, beginning at an index in the middle of the range. ;
*/ mask = (1 << order[k]) - 1;
i = 4;
radix_tree_for_each_slot(slot, &tree, &iter, 70) { assert(iter.index >= (tag_index[i] &~ mask));
assert(iter.index == tag_index[i]); assert(iter.index <= (tag_index[i] | mask));
i++; i++;
} }
}
radix_tree_range_tag_if_tagged(&tree, &first, ~0UL, radix_tree_range_tag_if_tagged(&tree, &first, ~0UL,
MT_NUM_ENTRIES, 1, 2); MT_NUM_ENTRIES, 1, 2);
i = 0; for (j = 0; j < 256; j++) {
radix_tree_for_each_tagged(slot, &tree, &iter, 1, 2) { int mask, k;
assert(iter.index == tag_index[i]);
for (i = 0; i < TAG_ENTRIES; i++) {
for (k = i; index[k] < tag_index[i]; k++)
;
if (j <= (index[k] | ((1 << order[k]) - 1)))
break;
}
radix_tree_for_each_tagged(slot, &tree, &iter, j, 2) {
for (k = i; index[k] < tag_index[i]; k++)
;
mask = (1 << order[k]) - 1;
assert(iter.index >= (tag_index[i] &~ mask));
assert(iter.index <= (tag_index[i] | mask));
i++; i++;
} }
}
first = 1; first = 1;
radix_tree_range_tag_if_tagged(&tree, &first, ~0UL, radix_tree_range_tag_if_tagged(&tree, &first, ~0UL,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment