]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/ipv4/fib_trie.c
[NETFILTER]: Add partial checksum validation helper
[mv-sheeva.git] / net / ipv4 / fib_trie.c
index ce6cb34e28e1bab0269bdd9c5d16fac8d39ddd4a..1ada5a6b03ea2b49ba281d5373e397453031d1f2 100644 (file)
@@ -122,7 +122,10 @@ struct tnode {
        unsigned char bits;             /* 2log(KEYLENGTH) bits needed */
        unsigned int full_children;     /* KEYLENGTH bits needed */
        unsigned int empty_children;    /* KEYLENGTH bits needed */
-       struct rcu_head rcu;
+       union {
+               struct rcu_head rcu;
+               struct work_struct work;
+       };
        struct node *child[0];
 };
 
@@ -160,7 +163,6 @@ static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n,
 static struct node *resize(struct trie *t, struct tnode *tn);
 static struct tnode *inflate(struct trie *t, struct tnode *tn);
 static struct tnode *halve(struct trie *t, struct tnode *tn);
-static void tnode_free(struct tnode *tn);
 
 static struct kmem_cache *fn_alias_kmem __read_mostly;
 static struct kmem_cache *trie_leaf_kmem __read_mostly;
@@ -334,6 +336,11 @@ static void __leaf_free_rcu(struct rcu_head *head)
        kmem_cache_free(trie_leaf_kmem, l);
 }
 
+static inline void free_leaf(struct leaf *l)
+{
+       call_rcu_bh(&l->rcu, __leaf_free_rcu);
+}
+
 static void __leaf_info_free_rcu(struct rcu_head *head)
 {
        kfree(container_of(head, struct leaf_info, rcu));
@@ -346,16 +353,16 @@ static inline void free_leaf_info(struct leaf_info *leaf)
 
 static struct tnode *tnode_alloc(size_t size)
 {
-       struct page *pages;
-
        if (size <= PAGE_SIZE)
                return kzalloc(size, GFP_KERNEL);
+       else
+               return __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
+}
 
-       pages = alloc_pages(GFP_KERNEL|__GFP_ZERO, get_order(size));
-       if (!pages)
-               return NULL;
-
-       return page_address(pages);
+static void __tnode_vfree(struct work_struct *arg)
+{
+       struct tnode *tn = container_of(arg, struct tnode, work);
+       vfree(tn);
 }
 
 static void __tnode_free_rcu(struct rcu_head *head)
@@ -366,16 +373,17 @@ static void __tnode_free_rcu(struct rcu_head *head)
 
        if (size <= PAGE_SIZE)
                kfree(tn);
-       else
-               free_pages((unsigned long)tn, get_order(size));
+       else {
+               INIT_WORK(&tn->work, __tnode_vfree);
+               schedule_work(&tn->work);
+       }
 }
 
 static inline void tnode_free(struct tnode *tn)
 {
-       if (IS_LEAF(tn)) {
-               struct leaf *l = (struct leaf *) tn;
-               call_rcu_bh(&l->rcu, __leaf_free_rcu);
-       } else
+       if (IS_LEAF(tn))
+               free_leaf((struct leaf *) tn);
+       else
                call_rcu(&tn->rcu, __tnode_free_rcu);
 }
 
@@ -1086,7 +1094,7 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
        li = leaf_info_new(plen);
 
        if (!li) {
-               tnode_free((struct tnode *) l);
+               free_leaf(l);
                return NULL;
        }
 
@@ -1122,7 +1130,7 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
 
                if (!tn) {
                        free_leaf_info(li);
-                       tnode_free((struct tnode *) l);
+                       free_leaf(l);
                        return NULL;
                }
 
@@ -1578,7 +1586,7 @@ static void trie_leaf_remove(struct trie *t, struct leaf *l)
        } else
                rcu_assign_pointer(t->trie, NULL);
 
-       tnode_free((struct tnode *) l);
+       free_leaf(l);
 }
 
 /*
@@ -1665,7 +1673,7 @@ static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg)
        return 0;
 }
 
-static int trie_flush_list(struct trie *t, struct list_head *head)
+static int trie_flush_list(struct list_head *head)
 {
        struct fib_alias *fa, *fa_node;
        int found = 0;
@@ -1683,7 +1691,7 @@ static int trie_flush_list(struct trie *t, struct list_head *head)
        return found;
 }
 
-static int trie_flush_leaf(struct trie *t, struct leaf *l)
+static int trie_flush_leaf(struct leaf *l)
 {
        int found = 0;
        struct hlist_head *lih = &l->list;
@@ -1691,7 +1699,7 @@ static int trie_flush_leaf(struct trie *t, struct leaf *l)
        struct leaf_info *li = NULL;
 
        hlist_for_each_entry_safe(li, node, tmp, lih, hlist) {
-               found += trie_flush_list(t, &li->falh);
+               found += trie_flush_list(&li->falh);
 
                if (list_empty(&li->falh)) {
                        hlist_del_rcu(&li->hlist);
@@ -1782,7 +1790,7 @@ static int fn_trie_flush(struct fib_table *tb)
        int found = 0;
 
        for (l = trie_firstleaf(t); l; l = trie_nextleaf(l)) {
-               found += trie_flush_leaf(t, l);
+               found += trie_flush_leaf(l);
 
                if (ll && hlist_empty(&ll->list))
                        trie_leaf_remove(t, ll);
@@ -2279,9 +2287,10 @@ static const struct file_operations fib_triestat_fops = {
        .release = fib_triestat_seq_release,
 };
 
-static struct node *fib_trie_get_idx(struct fib_trie_iter *iter, loff_t pos)
+static struct node *fib_trie_get_idx(struct seq_file *seq, loff_t pos)
 {
-       struct net *net = iter->p.net;
+       struct fib_trie_iter *iter = seq->private;
+       struct net *net = seq_file_net(seq);
        loff_t idx = 0;
        unsigned int h;
 
@@ -2309,16 +2318,14 @@ static struct node *fib_trie_get_idx(struct fib_trie_iter *iter, loff_t pos)
 static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
        __acquires(RCU)
 {
-       struct fib_trie_iter *iter = seq->private;
-
        rcu_read_lock();
-       return fib_trie_get_idx(iter, *pos);
+       return fib_trie_get_idx(seq, *pos);
 }
 
 static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
        struct fib_trie_iter *iter = seq->private;
-       struct net *net = iter->p.net;
+       struct net *net = seq_file_net(seq);
        struct fib_table *tb = iter->tb;
        struct hlist_node *tb_node;
        unsigned int h;
@@ -2513,7 +2520,7 @@ static void *fib_route_seq_start(struct seq_file *seq, loff_t *pos)
        struct fib_table *tb;
 
        rcu_read_lock();
-       tb = fib_get_table(iter->p.net, RT_TABLE_MAIN);
+       tb = fib_get_table(seq_file_net(seq), RT_TABLE_MAIN);
        if (!tb)
                return NULL;