aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_trie.c
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@redhat.com>2015-03-06 12:54:33 -0500
committerDavid S. Miller <davem@davemloft.net>2015-03-06 15:49:28 -0500
commit56ca2adf6ac1fca57f504ac1d76f7dff1dc08d3a (patch)
treedf9c55fc8ba9fd2bd111382eed0284395b9275f0 /net/ipv4/fib_trie.c
parentdc35dbeda3e00a05723784078a233c2531d34810 (diff)
fib_trie: Move rcu from key_vector to tnode, add accessors.
RCU is only needed once for the entire node, not once per key_vector so we can pull that out and move it to the tnode structure. In addition add accessors to be used inside the RCU functions so that we can more easily get from the key vector to either the tnode or the trie pointers. Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/fib_trie.c')
-rw-r--r--net/ipv4/fib_trie.c34
1 files changed, 16 insertions, 18 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 3a062370fc32..b9b5bbacace6 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -93,8 +93,6 @@ typedef unsigned int t_key;
93#define IS_LEAF(n) (!(n)->bits) 93#define IS_LEAF(n) (!(n)->bits)
94 94
95struct key_vector { 95struct key_vector {
96 struct rcu_head rcu;
97
98 t_key empty_children; /* KEYLENGTH bits needed */ 96 t_key empty_children; /* KEYLENGTH bits needed */
99 t_key full_children; /* KEYLENGTH bits needed */ 97 t_key full_children; /* KEYLENGTH bits needed */
100 struct key_vector __rcu *parent; 98 struct key_vector __rcu *parent;
@@ -112,7 +110,9 @@ struct key_vector {
112}; 110};
113 111
114struct tnode { 112struct tnode {
113 struct rcu_head rcu;
115 struct key_vector kv[1]; 114 struct key_vector kv[1];
115#define tn_bits kv[0].bits
116}; 116};
117 117
118#define TNODE_SIZE(n) offsetof(struct tnode, kv[0].tnode[n]) 118#define TNODE_SIZE(n) offsetof(struct tnode, kv[0].tnode[n])
@@ -159,6 +159,11 @@ static const int sync_pages = 128;
159static struct kmem_cache *fn_alias_kmem __read_mostly; 159static struct kmem_cache *fn_alias_kmem __read_mostly;
160static struct kmem_cache *trie_leaf_kmem __read_mostly; 160static struct kmem_cache *trie_leaf_kmem __read_mostly;
161 161
162static inline struct tnode *tn_info(struct key_vector *kv)
163{
164 return container_of(kv, struct tnode, kv[0]);
165}
166
162/* caller must hold RTNL */ 167/* caller must hold RTNL */
163#define node_parent(n) rtnl_dereference((n)->parent) 168#define node_parent(n) rtnl_dereference((n)->parent)
164#define get_child(tn, i) rtnl_dereference((tn)->tnode[i]) 169#define get_child(tn, i) rtnl_dereference((tn)->tnode[i])
@@ -191,13 +196,6 @@ static inline unsigned long get_index(t_key key, struct key_vector *kv)
191 return index >> kv->pos; 196 return index >> kv->pos;
192} 197}
193 198
194static inline struct fib_table *trie_get_table(struct trie *t)
195{
196 unsigned long *tb_data = (unsigned long *)t;
197
198 return container_of(tb_data, struct fib_table, tb_data[0]);
199}
200
201/* To understand this stuff, an understanding of keys and all their bits is 199/* To understand this stuff, an understanding of keys and all their bits is
202 * necessary. Every node in the trie has a key associated with it, but not 200 * necessary. Every node in the trie has a key associated with it, but not
203 * all of the bits in that key are significant. 201 * all of the bits in that key are significant.
@@ -280,17 +278,17 @@ static inline void alias_free_mem_rcu(struct fib_alias *fa)
280 278
281static void __node_free_rcu(struct rcu_head *head) 279static void __node_free_rcu(struct rcu_head *head)
282{ 280{
283 struct key_vector *n = container_of(head, struct key_vector, rcu); 281 struct tnode *n = container_of(head, struct tnode, rcu);
284 282
285 if (IS_LEAF(n)) 283 if (!n->tn_bits)
286 kmem_cache_free(trie_leaf_kmem, n); 284 kmem_cache_free(trie_leaf_kmem, n);
287 else if (n->bits <= TNODE_KMALLOC_MAX) 285 else if (n->tn_bits <= TNODE_KMALLOC_MAX)
288 kfree(n); 286 kfree(n);
289 else 287 else
290 vfree(n); 288 vfree(n);
291} 289}
292 290
293#define node_free(n) call_rcu(&n->rcu, __node_free_rcu) 291#define node_free(n) call_rcu(&tn_info(n)->rcu, __node_free_rcu)
294 292
295static struct tnode *tnode_alloc(int bits) 293static struct tnode *tnode_alloc(int bits)
296{ 294{
@@ -441,26 +439,26 @@ static inline void put_child_root(struct key_vector *tp, struct trie *t,
441 439
442static inline void tnode_free_init(struct key_vector *tn) 440static inline void tnode_free_init(struct key_vector *tn)
443{ 441{
444 tn->rcu.next = NULL; 442 tn_info(tn)->rcu.next = NULL;
445} 443}
446 444
447static inline void tnode_free_append(struct key_vector *tn, 445static inline void tnode_free_append(struct key_vector *tn,
448 struct key_vector *n) 446 struct key_vector *n)
449{ 447{
450 n->rcu.next = tn->rcu.next; 448 tn_info(n)->rcu.next = tn_info(tn)->rcu.next;
451 tn->rcu.next = &n->rcu; 449 tn_info(tn)->rcu.next = &tn_info(n)->rcu;
452} 450}
453 451
454static void tnode_free(struct key_vector *tn) 452static void tnode_free(struct key_vector *tn)
455{ 453{
456 struct callback_head *head = &tn->rcu; 454 struct callback_head *head = &tn_info(tn)->rcu;
457 455
458 while (head) { 456 while (head) {
459 head = head->next; 457 head = head->next;
460 tnode_free_size += TNODE_SIZE(1ul << tn->bits); 458 tnode_free_size += TNODE_SIZE(1ul << tn->bits);
461 node_free(tn); 459 node_free(tn);
462 460
463 tn = container_of(head, struct key_vector, rcu); 461 tn = container_of(head, struct tnode, rcu)->kv;
464 } 462 }
465 463
466 if (tnode_free_size >= PAGE_SIZE * sync_pages) { 464 if (tnode_free_size >= PAGE_SIZE * sync_pages) {