[IPV4]: Handle large allocations in fib_trie
authorPatrick McHardy <kaber@trash.net>
Tue, 5 Jul 2005 21:44:55 +0000 (14:44 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 5 Jul 2005 21:44:55 +0000 (14:44 -0700)
Inflating a node a couple of times makes it exceed the 128k kmalloc limit.
Use __get_free_pages for allocations > PAGE_SIZE, as in fib_hash.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Acked-by: Robert Olsson <Robert.Olsson@data.slu.se>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/fib_trie.c

index b56e88edf1b351a10a8d83a0abf0a20f4c663e29..9038b914b4b14df4076d56abb1100d024bbb9039 100644 (file)
@@ -358,11 +358,32 @@ static inline void free_leaf_info(struct leaf_info *li)
        kfree(li);
 }
 
+static struct tnode *tnode_alloc(unsigned int size)
+{
+       if (size <= PAGE_SIZE) {
+               return kmalloc(size, GFP_KERNEL);
+       } else {
+               return (struct tnode *)
+                      __get_free_pages(GFP_KERNEL, get_order(size));
+       }
+}
+
+static void __tnode_free(struct tnode *tn)
+{
+       unsigned int size = sizeof(struct tnode) +
+                           (1<<tn->bits) * sizeof(struct node *);
+
+       if (size <= PAGE_SIZE)
+               kfree(tn);
+       else
+               free_pages((unsigned long)tn, get_order(size));
+}
+
 static struct tnode* tnode_new(t_key key, int pos, int bits)
 {
        int nchildren = 1<<bits;
        int sz = sizeof(struct tnode) + nchildren * sizeof(struct node *);
-       struct tnode *tn = kmalloc(sz,  GFP_KERNEL);
+       struct tnode *tn = tnode_alloc(sz);
 
        if(tn)  {
                memset(tn, 0, sz);
@@ -390,7 +411,7 @@ static void tnode_free(struct tnode *tn)
                        printk("FL %p \n", tn);
        }
        else if(IS_TNODE(tn)) { 
-               kfree(tn);
+               __tnode_free(tn);
                if(trie_debug > 0 ) 
                        printk("FT %p \n", tn);
        }