diff options
author | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2008-01-23 00:56:34 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:11:00 -0500 |
commit | 9195bef7fb0ba0a91d5ffa566bcf8e007e3c7172 (patch) | |
tree | 417eb71596accb170cbd8cdc42598170e3024264 /net/ipv4 | |
parent | a88ee229253b31e3a844b30525ff77fbfe3111d3 (diff) |
[IPV4] fib_trie: avoid extra search on delete
Get rid of extra search that made route deletion O(n).
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/fib_trie.c | 50 |
1 files changed, 12 insertions, 38 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 2ea94ebe19f8..441c4eafb9e0 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -1545,49 +1545,23 @@ found: | |||
1545 | return ret; | 1545 | return ret; |
1546 | } | 1546 | } |
1547 | 1547 | ||
1548 | /* only called from updater side */ | 1548 | /* |
1549 | static int trie_leaf_remove(struct trie *t, t_key key) | 1549 | * Remove the leaf and return parent. |
1550 | */ | ||
1551 | static void trie_leaf_remove(struct trie *t, struct leaf *l) | ||
1550 | { | 1552 | { |
1551 | t_key cindex; | 1553 | struct tnode *tp = node_parent((struct node *) l); |
1552 | struct tnode *tp = NULL; | ||
1553 | struct node *n = t->trie; | ||
1554 | struct leaf *l; | ||
1555 | |||
1556 | pr_debug("entering trie_leaf_remove(%p)\n", n); | ||
1557 | 1554 | ||
1558 | /* Note that in the case skipped bits, those bits are *not* checked! | 1555 | pr_debug("entering trie_leaf_remove(%p)\n", l); |
1559 | * When we finish this, we will have NULL or a T_LEAF, and the | ||
1560 | * T_LEAF may or may not match our key. | ||
1561 | */ | ||
1562 | |||
1563 | while (n != NULL && IS_TNODE(n)) { | ||
1564 | struct tnode *tn = (struct tnode *) n; | ||
1565 | check_tnode(tn); | ||
1566 | n = tnode_get_child(tn, tkey_extract_bits(key, | ||
1567 | tn->pos, tn->bits)); | ||
1568 | |||
1569 | BUG_ON(n && node_parent(n) != tn); | ||
1570 | } | ||
1571 | l = (struct leaf *) n; | ||
1572 | |||
1573 | if (!n || !tkey_equals(l->key, key)) | ||
1574 | return 0; | ||
1575 | |||
1576 | /* | ||
1577 | * Key found. | ||
1578 | * Remove the leaf and rebalance the tree | ||
1579 | */ | ||
1580 | tp = node_parent(n); | ||
1581 | tnode_free((struct tnode *) n); | ||
1582 | 1556 | ||
1583 | if (tp) { | 1557 | if (tp) { |
1584 | cindex = tkey_extract_bits(key, tp->pos, tp->bits); | 1558 | t_key cindex = tkey_extract_bits(l->key, tp->pos, tp->bits); |
1585 | put_child(t, (struct tnode *)tp, cindex, NULL); | 1559 | put_child(t, (struct tnode *)tp, cindex, NULL); |
1586 | rcu_assign_pointer(t->trie, trie_rebalance(t, tp)); | 1560 | rcu_assign_pointer(t->trie, trie_rebalance(t, tp)); |
1587 | } else | 1561 | } else |
1588 | rcu_assign_pointer(t->trie, NULL); | 1562 | rcu_assign_pointer(t->trie, NULL); |
1589 | 1563 | ||
1590 | return 1; | 1564 | tnode_free((struct tnode *) l); |
1591 | } | 1565 | } |
1592 | 1566 | ||
1593 | /* | 1567 | /* |
@@ -1665,7 +1639,7 @@ static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg) | |||
1665 | } | 1639 | } |
1666 | 1640 | ||
1667 | if (hlist_empty(&l->list)) | 1641 | if (hlist_empty(&l->list)) |
1668 | trie_leaf_remove(t, key); | 1642 | trie_leaf_remove(t, l); |
1669 | 1643 | ||
1670 | if (fa->fa_state & FA_S_ACCESSED) | 1644 | if (fa->fa_state & FA_S_ACCESSED) |
1671 | rt_cache_flush(-1); | 1645 | rt_cache_flush(-1); |
@@ -1778,19 +1752,19 @@ static struct leaf *trie_nextleaf(struct leaf *l) | |||
1778 | static int fn_trie_flush(struct fib_table *tb) | 1752 | static int fn_trie_flush(struct fib_table *tb) |
1779 | { | 1753 | { |
1780 | struct trie *t = (struct trie *) tb->tb_data; | 1754 | struct trie *t = (struct trie *) tb->tb_data; |
1781 | struct leaf *ll = NULL, *l = NULL; | 1755 | struct leaf *l, *ll = NULL; |
1782 | int found = 0; | 1756 | int found = 0; |
1783 | 1757 | ||
1784 | for (l = trie_firstleaf(t); l; l = trie_nextleaf(l)) { | 1758 | for (l = trie_firstleaf(t); l; l = trie_nextleaf(l)) { |
1785 | found += trie_flush_leaf(t, l); | 1759 | found += trie_flush_leaf(t, l); |
1786 | 1760 | ||
1787 | if (ll && hlist_empty(&ll->list)) | 1761 | if (ll && hlist_empty(&ll->list)) |
1788 | trie_leaf_remove(t, ll->key); | 1762 | trie_leaf_remove(t, ll); |
1789 | ll = l; | 1763 | ll = l; |
1790 | } | 1764 | } |
1791 | 1765 | ||
1792 | if (ll && hlist_empty(&ll->list)) | 1766 | if (ll && hlist_empty(&ll->list)) |
1793 | trie_leaf_remove(t, ll->key); | 1767 | trie_leaf_remove(t, ll); |
1794 | 1768 | ||
1795 | pr_debug("trie_flush found=%d\n", found); | 1769 | pr_debug("trie_flush found=%d\n", found); |
1796 | return found; | 1770 | return found; |