diff options
author | Matthew Wilcox <willy@linux.intel.com> | 2016-05-20 20:03:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-20 20:58:30 -0400 |
commit | 0c7fa0a8418cbe0e8963fe36db9575d03b8589f7 (patch) | |
tree | 847a7e84548372584bbea5a4c67f765d8e9cff36 | |
parent | 2fcd9005cc03ab09ea2a940515ed728d43df66c4 (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.h | 7 | ||||
-rw-r--r-- | lib/radix-tree.c | 38 |
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 | ||
95 | struct radix_tree_node { | 91 | struct 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__ |
221 | static void dump_node(struct radix_tree_node *node, unsigned offset, | 221 | static 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 | ||
422 | static inline unsigned long node_maxindex(struct radix_tree_node *node) | 422 | static 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 | ||
427 | static unsigned radix_tree_load_root(struct radix_tree_root *root, | 427 | static 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 { | |||
1319 | static unsigned long __locate(struct radix_tree_node *slot, void *item, | 1319 | static 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); |