You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
2.9 KiB
96 lines
2.9 KiB
10 years ago
|
From: Alexander Duyck <alexander.h.duyck@redhat.com>
|
||
|
Date: Wed, 31 Dec 2014 10:57:02 -0800
|
||
|
Subject: [PATCH] fib_trie: Remove checks for index >= tnode_child_length
|
||
|
from tnode_get_child
|
||
|
|
||
|
For some reason the compiler doesn't seem to understand that when we are in
|
||
|
a loop that runs from tnode_child_length - 1 to 0 we don't expect the value
|
||
|
of tn->bits to change. As such every call to tnode_get_child was rerunning
|
||
|
tnode_chile_length which ended up consuming quite a bit of space in the
|
||
|
resultant assembly code.
|
||
|
|
||
|
I have gone though and verified that in all cases where tnode_get_child
|
||
|
is used we are either winding though a fixed loop from tnode_child_length -
|
||
|
1 to 0, or are in a fastpath case where we are verifying the value by
|
||
|
either checking for any remaining bits after shifting index by bits and
|
||
|
testing for leaf, or by using tnode_child_length.
|
||
|
|
||
|
size net/ipv4/fib_trie.o
|
||
|
Before:
|
||
|
text data bss dec hex filename
|
||
|
15506 376 8 15890 3e12 net/ipv4/fib_trie.o
|
||
|
|
||
|
After:
|
||
|
text data bss dec hex filename
|
||
|
14827 376 8 15211 3b6b net/ipv4/fib_trie.o
|
||
|
|
||
|
Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com>
|
||
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||
|
---
|
||
|
|
||
|
--- a/net/ipv4/fib_trie.c
|
||
|
+++ b/net/ipv4/fib_trie.c
|
||
|
@@ -186,8 +186,6 @@ static inline unsigned long tnode_child_
|
||
|
static inline struct tnode *tnode_get_child(const struct tnode *tn,
|
||
|
unsigned long i)
|
||
|
{
|
||
|
- BUG_ON(i >= tnode_child_length(tn));
|
||
|
-
|
||
|
return rtnl_dereference(tn->child[i]);
|
||
|
}
|
||
|
|
||
|
@@ -195,8 +193,6 @@ static inline struct tnode *tnode_get_ch
|
||
|
static inline struct tnode *tnode_get_child_rcu(const struct tnode *tn,
|
||
|
unsigned long i)
|
||
|
{
|
||
|
- BUG_ON(i >= tnode_child_length(tn));
|
||
|
-
|
||
|
return rcu_dereference_rtnl(tn->child[i]);
|
||
|
}
|
||
|
|
||
|
@@ -371,7 +367,7 @@ static inline int tnode_full(const struc
|
||
|
*/
|
||
|
static void put_child(struct tnode *tn, unsigned long i, struct tnode *n)
|
||
|
{
|
||
|
- struct tnode *chi = rtnl_dereference(tn->child[i]);
|
||
|
+ struct tnode *chi = tnode_get_child(tn, i);
|
||
|
int isfull, wasfull;
|
||
|
|
||
|
BUG_ON(i >= tnode_child_length(tn));
|
||
|
@@ -867,7 +863,7 @@ static struct tnode *fib_find_node(struc
|
||
|
if (IS_LEAF(n))
|
||
|
break;
|
||
|
|
||
|
- n = rcu_dereference_rtnl(n->child[index]);
|
||
|
+ n = tnode_get_child_rcu(n, index);
|
||
|
}
|
||
|
|
||
|
return n;
|
||
|
@@ -934,7 +930,7 @@ static struct list_head *fib_insert_node
|
||
|
}
|
||
|
|
||
|
tp = n;
|
||
|
- n = rcu_dereference_rtnl(n->child[index]);
|
||
|
+ n = tnode_get_child_rcu(n, index);
|
||
|
}
|
||
|
|
||
|
l = leaf_new(key);
|
||
|
@@ -1215,7 +1211,7 @@ int fib_table_lookup(struct fib_table *t
|
||
|
cindex = index;
|
||
|
}
|
||
|
|
||
|
- n = rcu_dereference(n->child[index]);
|
||
|
+ n = tnode_get_child_rcu(n, index);
|
||
|
if (unlikely(!n))
|
||
|
goto backtrace;
|
||
|
}
|
||
|
@@ -1835,7 +1831,7 @@ static void trie_collect_stats(struct tr
|
||
|
if (n->bits < MAX_STAT_DEPTH)
|
||
|
s->nodesizes[n->bits]++;
|
||
|
|
||
|
- for (i = 0; i < tnode_child_length(n); i++) {
|
||
|
+ for (i = tnode_child_length(n); i--;) {
|
||
|
if (!rcu_access_pointer(n->child[i]))
|
||
|
s->nullpointers++;
|
||
|
}
|