]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/ipv4/fib_hash.c
[IPV4]: Unify assignment of fi to fib_result
[karo-tx-linux.git] / net / ipv4 / fib_hash.c
index 9ad1d9ff9ce777232b69ad84d083fa3ba3b0b4c9..86087d45c64e29548fdc134fe5dcf330f6f65654 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/netlink.h>
 #include <linux/init.h>
 
+#include <net/net_namespace.h>
 #include <net/ip.h>
 #include <net/protocol.h>
 #include <net/route.h>
@@ -101,10 +102,10 @@ static struct hlist_head *fz_hash_alloc(int divisor)
        unsigned long size = divisor * sizeof(struct hlist_head);
 
        if (size <= PAGE_SIZE) {
-               return kmalloc(size, GFP_KERNEL);
+               return kzalloc(size, GFP_KERNEL);
        } else {
                return (struct hlist_head *)
-                       __get_free_pages(GFP_KERNEL, get_order(size));
+                       __get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(size));
        }
 }
 
@@ -173,8 +174,6 @@ static void fn_rehash_zone(struct fn_zone *fz)
        ht = fz_hash_alloc(new_divisor);
 
        if (ht) {
-               memset(ht, 0, new_divisor * sizeof(struct hlist_head));
-
                write_lock_bh(&fib_hash_lock);
                old_ht = fz->fz_hash;
                fz->fz_hash = ht;
@@ -218,7 +217,6 @@ fn_new_zone(struct fn_hash *table, int z)
                kfree(fz);
                return NULL;
        }
-       memset(fz->fz_hash, 0, fz->fz_divisor * sizeof(struct hlist_head *));
        fz->fz_order = z;
        fz->fz_mask = inet_make_mask(z);
 
@@ -316,11 +314,8 @@ fn_hash_select_default(struct fib_table *tb, const struct flowi *flp, struct fib
                                if (next_fi != res->fi)
                                        break;
                        } else if (!fib_detect_death(fi, order, &last_resort,
-                                                    &last_idx, &fn_hash_last_dflt)) {
-                               if (res->fi)
-                                       fib_info_put(res->fi);
-                               res->fi = fi;
-                               atomic_inc(&fi->fib_clntref);
+                                                    &last_idx, fn_hash_last_dflt)) {
+                               fib_result_assign(res, fi);
                                fn_hash_last_dflt = order;
                                goto out;
                        }
@@ -334,22 +329,14 @@ fn_hash_select_default(struct fib_table *tb, const struct flowi *flp, struct fib
                goto out;
        }
 
-       if (!fib_detect_death(fi, order, &last_resort, &last_idx, &fn_hash_last_dflt)) {
-               if (res->fi)
-                       fib_info_put(res->fi);
-               res->fi = fi;
-               atomic_inc(&fi->fib_clntref);
+       if (!fib_detect_death(fi, order, &last_resort, &last_idx, fn_hash_last_dflt)) {
+               fib_result_assign(res, fi);
                fn_hash_last_dflt = order;
                goto out;
        }
 
-       if (last_idx >= 0) {
-               if (res->fi)
-                       fib_info_put(res->fi);
-               res->fi = last_resort;
-               if (last_resort)
-                       atomic_inc(&last_resort->fib_clntref);
-       }
+       if (last_idx >= 0)
+               fib_result_assign(res, last_resort);
        fn_hash_last_dflt = last_idx;
 out:
        read_unlock(&fib_hash_lock);
@@ -443,6 +430,9 @@ static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg)
                        struct fib_info *fi_drop;
                        u8 state;
 
+                       if (fi->fib_treeref > 1)
+                               goto out;
+
                        write_lock_bh(&fib_hash_lock);
                        fi_drop = fa->fa_info;
                        fa->fa_info = fi;
@@ -717,19 +707,18 @@ fn_hash_dump_zone(struct sk_buff *skb, struct netlink_callback *cb,
 {
        int h, s_h;
 
+       if (fz->fz_hash == NULL)
+               return skb->len;
        s_h = cb->args[3];
-       for (h=0; h < fz->fz_divisor; h++) {
-               if (h < s_h) continue;
-               if (h > s_h)
-                       memset(&cb->args[4], 0,
-                              sizeof(cb->args) - 4*sizeof(cb->args[0]));
-               if (fz->fz_hash == NULL ||
-                   hlist_empty(&fz->fz_hash[h]))
+       for (h = s_h; h < fz->fz_divisor; h++) {
+               if (hlist_empty(&fz->fz_hash[h]))
                        continue;
-               if (fn_hash_dump_bucket(skb, cb, tb, fz, &fz->fz_hash[h])<0) {
+               if (fn_hash_dump_bucket(skb, cb, tb, fz, &fz->fz_hash[h]) < 0) {
                        cb->args[3] = h;
                        return -1;
                }
+               memset(&cb->args[4], 0,
+                      sizeof(cb->args) - 4*sizeof(cb->args[0]));
        }
        cb->args[3] = h;
        return skb->len;
@@ -745,14 +734,13 @@ static int fn_hash_dump(struct fib_table *tb, struct sk_buff *skb, struct netlin
        read_lock(&fib_hash_lock);
        for (fz = table->fn_zone_list, m=0; fz; fz = fz->fz_next, m++) {
                if (m < s_m) continue;
-               if (m > s_m)
-                       memset(&cb->args[3], 0,
-                              sizeof(cb->args) - 3*sizeof(cb->args[0]));
                if (fn_hash_dump_zone(skb, cb, tb, fz) < 0) {
                        cb->args[2] = m;
                        read_unlock(&fib_hash_lock);
                        return -1;
                }
+               memset(&cb->args[3], 0,
+                      sizeof(cb->args) - 3*sizeof(cb->args[0]));
        }
        read_unlock(&fib_hash_lock);
        cb->args[2] = m;
@@ -812,7 +800,8 @@ struct fib_iter_state {
 static struct fib_alias *fib_get_first(struct seq_file *seq)
 {
        struct fib_iter_state *iter = seq->private;
-       struct fn_hash *table = (struct fn_hash *) ip_fib_main_table->tb_data;
+       struct fib_table *main_table = fib_get_table(RT_TABLE_MAIN);
+       struct fn_hash *table = (struct fn_hash *)main_table->tb_data;
 
        iter->bucket    = 0;
        iter->hash_head = NULL;
@@ -951,7 +940,7 @@ static void *fib_seq_start(struct seq_file *seq, loff_t *pos)
        void *v = NULL;
 
        read_lock(&fib_hash_lock);
-       if (ip_fib_main_table)
+       if (fib_get_table(RT_TABLE_MAIN))
                v = *pos ? fib_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
        return v;
 }
@@ -1038,24 +1027,8 @@ static const struct seq_operations fib_seq_ops = {
 
 static int fib_seq_open(struct inode *inode, struct file *file)
 {
-       struct seq_file *seq;
-       int rc = -ENOMEM;
-       struct fib_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
-
-       if (!s)
-               goto out;
-
-       rc = seq_open(file, &fib_seq_ops);
-       if (rc)
-               goto out_kfree;
-
-       seq          = file->private_data;
-       seq->private = s;
-out:
-       return rc;
-out_kfree:
-       kfree(s);
-       goto out;
+       return seq_open_private(file, &fib_seq_ops,
+                       sizeof(struct fib_iter_state));
 }
 
 static const struct file_operations fib_seq_fops = {
@@ -1068,13 +1041,13 @@ static const struct file_operations fib_seq_fops = {
 
 int __init fib_proc_init(void)
 {
-       if (!proc_net_fops_create("route", S_IRUGO, &fib_seq_fops))
+       if (!proc_net_fops_create(&init_net, "route", S_IRUGO, &fib_seq_fops))
                return -ENOMEM;
        return 0;
 }
 
 void __init fib_proc_exit(void)
 {
-       proc_net_remove("route");
+       proc_net_remove(&init_net, "route");
 }
 #endif /* CONFIG_PROC_FS */