aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@linux.intel.com>2016-05-20 20:03:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-20 20:58:30 -0400
commitd0891265bbc988dc91ed8580b38eb3dac128581b (patch)
tree6807e6d2102ca79e4b53ff9903ada0ed652b4d38 /lib
parent0694f0c9e20c47063e4237e5f6649ae5ce5a369a (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.c106
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 */
45static 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 */
50static struct kmem_cache *radix_tree_node_cachep; 44static 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__
221static void dump_node(struct radix_tree_node *node, 215static 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 */
253static void radix_tree_dump(struct radix_tree_root *root) 245static 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)
411EXPORT_SYMBOL(radix_tree_maybe_preload); 402EXPORT_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 */
417static inline unsigned long radix_tree_maxindex(unsigned int height)
418{
419 return height_to_maxindex[height];
420}
421
422static inline unsigned long shift_maxindex(unsigned int shift) 407static 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 */
452static int radix_tree_extend(struct radix_tree_root *root, 437static 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);
500out: 481out:
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 */
1418static inline bool radix_tree_shrink(struct radix_tree_root *root) 1397static 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
1634static __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
1646static __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
1654static int radix_tree_callback(struct notifier_block *nfb, 1611static 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}