Commit d58275bc authored by Matthew Wilcox's avatar Matthew Wilcox

radix-tree: Store a pointer to the root in each node

Instead of having this mysterious private_data in each radix_tree_node,
store a pointer to the root, which can be useful for debugging.  This also
relieves the mm code from the duty of updating it.
Acked-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
Signed-off-by: default avatarMatthew Wilcox <mawilcox@microsoft.com>
parent 1293d5c5
...@@ -96,7 +96,7 @@ struct radix_tree_node { ...@@ -96,7 +96,7 @@ struct radix_tree_node {
unsigned char count; /* Total entry count */ unsigned char count; /* Total entry count */
unsigned char exceptional; /* Exceptional entry count */ unsigned char exceptional; /* Exceptional entry count */
struct radix_tree_node *parent; /* Used when ascending tree */ struct radix_tree_node *parent; /* Used when ascending tree */
void *private_data; /* For tree user */ struct radix_tree_root *root; /* The tree we belong to */
union { union {
struct list_head private_list; /* For tree user */ struct list_head private_list; /* For tree user */
struct rcu_head rcu_head; /* Used when freeing node */ struct rcu_head rcu_head; /* Used when freeing node */
......
...@@ -374,6 +374,7 @@ static void ida_dump(struct ida *ida) ...@@ -374,6 +374,7 @@ static void ida_dump(struct ida *ida)
*/ */
static struct radix_tree_node * static struct radix_tree_node *
radix_tree_node_alloc(gfp_t gfp_mask, struct radix_tree_node *parent, radix_tree_node_alloc(gfp_t gfp_mask, struct radix_tree_node *parent,
struct radix_tree_root *root,
unsigned int shift, unsigned int offset, unsigned int shift, unsigned int offset,
unsigned int count, unsigned int exceptional) unsigned int count, unsigned int exceptional)
{ {
...@@ -419,11 +420,12 @@ radix_tree_node_alloc(gfp_t gfp_mask, struct radix_tree_node *parent, ...@@ -419,11 +420,12 @@ radix_tree_node_alloc(gfp_t gfp_mask, struct radix_tree_node *parent,
out: out:
BUG_ON(radix_tree_is_internal_node(ret)); BUG_ON(radix_tree_is_internal_node(ret));
if (ret) { if (ret) {
ret->parent = parent;
ret->shift = shift; ret->shift = shift;
ret->offset = offset; ret->offset = offset;
ret->count = count; ret->count = count;
ret->exceptional = exceptional; ret->exceptional = exceptional;
ret->parent = parent;
ret->root = root;
} }
return ret; return ret;
} }
...@@ -631,7 +633,7 @@ static int radix_tree_extend(struct radix_tree_root *root, gfp_t gfp, ...@@ -631,7 +633,7 @@ static int radix_tree_extend(struct radix_tree_root *root, gfp_t gfp,
do { do {
struct radix_tree_node *node = radix_tree_node_alloc(gfp, NULL, struct radix_tree_node *node = radix_tree_node_alloc(gfp, NULL,
shift, 0, 1, 0); root, shift, 0, 1, 0);
if (!node) if (!node)
return -ENOMEM; return -ENOMEM;
...@@ -828,7 +830,7 @@ int __radix_tree_create(struct radix_tree_root *root, unsigned long index, ...@@ -828,7 +830,7 @@ int __radix_tree_create(struct radix_tree_root *root, unsigned long index,
shift -= RADIX_TREE_MAP_SHIFT; shift -= RADIX_TREE_MAP_SHIFT;
if (child == NULL) { if (child == NULL) {
/* Have to add a child node. */ /* Have to add a child node. */
child = radix_tree_node_alloc(gfp, node, shift, child = radix_tree_node_alloc(gfp, node, root, shift,
offset, 0, 0); offset, 0, 0);
if (!child) if (!child)
return -ENOMEM; return -ENOMEM;
...@@ -1330,7 +1332,7 @@ int radix_tree_split(struct radix_tree_root *root, unsigned long index, ...@@ -1330,7 +1332,7 @@ int radix_tree_split(struct radix_tree_root *root, unsigned long index,
for (;;) { for (;;) {
if (node->shift > order) { if (node->shift > order) {
child = radix_tree_node_alloc(gfp, node, child = radix_tree_node_alloc(gfp, node, root,
node->shift - RADIX_TREE_MAP_SHIFT, node->shift - RADIX_TREE_MAP_SHIFT,
offset, 0, 0); offset, 0, 0);
if (!child) if (!child)
...@@ -2152,8 +2154,8 @@ void **idr_get_free(struct radix_tree_root *root, ...@@ -2152,8 +2154,8 @@ void **idr_get_free(struct radix_tree_root *root,
shift -= RADIX_TREE_MAP_SHIFT; shift -= RADIX_TREE_MAP_SHIFT;
if (child == NULL) { if (child == NULL) {
/* Have to add a child node. */ /* Have to add a child node. */
child = radix_tree_node_alloc(gfp, node, shift, offset, child = radix_tree_node_alloc(gfp, node, root, shift,
0, 0); offset, 0, 0);
if (!child) if (!child)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
all_tag_set(child, IDR_FREE); all_tag_set(child, IDR_FREE);
......
...@@ -354,10 +354,8 @@ void workingset_update_node(struct radix_tree_node *node, void *private) ...@@ -354,10 +354,8 @@ void workingset_update_node(struct radix_tree_node *node, void *private)
* as node->private_list is protected by &mapping->tree_lock. * as node->private_list is protected by &mapping->tree_lock.
*/ */
if (node->count && node->count == node->exceptional) { if (node->count && node->count == node->exceptional) {
if (list_empty(&node->private_list)) { if (list_empty(&node->private_list))
node->private_data = mapping;
list_lru_add(&shadow_nodes, &node->private_list); list_lru_add(&shadow_nodes, &node->private_list);
}
} else { } else {
if (!list_empty(&node->private_list)) if (!list_empty(&node->private_list))
list_lru_del(&shadow_nodes, &node->private_list); list_lru_del(&shadow_nodes, &node->private_list);
...@@ -435,7 +433,7 @@ static enum lru_status shadow_lru_isolate(struct list_head *item, ...@@ -435,7 +433,7 @@ static enum lru_status shadow_lru_isolate(struct list_head *item,
*/ */
node = container_of(item, struct radix_tree_node, private_list); node = container_of(item, struct radix_tree_node, private_list);
mapping = node->private_data; mapping = container_of(node->root, struct address_space, page_tree);
/* Coming from the list, invert the lock order */ /* Coming from the list, invert the lock order */
if (!spin_trylock(&mapping->tree_lock)) { if (!spin_trylock(&mapping->tree_lock)) {
......
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