|
@@ -342,7 +342,8 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
|
|
|
|
|
|
/* Increase the height. */
|
|
/* Increase the height. */
|
|
newheight = root->height+1;
|
|
newheight = root->height+1;
|
|
- node->height = newheight;
|
|
|
|
|
|
+ BUG_ON(newheight & ~RADIX_TREE_HEIGHT_MASK);
|
|
|
|
+ node->path = newheight;
|
|
node->count = 1;
|
|
node->count = 1;
|
|
node->parent = NULL;
|
|
node->parent = NULL;
|
|
slot = root->rnode;
|
|
slot = root->rnode;
|
|
@@ -400,11 +401,12 @@ int __radix_tree_create(struct radix_tree_root *root, unsigned long index,
|
|
/* Have to add a child node. */
|
|
/* Have to add a child node. */
|
|
if (!(slot = radix_tree_node_alloc(root)))
|
|
if (!(slot = radix_tree_node_alloc(root)))
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
- slot->height = height;
|
|
|
|
|
|
+ slot->path = height;
|
|
slot->parent = node;
|
|
slot->parent = node;
|
|
if (node) {
|
|
if (node) {
|
|
rcu_assign_pointer(node->slots[offset], slot);
|
|
rcu_assign_pointer(node->slots[offset], slot);
|
|
node->count++;
|
|
node->count++;
|
|
|
|
+ slot->path |= offset << RADIX_TREE_HEIGHT_SHIFT;
|
|
} else
|
|
} else
|
|
rcu_assign_pointer(root->rnode, ptr_to_indirect(slot));
|
|
rcu_assign_pointer(root->rnode, ptr_to_indirect(slot));
|
|
}
|
|
}
|
|
@@ -498,7 +500,7 @@ void *__radix_tree_lookup(struct radix_tree_root *root, unsigned long index,
|
|
}
|
|
}
|
|
node = indirect_to_ptr(node);
|
|
node = indirect_to_ptr(node);
|
|
|
|
|
|
- height = node->height;
|
|
|
|
|
|
+ height = node->path & RADIX_TREE_HEIGHT_MASK;
|
|
if (index > radix_tree_maxindex(height))
|
|
if (index > radix_tree_maxindex(height))
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
@@ -704,7 +706,7 @@ int radix_tree_tag_get(struct radix_tree_root *root,
|
|
return (index == 0);
|
|
return (index == 0);
|
|
node = indirect_to_ptr(node);
|
|
node = indirect_to_ptr(node);
|
|
|
|
|
|
- height = node->height;
|
|
|
|
|
|
+ height = node->path & RADIX_TREE_HEIGHT_MASK;
|
|
if (index > radix_tree_maxindex(height))
|
|
if (index > radix_tree_maxindex(height))
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
@@ -741,7 +743,7 @@ void **radix_tree_next_chunk(struct radix_tree_root *root,
|
|
{
|
|
{
|
|
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 *rnode, *node;
|
|
- unsigned long index, offset;
|
|
|
|
|
|
+ unsigned long index, offset, height;
|
|
|
|
|
|
if ((flags & RADIX_TREE_ITER_TAGGED) && !root_tag_get(root, tag))
|
|
if ((flags & RADIX_TREE_ITER_TAGGED) && !root_tag_get(root, tag))
|
|
return NULL;
|
|
return NULL;
|
|
@@ -772,7 +774,8 @@ void **radix_tree_next_chunk(struct radix_tree_root *root,
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
restart:
|
|
restart:
|
|
- shift = (rnode->height - 1) * RADIX_TREE_MAP_SHIFT;
|
|
|
|
|
|
+ height = rnode->path & RADIX_TREE_HEIGHT_MASK;
|
|
|
|
+ shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
|
|
offset = index >> shift;
|
|
offset = index >> shift;
|
|
|
|
|
|
/* Index outside of the tree */
|
|
/* Index outside of the tree */
|
|
@@ -1142,7 +1145,7 @@ static unsigned long __locate(struct radix_tree_node *slot, void *item,
|
|
unsigned int shift, height;
|
|
unsigned int shift, height;
|
|
unsigned long i;
|
|
unsigned long i;
|
|
|
|
|
|
- height = slot->height;
|
|
|
|
|
|
+ height = slot->path & RADIX_TREE_HEIGHT_MASK;
|
|
shift = (height-1) * RADIX_TREE_MAP_SHIFT;
|
|
shift = (height-1) * RADIX_TREE_MAP_SHIFT;
|
|
|
|
|
|
for ( ; height > 1; height--) {
|
|
for ( ; height > 1; height--) {
|
|
@@ -1205,7 +1208,8 @@ unsigned long radix_tree_locate_item(struct radix_tree_root *root, void *item)
|
|
}
|
|
}
|
|
|
|
|
|
node = indirect_to_ptr(node);
|
|
node = indirect_to_ptr(node);
|
|
- max_index = radix_tree_maxindex(node->height);
|
|
|
|
|
|
+ max_index = radix_tree_maxindex(node->path &
|
|
|
|
+ RADIX_TREE_HEIGHT_MASK);
|
|
if (cur_index > max_index) {
|
|
if (cur_index > max_index) {
|
|
rcu_read_unlock();
|
|
rcu_read_unlock();
|
|
break;
|
|
break;
|
|
@@ -1301,7 +1305,7 @@ static inline void radix_tree_shrink(struct radix_tree_root *root)
|
|
*
|
|
*
|
|
* Returns %true if @node was freed, %false otherwise.
|
|
* Returns %true if @node was freed, %false otherwise.
|
|
*/
|
|
*/
|
|
-bool __radix_tree_delete_node(struct radix_tree_root *root, unsigned long index,
|
|
|
|
|
|
+bool __radix_tree_delete_node(struct radix_tree_root *root,
|
|
struct radix_tree_node *node)
|
|
struct radix_tree_node *node)
|
|
{
|
|
{
|
|
bool deleted = false;
|
|
bool deleted = false;
|
|
@@ -1320,9 +1324,10 @@ bool __radix_tree_delete_node(struct radix_tree_root *root, unsigned long index,
|
|
|
|
|
|
parent = node->parent;
|
|
parent = node->parent;
|
|
if (parent) {
|
|
if (parent) {
|
|
- index >>= RADIX_TREE_MAP_SHIFT;
|
|
|
|
|
|
+ unsigned int offset;
|
|
|
|
|
|
- parent->slots[index & RADIX_TREE_MAP_MASK] = NULL;
|
|
|
|
|
|
+ offset = node->path >> RADIX_TREE_HEIGHT_SHIFT;
|
|
|
|
+ parent->slots[offset] = NULL;
|
|
parent->count--;
|
|
parent->count--;
|
|
} else {
|
|
} else {
|
|
root_tag_clear_all(root);
|
|
root_tag_clear_all(root);
|
|
@@ -1386,7 +1391,7 @@ void *radix_tree_delete_item(struct radix_tree_root *root,
|
|
node->slots[offset] = NULL;
|
|
node->slots[offset] = NULL;
|
|
node->count--;
|
|
node->count--;
|
|
|
|
|
|
- __radix_tree_delete_node(root, index, node);
|
|
|
|
|
|
+ __radix_tree_delete_node(root, node);
|
|
|
|
|
|
return entry;
|
|
return entry;
|
|
}
|
|
}
|
|
@@ -1419,9 +1424,12 @@ int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag)
|
|
EXPORT_SYMBOL(radix_tree_tagged);
|
|
EXPORT_SYMBOL(radix_tree_tagged);
|
|
|
|
|
|
static void
|
|
static void
|
|
-radix_tree_node_ctor(void *node)
|
|
|
|
|
|
+radix_tree_node_ctor(void *arg)
|
|
{
|
|
{
|
|
- memset(node, 0, sizeof(struct radix_tree_node));
|
|
|
|
|
|
+ struct radix_tree_node *node = arg;
|
|
|
|
+
|
|
|
|
+ memset(node, 0, sizeof(*node));
|
|
|
|
+ INIT_LIST_HEAD(&node->private_list);
|
|
}
|
|
}
|
|
|
|
|
|
static __init unsigned long __maxindex(unsigned int height)
|
|
static __init unsigned long __maxindex(unsigned int height)
|