diff options
author | Matthew Wilcox <willy@linux.intel.com> | 2016-05-20 20:03:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-20 20:58:30 -0400 |
commit | d0891265bbc988dc91ed8580b38eb3dac128581b (patch) | |
tree | 6807e6d2102ca79e4b53ff9903ada0ed652b4d38 /lib | |
parent | 0694f0c9e20c47063e4237e5f6649ae5ce5a369a (diff) |
radix-tree: remove root->height
The only remaining references to root->height were in extend and shrink,
where it was updated. Now we can remove it entirely.
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>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/radix-tree.c | 106 |
1 files changed, 31 insertions, 75 deletions
diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 75c9e6197b5b..58f79fee8c71 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c | |||
@@ -39,12 +39,6 @@ | |||
39 | 39 | ||
40 | 40 | ||
41 | /* | 41 | /* |
42 | * The height_to_maxindex array needs to be one deeper than the maximum | ||
43 | * path as height 0 holds only 1 entry. | ||
44 | */ | ||
45 | static unsigned long height_to_maxindex[RADIX_TREE_MAX_PATH + 1] __read_mostly; | ||
46 | |||
47 | /* | ||
48 | * Radix tree node cache. | 42 | * Radix tree node cache. |
49 | */ | 43 | */ |
50 | static struct kmem_cache *radix_tree_node_cachep; | 44 | static struct kmem_cache *radix_tree_node_cachep; |
@@ -218,8 +212,7 @@ radix_tree_find_next_bit(const unsigned long *addr, | |||
218 | } | 212 | } |
219 | 213 | ||
220 | #ifndef __KERNEL__ | 214 | #ifndef __KERNEL__ |
221 | static void dump_node(struct radix_tree_node *node, | 215 | static void dump_node(struct radix_tree_node *node, unsigned long index) |
222 | unsigned shift, unsigned long index) | ||
223 | { | 216 | { |
224 | unsigned long i; | 217 | unsigned long i; |
225 | 218 | ||
@@ -229,8 +222,8 @@ static void dump_node(struct radix_tree_node *node, | |||
229 | node->shift, node->count, node->parent); | 222 | node->shift, node->count, node->parent); |
230 | 223 | ||
231 | for (i = 0; i < RADIX_TREE_MAP_SIZE; i++) { | 224 | for (i = 0; i < RADIX_TREE_MAP_SIZE; i++) { |
232 | unsigned long first = index | (i << shift); | 225 | unsigned long first = index | (i << node->shift); |
233 | unsigned long last = first | ((1UL << shift) - 1); | 226 | unsigned long last = first | ((1UL << node->shift) - 1); |
234 | void *entry = node->slots[i]; | 227 | void *entry = node->slots[i]; |
235 | if (!entry) | 228 | if (!entry) |
236 | continue; | 229 | continue; |
@@ -243,8 +236,7 @@ static void dump_node(struct radix_tree_node *node, | |||
243 | pr_debug("radix entry %p offset %ld indices %ld-%ld\n", | 236 | pr_debug("radix entry %p offset %ld indices %ld-%ld\n", |
244 | entry, i, first, last); | 237 | entry, i, first, last); |
245 | } else { | 238 | } else { |
246 | dump_node(indirect_to_ptr(entry), | 239 | dump_node(indirect_to_ptr(entry), first); |
247 | shift - RADIX_TREE_MAP_SHIFT, first); | ||
248 | } | 240 | } |
249 | } | 241 | } |
250 | } | 242 | } |
@@ -252,13 +244,12 @@ static void dump_node(struct radix_tree_node *node, | |||
252 | /* For debug */ | 244 | /* For debug */ |
253 | static void radix_tree_dump(struct radix_tree_root *root) | 245 | static void radix_tree_dump(struct radix_tree_root *root) |
254 | { | 246 | { |
255 | pr_debug("radix root: %p height %d rnode %p tags %x\n", | 247 | pr_debug("radix root: %p rnode %p tags %x\n", |
256 | root, root->height, root->rnode, | 248 | root, root->rnode, |
257 | root->gfp_mask >> __GFP_BITS_SHIFT); | 249 | root->gfp_mask >> __GFP_BITS_SHIFT); |
258 | if (!radix_tree_is_indirect_ptr(root->rnode)) | 250 | if (!radix_tree_is_indirect_ptr(root->rnode)) |
259 | return; | 251 | return; |
260 | dump_node(indirect_to_ptr(root->rnode), | 252 | dump_node(indirect_to_ptr(root->rnode), 0); |
261 | (root->height - 1) * RADIX_TREE_MAP_SHIFT, 0); | ||
262 | } | 253 | } |
263 | #endif | 254 | #endif |
264 | 255 | ||
@@ -411,14 +402,8 @@ int radix_tree_maybe_preload(gfp_t gfp_mask) | |||
411 | EXPORT_SYMBOL(radix_tree_maybe_preload); | 402 | EXPORT_SYMBOL(radix_tree_maybe_preload); |
412 | 403 | ||
413 | /* | 404 | /* |
414 | * Return the maximum key which can be store into a | 405 | * The maximum index which can be stored in a radix tree |
415 | * radix tree with height HEIGHT. | ||
416 | */ | 406 | */ |
417 | static inline unsigned long radix_tree_maxindex(unsigned int height) | ||
418 | { | ||
419 | return height_to_maxindex[height]; | ||
420 | } | ||
421 | |||
422 | static inline unsigned long shift_maxindex(unsigned int shift) | 407 | static inline unsigned long shift_maxindex(unsigned int shift) |
423 | { | 408 | { |
424 | return (RADIX_TREE_MAP_SIZE << shift) - 1; | 409 | return (RADIX_TREE_MAP_SIZE << shift) - 1; |
@@ -450,24 +435,22 @@ static unsigned radix_tree_load_root(struct radix_tree_root *root, | |||
450 | * Extend a radix tree so it can store key @index. | 435 | * Extend a radix tree so it can store key @index. |
451 | */ | 436 | */ |
452 | static int radix_tree_extend(struct radix_tree_root *root, | 437 | static int radix_tree_extend(struct radix_tree_root *root, |
453 | unsigned long index) | 438 | unsigned long index, unsigned int shift) |
454 | { | 439 | { |
455 | struct radix_tree_node *slot; | 440 | struct radix_tree_node *slot; |
456 | unsigned int height; | 441 | unsigned int maxshift; |
457 | int tag; | 442 | int tag; |
458 | 443 | ||
459 | /* Figure out what the height should be. */ | 444 | /* Figure out what the shift should be. */ |
460 | height = root->height + 1; | 445 | maxshift = shift; |
461 | while (index > radix_tree_maxindex(height)) | 446 | while (index > shift_maxindex(maxshift)) |
462 | height++; | 447 | maxshift += RADIX_TREE_MAP_SHIFT; |
463 | 448 | ||
464 | if (root->rnode == NULL) { | 449 | slot = root->rnode; |
465 | root->height = height; | 450 | if (!slot) |
466 | goto out; | 451 | goto out; |
467 | } | ||
468 | 452 | ||
469 | do { | 453 | do { |
470 | unsigned int newheight; | ||
471 | struct radix_tree_node *node = radix_tree_node_alloc(root); | 454 | struct radix_tree_node *node = radix_tree_node_alloc(root); |
472 | 455 | ||
473 | if (!node) | 456 | if (!node) |
@@ -479,14 +462,11 @@ static int radix_tree_extend(struct radix_tree_root *root, | |||
479 | tag_set(node, tag, 0); | 462 | tag_set(node, tag, 0); |
480 | } | 463 | } |
481 | 464 | ||
482 | /* Increase the height. */ | 465 | BUG_ON(shift > BITS_PER_LONG); |
483 | newheight = root->height; | 466 | node->shift = shift; |
484 | BUG_ON(newheight > BITS_PER_LONG); | ||
485 | node->shift = newheight * RADIX_TREE_MAP_SHIFT; | ||
486 | node->offset = 0; | 467 | node->offset = 0; |
487 | node->count = 1; | 468 | node->count = 1; |
488 | node->parent = NULL; | 469 | node->parent = NULL; |
489 | slot = root->rnode; | ||
490 | if (radix_tree_is_indirect_ptr(slot)) { | 470 | if (radix_tree_is_indirect_ptr(slot)) { |
491 | slot = indirect_to_ptr(slot); | 471 | slot = indirect_to_ptr(slot); |
492 | slot->parent = node; | 472 | slot->parent = node; |
@@ -495,10 +475,11 @@ static int radix_tree_extend(struct radix_tree_root *root, | |||
495 | node->slots[0] = slot; | 475 | node->slots[0] = slot; |
496 | node = ptr_to_indirect(node); | 476 | node = ptr_to_indirect(node); |
497 | rcu_assign_pointer(root->rnode, node); | 477 | rcu_assign_pointer(root->rnode, node); |
498 | root->height = ++newheight; | 478 | shift += RADIX_TREE_MAP_SHIFT; |
499 | } while (height > root->height); | 479 | slot = node; |
480 | } while (shift <= maxshift); | ||
500 | out: | 481 | out: |
501 | return height * RADIX_TREE_MAP_SHIFT; | 482 | return maxshift + RADIX_TREE_MAP_SHIFT; |
502 | } | 483 | } |
503 | 484 | ||
504 | /** | 485 | /** |
@@ -531,15 +512,13 @@ int __radix_tree_create(struct radix_tree_root *root, unsigned long index, | |||
531 | 512 | ||
532 | /* Make sure the tree is high enough. */ | 513 | /* Make sure the tree is high enough. */ |
533 | if (max > maxindex) { | 514 | if (max > maxindex) { |
534 | int error = radix_tree_extend(root, max); | 515 | int error = radix_tree_extend(root, max, shift); |
535 | if (error < 0) | 516 | if (error < 0) |
536 | return error; | 517 | return error; |
537 | shift = error; | 518 | shift = error; |
538 | slot = root->rnode; | 519 | slot = root->rnode; |
539 | if (order == shift) { | 520 | if (order == shift) |
540 | shift += RADIX_TREE_MAP_SHIFT; | 521 | shift += RADIX_TREE_MAP_SHIFT; |
541 | root->height++; | ||
542 | } | ||
543 | } | 522 | } |
544 | 523 | ||
545 | offset = 0; /* uninitialised var warning */ | 524 | offset = 0; /* uninitialised var warning */ |
@@ -1412,32 +1391,32 @@ unsigned long radix_tree_locate_item(struct radix_tree_root *root, void *item) | |||
1412 | #endif /* CONFIG_SHMEM && CONFIG_SWAP */ | 1391 | #endif /* CONFIG_SHMEM && CONFIG_SWAP */ |
1413 | 1392 | ||
1414 | /** | 1393 | /** |
1415 | * radix_tree_shrink - shrink height of a radix tree to minimal | 1394 | * radix_tree_shrink - shrink radix tree to minimum height |
1416 | * @root radix tree root | 1395 | * @root radix tree root |
1417 | */ | 1396 | */ |
1418 | static inline bool radix_tree_shrink(struct radix_tree_root *root) | 1397 | static inline bool radix_tree_shrink(struct radix_tree_root *root) |
1419 | { | 1398 | { |
1420 | bool shrunk = false; | 1399 | bool shrunk = false; |
1421 | 1400 | ||
1422 | /* try to shrink tree height */ | 1401 | for (;;) { |
1423 | while (root->height > 0) { | ||
1424 | struct radix_tree_node *to_free = root->rnode; | 1402 | struct radix_tree_node *to_free = root->rnode; |
1425 | struct radix_tree_node *slot; | 1403 | struct radix_tree_node *slot; |
1426 | 1404 | ||
1427 | BUG_ON(!radix_tree_is_indirect_ptr(to_free)); | 1405 | if (!radix_tree_is_indirect_ptr(to_free)) |
1406 | break; | ||
1428 | to_free = indirect_to_ptr(to_free); | 1407 | to_free = indirect_to_ptr(to_free); |
1429 | 1408 | ||
1430 | /* | 1409 | /* |
1431 | * The candidate node has more than one child, or its child | 1410 | * The candidate node has more than one child, or its child |
1432 | * is not at the leftmost slot, or it is a multiorder entry, | 1411 | * is not at the leftmost slot, or the child is a multiorder |
1433 | * we cannot shrink. | 1412 | * entry, we cannot shrink. |
1434 | */ | 1413 | */ |
1435 | if (to_free->count != 1) | 1414 | if (to_free->count != 1) |
1436 | break; | 1415 | break; |
1437 | slot = to_free->slots[0]; | 1416 | slot = to_free->slots[0]; |
1438 | if (!slot) | 1417 | if (!slot) |
1439 | break; | 1418 | break; |
1440 | if (!radix_tree_is_indirect_ptr(slot) && (root->height > 1)) | 1419 | if (!radix_tree_is_indirect_ptr(slot) && to_free->shift) |
1441 | break; | 1420 | break; |
1442 | 1421 | ||
1443 | if (radix_tree_is_indirect_ptr(slot)) { | 1422 | if (radix_tree_is_indirect_ptr(slot)) { |
@@ -1454,7 +1433,6 @@ static inline bool radix_tree_shrink(struct radix_tree_root *root) | |||
1454 | * one (root->rnode) as far as dependent read barriers go. | 1433 | * one (root->rnode) as far as dependent read barriers go. |
1455 | */ | 1434 | */ |
1456 | root->rnode = slot; | 1435 | root->rnode = slot; |
1457 | root->height--; | ||
1458 | 1436 | ||
1459 | /* | 1437 | /* |
1460 | * We have a dilemma here. The node's slot[0] must not be | 1438 | * We have a dilemma here. The node's slot[0] must not be |
@@ -1515,7 +1493,6 @@ bool __radix_tree_delete_node(struct radix_tree_root *root, | |||
1515 | parent->count--; | 1493 | parent->count--; |
1516 | } else { | 1494 | } else { |
1517 | root_tag_clear_all(root); | 1495 | root_tag_clear_all(root); |
1518 | root->height = 0; | ||
1519 | root->rnode = NULL; | 1496 | root->rnode = NULL; |
1520 | } | 1497 | } |
1521 | 1498 | ||
@@ -1631,26 +1608,6 @@ radix_tree_node_ctor(void *arg) | |||
1631 | INIT_LIST_HEAD(&node->private_list); | 1608 | INIT_LIST_HEAD(&node->private_list); |
1632 | } | 1609 | } |
1633 | 1610 | ||
1634 | static __init unsigned long __maxindex(unsigned int height) | ||
1635 | { | ||
1636 | unsigned int width = height * RADIX_TREE_MAP_SHIFT; | ||
1637 | int shift = RADIX_TREE_INDEX_BITS - width; | ||
1638 | |||
1639 | if (shift < 0) | ||
1640 | return ~0UL; | ||
1641 | if (shift >= BITS_PER_LONG) | ||
1642 | return 0UL; | ||
1643 | return ~0UL >> shift; | ||
1644 | } | ||
1645 | |||
1646 | static __init void radix_tree_init_maxindex(void) | ||
1647 | { | ||
1648 | unsigned int i; | ||
1649 | |||
1650 | for (i = 0; i < ARRAY_SIZE(height_to_maxindex); i++) | ||
1651 | height_to_maxindex[i] = __maxindex(i); | ||
1652 | } | ||
1653 | |||
1654 | static int radix_tree_callback(struct notifier_block *nfb, | 1611 | static int radix_tree_callback(struct notifier_block *nfb, |
1655 | unsigned long action, void *hcpu) | 1612 | unsigned long action, void *hcpu) |
1656 | { | 1613 | { |
@@ -1677,6 +1634,5 @@ void __init radix_tree_init(void) | |||
1677 | sizeof(struct radix_tree_node), 0, | 1634 | sizeof(struct radix_tree_node), 0, |
1678 | SLAB_PANIC | SLAB_RECLAIM_ACCOUNT, | 1635 | SLAB_PANIC | SLAB_RECLAIM_ACCOUNT, |
1679 | radix_tree_node_ctor); | 1636 | radix_tree_node_ctor); |
1680 | radix_tree_init_maxindex(); | ||
1681 | hotcpu_notifier(radix_tree_callback, 0); | 1637 | hotcpu_notifier(radix_tree_callback, 0); |
1682 | } | 1638 | } |