diff options
Diffstat (limited to 'net/ipv4/fib_trie.c')
-rw-r--r-- | net/ipv4/fib_trie.c | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 9e491e70e855..64a274282042 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -122,7 +122,10 @@ struct tnode { | |||
122 | unsigned char bits; /* 2log(KEYLENGTH) bits needed */ | 122 | unsigned char bits; /* 2log(KEYLENGTH) bits needed */ |
123 | unsigned int full_children; /* KEYLENGTH bits needed */ | 123 | unsigned int full_children; /* KEYLENGTH bits needed */ |
124 | unsigned int empty_children; /* KEYLENGTH bits needed */ | 124 | unsigned int empty_children; /* KEYLENGTH bits needed */ |
125 | struct rcu_head rcu; | 125 | union { |
126 | struct rcu_head rcu; | ||
127 | struct work_struct work; | ||
128 | }; | ||
126 | struct node *child[0]; | 129 | struct node *child[0]; |
127 | }; | 130 | }; |
128 | 131 | ||
@@ -346,16 +349,16 @@ static inline void free_leaf_info(struct leaf_info *leaf) | |||
346 | 349 | ||
347 | static struct tnode *tnode_alloc(size_t size) | 350 | static struct tnode *tnode_alloc(size_t size) |
348 | { | 351 | { |
349 | struct page *pages; | ||
350 | |||
351 | if (size <= PAGE_SIZE) | 352 | if (size <= PAGE_SIZE) |
352 | return kzalloc(size, GFP_KERNEL); | 353 | return kzalloc(size, GFP_KERNEL); |
354 | else | ||
355 | return __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL); | ||
356 | } | ||
353 | 357 | ||
354 | pages = alloc_pages(GFP_KERNEL|__GFP_ZERO, get_order(size)); | 358 | static void __tnode_vfree(struct work_struct *arg) |
355 | if (!pages) | 359 | { |
356 | return NULL; | 360 | struct tnode *tn = container_of(arg, struct tnode, work); |
357 | 361 | vfree(tn); | |
358 | return page_address(pages); | ||
359 | } | 362 | } |
360 | 363 | ||
361 | static void __tnode_free_rcu(struct rcu_head *head) | 364 | static void __tnode_free_rcu(struct rcu_head *head) |
@@ -366,8 +369,10 @@ static void __tnode_free_rcu(struct rcu_head *head) | |||
366 | 369 | ||
367 | if (size <= PAGE_SIZE) | 370 | if (size <= PAGE_SIZE) |
368 | kfree(tn); | 371 | kfree(tn); |
369 | else | 372 | else { |
370 | free_pages((unsigned long)tn, get_order(size)); | 373 | INIT_WORK(&tn->work, __tnode_vfree); |
374 | schedule_work(&tn->work); | ||
375 | } | ||
371 | } | 376 | } |
372 | 377 | ||
373 | static inline void tnode_free(struct tnode *tn) | 378 | static inline void tnode_free(struct tnode *tn) |