diff options
Diffstat (limited to 'net/ipv4/fib_trie.c')
-rw-r--r-- | net/ipv4/fib_trie.c | 101 |
1 files changed, 41 insertions, 60 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 63c2fa7b68c4..291bdf50a21f 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -48,7 +48,7 @@ | |||
48 | * Patrick McHardy <kaber@trash.net> | 48 | * Patrick McHardy <kaber@trash.net> |
49 | */ | 49 | */ |
50 | 50 | ||
51 | #define VERSION "0.408" | 51 | #define VERSION "0.409" |
52 | 52 | ||
53 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
54 | #include <asm/system.h> | 54 | #include <asm/system.h> |
@@ -164,6 +164,14 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn); | |||
164 | static struct tnode *halve(struct trie *t, struct tnode *tn); | 164 | static struct tnode *halve(struct trie *t, struct tnode *tn); |
165 | /* tnodes to free after resize(); protected by RTNL */ | 165 | /* tnodes to free after resize(); protected by RTNL */ |
166 | static struct tnode *tnode_free_head; | 166 | static struct tnode *tnode_free_head; |
167 | static size_t tnode_free_size; | ||
168 | |||
169 | /* | ||
170 | * synchronize_rcu after call_rcu for that many pages; it should be especially | ||
171 | * useful before resizing the root node with PREEMPT_NONE configs; the value was | ||
172 | * obtained experimentally, aiming to avoid visible slowdown. | ||
173 | */ | ||
174 | static const int sync_pages = 128; | ||
167 | 175 | ||
168 | static struct kmem_cache *fn_alias_kmem __read_mostly; | 176 | static struct kmem_cache *fn_alias_kmem __read_mostly; |
169 | static struct kmem_cache *trie_leaf_kmem __read_mostly; | 177 | static struct kmem_cache *trie_leaf_kmem __read_mostly; |
@@ -317,8 +325,7 @@ static inline void check_tnode(const struct tnode *tn) | |||
317 | static const int halve_threshold = 25; | 325 | static const int halve_threshold = 25; |
318 | static const int inflate_threshold = 50; | 326 | static const int inflate_threshold = 50; |
319 | static const int halve_threshold_root = 15; | 327 | static const int halve_threshold_root = 15; |
320 | static const int inflate_threshold_root = 25; | 328 | static const int inflate_threshold_root = 30; |
321 | |||
322 | 329 | ||
323 | static void __alias_free_mem(struct rcu_head *head) | 330 | static void __alias_free_mem(struct rcu_head *head) |
324 | { | 331 | { |
@@ -393,6 +400,8 @@ static void tnode_free_safe(struct tnode *tn) | |||
393 | BUG_ON(IS_LEAF(tn)); | 400 | BUG_ON(IS_LEAF(tn)); |
394 | tn->tnode_free = tnode_free_head; | 401 | tn->tnode_free = tnode_free_head; |
395 | tnode_free_head = tn; | 402 | tnode_free_head = tn; |
403 | tnode_free_size += sizeof(struct tnode) + | ||
404 | (sizeof(struct node *) << tn->bits); | ||
396 | } | 405 | } |
397 | 406 | ||
398 | static void tnode_free_flush(void) | 407 | static void tnode_free_flush(void) |
@@ -404,6 +413,11 @@ static void tnode_free_flush(void) | |||
404 | tn->tnode_free = NULL; | 413 | tn->tnode_free = NULL; |
405 | tnode_free(tn); | 414 | tnode_free(tn); |
406 | } | 415 | } |
416 | |||
417 | if (tnode_free_size >= PAGE_SIZE * sync_pages) { | ||
418 | tnode_free_size = 0; | ||
419 | synchronize_rcu(); | ||
420 | } | ||
407 | } | 421 | } |
408 | 422 | ||
409 | static struct leaf *leaf_new(void) | 423 | static struct leaf *leaf_new(void) |
@@ -499,14 +513,14 @@ static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, | |||
499 | rcu_assign_pointer(tn->child[i], n); | 513 | rcu_assign_pointer(tn->child[i], n); |
500 | } | 514 | } |
501 | 515 | ||
516 | #define MAX_WORK 10 | ||
502 | static struct node *resize(struct trie *t, struct tnode *tn) | 517 | static struct node *resize(struct trie *t, struct tnode *tn) |
503 | { | 518 | { |
504 | int i; | 519 | int i; |
505 | int err = 0; | ||
506 | struct tnode *old_tn; | 520 | struct tnode *old_tn; |
507 | int inflate_threshold_use; | 521 | int inflate_threshold_use; |
508 | int halve_threshold_use; | 522 | int halve_threshold_use; |
509 | int max_resize; | 523 | int max_work; |
510 | 524 | ||
511 | if (!tn) | 525 | if (!tn) |
512 | return NULL; | 526 | return NULL; |
@@ -521,18 +535,7 @@ static struct node *resize(struct trie *t, struct tnode *tn) | |||
521 | } | 535 | } |
522 | /* One child */ | 536 | /* One child */ |
523 | if (tn->empty_children == tnode_child_length(tn) - 1) | 537 | if (tn->empty_children == tnode_child_length(tn) - 1) |
524 | for (i = 0; i < tnode_child_length(tn); i++) { | 538 | goto one_child; |
525 | struct node *n; | ||
526 | |||
527 | n = tn->child[i]; | ||
528 | if (!n) | ||
529 | continue; | ||
530 | |||
531 | /* compress one level */ | ||
532 | node_set_parent(n, NULL); | ||
533 | tnode_free_safe(tn); | ||
534 | return n; | ||
535 | } | ||
536 | /* | 539 | /* |
537 | * Double as long as the resulting node has a number of | 540 | * Double as long as the resulting node has a number of |
538 | * nonempty nodes that are above the threshold. | 541 | * nonempty nodes that are above the threshold. |
@@ -601,14 +604,17 @@ static struct node *resize(struct trie *t, struct tnode *tn) | |||
601 | 604 | ||
602 | /* Keep root node larger */ | 605 | /* Keep root node larger */ |
603 | 606 | ||
604 | if (!tn->parent) | 607 | if (!node_parent((struct node*) tn)) { |
605 | inflate_threshold_use = inflate_threshold_root; | 608 | inflate_threshold_use = inflate_threshold_root; |
606 | else | 609 | halve_threshold_use = halve_threshold_root; |
610 | } | ||
611 | else { | ||
607 | inflate_threshold_use = inflate_threshold; | 612 | inflate_threshold_use = inflate_threshold; |
613 | halve_threshold_use = halve_threshold; | ||
614 | } | ||
608 | 615 | ||
609 | err = 0; | 616 | max_work = MAX_WORK; |
610 | max_resize = 10; | 617 | while ((tn->full_children > 0 && max_work-- && |
611 | while ((tn->full_children > 0 && max_resize-- && | ||
612 | 50 * (tn->full_children + tnode_child_length(tn) | 618 | 50 * (tn->full_children + tnode_child_length(tn) |
613 | - tn->empty_children) | 619 | - tn->empty_children) |
614 | >= inflate_threshold_use * tnode_child_length(tn))) { | 620 | >= inflate_threshold_use * tnode_child_length(tn))) { |
@@ -625,35 +631,19 @@ static struct node *resize(struct trie *t, struct tnode *tn) | |||
625 | } | 631 | } |
626 | } | 632 | } |
627 | 633 | ||
628 | if (max_resize < 0) { | ||
629 | if (!tn->parent) | ||
630 | pr_warning("Fix inflate_threshold_root." | ||
631 | " Now=%d size=%d bits\n", | ||
632 | inflate_threshold_root, tn->bits); | ||
633 | else | ||
634 | pr_warning("Fix inflate_threshold." | ||
635 | " Now=%d size=%d bits\n", | ||
636 | inflate_threshold, tn->bits); | ||
637 | } | ||
638 | |||
639 | check_tnode(tn); | 634 | check_tnode(tn); |
640 | 635 | ||
636 | /* Return if at least one inflate is run */ | ||
637 | if( max_work != MAX_WORK) | ||
638 | return (struct node *) tn; | ||
639 | |||
641 | /* | 640 | /* |
642 | * Halve as long as the number of empty children in this | 641 | * Halve as long as the number of empty children in this |
643 | * node is above threshold. | 642 | * node is above threshold. |
644 | */ | 643 | */ |
645 | 644 | ||
646 | 645 | max_work = MAX_WORK; | |
647 | /* Keep root node larger */ | 646 | while (tn->bits > 1 && max_work-- && |
648 | |||
649 | if (!tn->parent) | ||
650 | halve_threshold_use = halve_threshold_root; | ||
651 | else | ||
652 | halve_threshold_use = halve_threshold; | ||
653 | |||
654 | err = 0; | ||
655 | max_resize = 10; | ||
656 | while (tn->bits > 1 && max_resize-- && | ||
657 | 100 * (tnode_child_length(tn) - tn->empty_children) < | 647 | 100 * (tnode_child_length(tn) - tn->empty_children) < |
658 | halve_threshold_use * tnode_child_length(tn)) { | 648 | halve_threshold_use * tnode_child_length(tn)) { |
659 | 649 | ||
@@ -668,19 +658,10 @@ static struct node *resize(struct trie *t, struct tnode *tn) | |||
668 | } | 658 | } |
669 | } | 659 | } |
670 | 660 | ||
671 | if (max_resize < 0) { | ||
672 | if (!tn->parent) | ||
673 | pr_warning("Fix halve_threshold_root." | ||
674 | " Now=%d size=%d bits\n", | ||
675 | halve_threshold_root, tn->bits); | ||
676 | else | ||
677 | pr_warning("Fix halve_threshold." | ||
678 | " Now=%d size=%d bits\n", | ||
679 | halve_threshold, tn->bits); | ||
680 | } | ||
681 | 661 | ||
682 | /* Only one child remains */ | 662 | /* Only one child remains */ |
683 | if (tn->empty_children == tnode_child_length(tn) - 1) | 663 | if (tn->empty_children == tnode_child_length(tn) - 1) { |
664 | one_child: | ||
684 | for (i = 0; i < tnode_child_length(tn); i++) { | 665 | for (i = 0; i < tnode_child_length(tn); i++) { |
685 | struct node *n; | 666 | struct node *n; |
686 | 667 | ||
@@ -694,7 +675,7 @@ static struct node *resize(struct trie *t, struct tnode *tn) | |||
694 | tnode_free_safe(tn); | 675 | tnode_free_safe(tn); |
695 | return n; | 676 | return n; |
696 | } | 677 | } |
697 | 678 | } | |
698 | return (struct node *) tn; | 679 | return (struct node *) tn; |
699 | } | 680 | } |
700 | 681 | ||
@@ -1435,7 +1416,7 @@ static int fn_trie_lookup(struct fib_table *tb, const struct flowi *flp, | |||
1435 | cindex = tkey_extract_bits(mask_pfx(key, current_prefix_length), | 1416 | cindex = tkey_extract_bits(mask_pfx(key, current_prefix_length), |
1436 | pos, bits); | 1417 | pos, bits); |
1437 | 1418 | ||
1438 | n = tnode_get_child(pn, cindex); | 1419 | n = tnode_get_child_rcu(pn, cindex); |
1439 | 1420 | ||
1440 | if (n == NULL) { | 1421 | if (n == NULL) { |
1441 | #ifdef CONFIG_IP_FIB_TRIE_STATS | 1422 | #ifdef CONFIG_IP_FIB_TRIE_STATS |
@@ -1570,7 +1551,7 @@ backtrace: | |||
1570 | if (chopped_off <= pn->bits) { | 1551 | if (chopped_off <= pn->bits) { |
1571 | cindex &= ~(1 << (chopped_off-1)); | 1552 | cindex &= ~(1 << (chopped_off-1)); |
1572 | } else { | 1553 | } else { |
1573 | struct tnode *parent = node_parent((struct node *) pn); | 1554 | struct tnode *parent = node_parent_rcu((struct node *) pn); |
1574 | if (!parent) | 1555 | if (!parent) |
1575 | goto failed; | 1556 | goto failed; |
1576 | 1557 | ||
@@ -1783,7 +1764,7 @@ static struct leaf *trie_firstleaf(struct trie *t) | |||
1783 | static struct leaf *trie_nextleaf(struct leaf *l) | 1764 | static struct leaf *trie_nextleaf(struct leaf *l) |
1784 | { | 1765 | { |
1785 | struct node *c = (struct node *) l; | 1766 | struct node *c = (struct node *) l; |
1786 | struct tnode *p = node_parent(c); | 1767 | struct tnode *p = node_parent_rcu(c); |
1787 | 1768 | ||
1788 | if (!p) | 1769 | if (!p) |
1789 | return NULL; /* trie with just one leaf */ | 1770 | return NULL; /* trie with just one leaf */ |
@@ -2391,7 +2372,7 @@ static inline const char *rtn_scope(char *buf, size_t len, enum rt_scope_t s) | |||
2391 | } | 2372 | } |
2392 | } | 2373 | } |
2393 | 2374 | ||
2394 | static const char *rtn_type_names[__RTN_MAX] = { | 2375 | static const char *const rtn_type_names[__RTN_MAX] = { |
2395 | [RTN_UNSPEC] = "UNSPEC", | 2376 | [RTN_UNSPEC] = "UNSPEC", |
2396 | [RTN_UNICAST] = "UNICAST", | 2377 | [RTN_UNICAST] = "UNICAST", |
2397 | [RTN_LOCAL] = "LOCAL", | 2378 | [RTN_LOCAL] = "LOCAL", |