aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorStephen Hemminger <stephen.hemminger@vyatta.com>2008-01-23 00:56:34 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:11:00 -0500
commit9195bef7fb0ba0a91d5ffa566bcf8e007e3c7172 (patch)
tree417eb71596accb170cbd8cdc42598170e3024264 /net/ipv4
parenta88ee229253b31e3a844b30525ff77fbfe3111d3 (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.c50
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/*
1549static int trie_leaf_remove(struct trie *t, t_key key) 1549 * Remove the leaf and return parent.
1550 */
1551static 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)
1778static int fn_trie_flush(struct fib_table *tb) 1752static 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;