summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@linux.intel.com>2016-05-20 20:03:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-20 20:58:30 -0400
commit0c7fa0a8418cbe0e8963fe36db9575d03b8589f7 (patch)
tree847a7e84548372584bbea5a4c67f765d8e9cff36
parent2fcd9005cc03ab09ea2a940515ed728d43df66c4 (diff)
radix-tree: split node->path into offset and height
Neither piece of information we're storing in node->path can be larger than 64, so store each in its own unsigned char instead of shifting and masking to store them both in an unsigned int. Signed-off-by: Matthew Wilcox <willy@linux.intel.com> Reviewed-by: Ross Zwisler <ross.zwisler@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> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/radix-tree.h7
-rw-r--r--lib/radix-tree.c38
2 files changed, 19 insertions, 26 deletions
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index 8558d52e1c7b..2d2ad9d685a3 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -84,16 +84,13 @@ static inline int radix_tree_is_indirect_ptr(void *ptr)
84#define RADIX_TREE_MAX_PATH (DIV_ROUND_UP(RADIX_TREE_INDEX_BITS, \ 84#define RADIX_TREE_MAX_PATH (DIV_ROUND_UP(RADIX_TREE_INDEX_BITS, \
85 RADIX_TREE_MAP_SHIFT)) 85 RADIX_TREE_MAP_SHIFT))
86 86
87/* Height component in node->path */
88#define RADIX_TREE_HEIGHT_SHIFT (RADIX_TREE_MAX_PATH + 1)
89#define RADIX_TREE_HEIGHT_MASK ((1UL << RADIX_TREE_HEIGHT_SHIFT) - 1)
90
91/* Internally used bits of node->count */ 87/* Internally used bits of node->count */
92#define RADIX_TREE_COUNT_SHIFT (RADIX_TREE_MAP_SHIFT + 1) 88#define RADIX_TREE_COUNT_SHIFT (RADIX_TREE_MAP_SHIFT + 1)
93#define RADIX_TREE_COUNT_MASK ((1UL << RADIX_TREE_COUNT_SHIFT) - 1) 89#define RADIX_TREE_COUNT_MASK ((1UL << RADIX_TREE_COUNT_SHIFT) - 1)
94 90
95struct radix_tree_node { 91struct radix_tree_node {
96 unsigned int path; /* Offset in parent & height from the bottom */ 92 unsigned char height; /* From the bottom */
93 unsigned char offset; /* Slot offset in parent */
97 unsigned int count; 94 unsigned int count;
98 union { 95 union {
99 struct { 96 struct {
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 75944e42e4a0..dd04b51e5fbb 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -218,15 +218,15 @@ radix_tree_find_next_bit(const unsigned long *addr,
218} 218}
219 219
220#ifndef __KERNEL__ 220#ifndef __KERNEL__
221static void dump_node(struct radix_tree_node *node, unsigned offset, 221static void dump_node(struct radix_tree_node *node,
222 unsigned shift, unsigned long index) 222 unsigned shift, unsigned long index)
223{ 223{
224 unsigned long i; 224 unsigned long i;
225 225
226 pr_debug("radix node: %p offset %d tags %lx %lx %lx path %x count %d parent %p\n", 226 pr_debug("radix node: %p offset %d tags %lx %lx %lx height %d count %d parent %p\n",
227 node, offset, 227 node, node->offset,
228 node->tags[0][0], node->tags[1][0], node->tags[2][0], 228 node->tags[0][0], node->tags[1][0], node->tags[2][0],
229 node->path, node->count, node->parent); 229 node->height, node->count, node->parent);
230 230
231 for (i = 0; i < RADIX_TREE_MAP_SIZE; i++) { 231 for (i = 0; i < RADIX_TREE_MAP_SIZE; i++) {
232 unsigned long first = index | (i << shift); 232 unsigned long first = index | (i << shift);
@@ -243,7 +243,7 @@ static void dump_node(struct radix_tree_node *node, unsigned offset,
243 pr_debug("radix entry %p offset %ld indices %ld-%ld\n", 243 pr_debug("radix entry %p offset %ld indices %ld-%ld\n",
244 entry, i, first, last); 244 entry, i, first, last);
245 } else { 245 } else {
246 dump_node(indirect_to_ptr(entry), i, 246 dump_node(indirect_to_ptr(entry),
247 shift - RADIX_TREE_MAP_SHIFT, first); 247 shift - RADIX_TREE_MAP_SHIFT, first);
248 } 248 }
249 } 249 }
@@ -257,7 +257,7 @@ static void radix_tree_dump(struct radix_tree_root *root)
257 root->gfp_mask >> __GFP_BITS_SHIFT); 257 root->gfp_mask >> __GFP_BITS_SHIFT);
258 if (!radix_tree_is_indirect_ptr(root->rnode)) 258 if (!radix_tree_is_indirect_ptr(root->rnode))
259 return; 259 return;
260 dump_node(indirect_to_ptr(root->rnode), 0, 260 dump_node(indirect_to_ptr(root->rnode),
261 (root->height - 1) * RADIX_TREE_MAP_SHIFT, 0); 261 (root->height - 1) * RADIX_TREE_MAP_SHIFT, 0);
262} 262}
263#endif 263#endif
@@ -421,7 +421,7 @@ static inline unsigned long radix_tree_maxindex(unsigned int height)
421 421
422static inline unsigned long node_maxindex(struct radix_tree_node *node) 422static inline unsigned long node_maxindex(struct radix_tree_node *node)
423{ 423{
424 return radix_tree_maxindex(node->path & RADIX_TREE_HEIGHT_MASK); 424 return radix_tree_maxindex(node->height);
425} 425}
426 426
427static unsigned radix_tree_load_root(struct radix_tree_root *root, 427static unsigned radix_tree_load_root(struct radix_tree_root *root,
@@ -434,8 +434,7 @@ static unsigned radix_tree_load_root(struct radix_tree_root *root,
434 if (likely(radix_tree_is_indirect_ptr(node))) { 434 if (likely(radix_tree_is_indirect_ptr(node))) {
435 node = indirect_to_ptr(node); 435 node = indirect_to_ptr(node);
436 *maxindex = node_maxindex(node); 436 *maxindex = node_maxindex(node);
437 return (node->path & RADIX_TREE_HEIGHT_MASK) * 437 return node->height * RADIX_TREE_MAP_SHIFT;
438 RADIX_TREE_MAP_SHIFT;
439 } 438 }
440 439
441 *maxindex = 0; 440 *maxindex = 0;
@@ -476,9 +475,10 @@ static int radix_tree_extend(struct radix_tree_root *root,
476 } 475 }
477 476
478 /* Increase the height. */ 477 /* Increase the height. */
479 newheight = root->height+1; 478 newheight = root->height + 1;
480 BUG_ON(newheight & ~RADIX_TREE_HEIGHT_MASK); 479 BUG_ON(newheight > BITS_PER_LONG);
481 node->path = newheight; 480 node->height = newheight;
481 node->offset = 0;
482 node->count = 1; 482 node->count = 1;
483 node->parent = NULL; 483 node->parent = NULL;
484 slot = root->rnode; 484 slot = root->rnode;
@@ -546,13 +546,13 @@ int __radix_tree_create(struct radix_tree_root *root, unsigned long index,
546 slot = radix_tree_node_alloc(root); 546 slot = radix_tree_node_alloc(root);
547 if (!slot) 547 if (!slot)
548 return -ENOMEM; 548 return -ENOMEM;
549 slot->path = height; 549 slot->height = height;
550 slot->offset = offset;
550 slot->parent = node; 551 slot->parent = node;
551 if (node) { 552 if (node) {
552 rcu_assign_pointer(node->slots[offset], 553 rcu_assign_pointer(node->slots[offset],
553 ptr_to_indirect(slot)); 554 ptr_to_indirect(slot));
554 node->count++; 555 node->count++;
555 slot->path |= offset << RADIX_TREE_HEIGHT_SHIFT;
556 } else 556 } else
557 rcu_assign_pointer(root->rnode, 557 rcu_assign_pointer(root->rnode,
558 ptr_to_indirect(slot)); 558 ptr_to_indirect(slot));
@@ -1319,11 +1319,10 @@ struct locate_info {
1319static unsigned long __locate(struct radix_tree_node *slot, void *item, 1319static unsigned long __locate(struct radix_tree_node *slot, void *item,
1320 unsigned long index, struct locate_info *info) 1320 unsigned long index, struct locate_info *info)
1321{ 1321{
1322 unsigned int shift, height; 1322 unsigned int shift;
1323 unsigned long i; 1323 unsigned long i;
1324 1324
1325 height = slot->path & RADIX_TREE_HEIGHT_MASK; 1325 shift = slot->height * RADIX_TREE_MAP_SHIFT;
1326 shift = height * RADIX_TREE_MAP_SHIFT;
1327 1326
1328 do { 1327 do {
1329 shift -= RADIX_TREE_MAP_SHIFT; 1328 shift -= RADIX_TREE_MAP_SHIFT;
@@ -1508,10 +1507,7 @@ bool __radix_tree_delete_node(struct radix_tree_root *root,
1508 1507
1509 parent = node->parent; 1508 parent = node->parent;
1510 if (parent) { 1509 if (parent) {
1511 unsigned int offset; 1510 parent->slots[node->offset] = NULL;
1512
1513 offset = node->path >> RADIX_TREE_HEIGHT_SHIFT;
1514 parent->slots[offset] = NULL;
1515 parent->count--; 1511 parent->count--;
1516 } else { 1512 } else {
1517 root_tag_clear_all(root); 1513 root_tag_clear_all(root);