X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=net%2Fipv4%2Ffib_trie.c;h=fc0624e6a649b5dd94d873aefe65a3368d3b95cc;hb=8ad4942cd5bdad4143f7aa1d1bd4f7b2526c19c5;hp=8d8c2915e064f98d16d1409c2524f2277107185b;hpb=b3d9d6be035a7d1cc6740cee695301bf37caedcd;p=linux-2.6-omap-h63xx.git diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 8d8c2915e06..fc0624e6a64 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -164,7 +164,6 @@ 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 trie *trie_local = NULL, *trie_main = NULL; static inline struct tnode *node_parent(struct node *node) { @@ -300,10 +299,10 @@ static inline void check_tnode(const struct tnode *tn) WARN_ON(tn && tn->pos+tn->bits > 32); } -static int halve_threshold = 25; -static int inflate_threshold = 50; -static int halve_threshold_root = 8; -static int inflate_threshold_root = 15; +static const int halve_threshold = 25; +static const int inflate_threshold = 50; +static const int halve_threshold_root = 8; +static const int inflate_threshold_root = 15; static void __alias_free_mem(struct rcu_head *head) @@ -1214,6 +1213,9 @@ static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) struct fib_info *fi_drop; u8 state; + if (fi->fib_treeref > 1) + goto out; + err = -ENOBUFS; new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL); if (new_fa == NULL) @@ -1780,8 +1782,6 @@ static int fn_trie_flush(struct fib_table *tb) return found; } -static int trie_last_dflt = -1; - static void fn_trie_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res) { @@ -1828,39 +1828,29 @@ fn_trie_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, &trie_last_dflt)) { - if (res->fi) - fib_info_put(res->fi); - res->fi = fi; - atomic_inc(&fi->fib_clntref); - trie_last_dflt = order; + &last_idx, tb->tb_default)) { + fib_result_assign(res, fi); + tb->tb_default = order; goto out; } fi = next_fi; order++; } if (order <= 0 || fi == NULL) { - trie_last_dflt = -1; + tb->tb_default = -1; goto out; } - if (!fib_detect_death(fi, order, &last_resort, &last_idx, &trie_last_dflt)) { - if (res->fi) - fib_info_put(res->fi); - res->fi = fi; - atomic_inc(&fi->fib_clntref); - trie_last_dflt = order; + if (!fib_detect_death(fi, order, &last_resort, &last_idx, + tb->tb_default)) { + fib_result_assign(res, fi); + tb->tb_default = 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); - } - trie_last_dflt = last_idx; - out:; + if (last_idx >= 0) + fib_result_assign(res, last_resort); + tb->tb_default = last_idx; +out: rcu_read_unlock(); } @@ -1966,11 +1956,7 @@ out: /* Fix more generic FIB names for init later */ -#ifdef CONFIG_IP_MULTIPLE_TABLES -struct fib_table * fib_hash_init(u32 id) -#else -struct fib_table * __init fib_hash_init(u32 id) -#endif +struct fib_table *fib_hash_init(u32 id) { struct fib_table *tb; struct trie *t; @@ -1987,6 +1973,7 @@ struct fib_table * __init fib_hash_init(u32 id) return NULL; tb->tb_id = id; + tb->tb_default = -1; tb->tb_lookup = fn_trie_lookup; tb->tb_insert = fn_trie_insert; tb->tb_delete = fn_trie_delete; @@ -1999,11 +1986,6 @@ struct fib_table * __init fib_hash_init(u32 id) trie_init(t); - if (id == RT_TABLE_LOCAL) - trie_local = t; - else if (id == RT_TABLE_MAIN) - trie_main = t; - if (id == RT_TABLE_LOCAL) printk(KERN_INFO "IPv4 FIB: Using LC-trie version %s\n", VERSION); @@ -2013,6 +1995,7 @@ struct fib_table * __init fib_hash_init(u32 id) #ifdef CONFIG_PROC_FS /* Depth first Trie walk iterator */ struct fib_trie_iter { + struct trie *trie_local, *trie_main; struct tnode *tnode; struct trie *trie; unsigned index; @@ -2179,7 +2162,20 @@ static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat) static int fib_triestat_seq_show(struct seq_file *seq, void *v) { + struct trie *trie_local, *trie_main; struct trie_stat *stat; + struct fib_table *tb; + + trie_local = NULL; + tb = fib_get_table(&init_net, RT_TABLE_LOCAL); + if (tb) + trie_local = (struct trie *) tb->tb_data; + + trie_main = NULL; + tb = fib_get_table(&init_net, RT_TABLE_MAIN); + if (tb) + trie_main = (struct trie *) tb->tb_data; + stat = kmalloc(sizeof(*stat), GFP_KERNEL); if (!stat) @@ -2223,13 +2219,13 @@ static struct node *fib_trie_get_idx(struct fib_trie_iter *iter, loff_t idx = 0; struct node *n; - for (n = fib_trie_get_first(iter, trie_local); + for (n = fib_trie_get_first(iter, iter->trie_local); n; ++idx, n = fib_trie_get_next(iter)) { if (pos == idx) return n; } - for (n = fib_trie_get_first(iter, trie_main); + for (n = fib_trie_get_first(iter, iter->trie_main); n; ++idx, n = fib_trie_get_next(iter)) { if (pos == idx) return n; @@ -2239,10 +2235,23 @@ static struct node *fib_trie_get_idx(struct fib_trie_iter *iter, static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos) { + struct fib_trie_iter *iter = seq->private; + struct fib_table *tb; + + if (!iter->trie_local) { + tb = fib_get_table(&init_net, RT_TABLE_LOCAL); + if (tb) + iter->trie_local = (struct trie *) tb->tb_data; + } + if (!iter->trie_main) { + tb = fib_get_table(&init_net, RT_TABLE_MAIN); + if (tb) + iter->trie_main = (struct trie *) tb->tb_data; + } rcu_read_lock(); if (*pos == 0) return SEQ_START_TOKEN; - return fib_trie_get_idx(seq->private, *pos - 1); + return fib_trie_get_idx(iter, *pos - 1); } static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos) @@ -2260,8 +2269,8 @@ static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos) return v; /* continue scan in next trie */ - if (iter->trie == trie_local) - return fib_trie_get_first(iter, trie_main); + if (iter->trie == iter->trie_local) + return fib_trie_get_first(iter, iter->trie_main); return NULL; } @@ -2327,7 +2336,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v) return 0; if (!node_parent(n)) { - if (iter->trie == trie_local) + if (iter->trie == iter->trie_local) seq_puts(seq, ":\n"); else seq_puts(seq, "
:\n"); @@ -2426,7 +2435,7 @@ static int fib_route_seq_show(struct seq_file *seq, void *v) return 0; } - if (iter->trie == trie_local) + if (iter->trie == iter->trie_local) return 0; if (IS_TNODE(l)) return 0; @@ -2495,32 +2504,33 @@ static const struct file_operations fib_route_fops = { .release = seq_release_private, }; -int __init fib_proc_init(void) +int __net_init fib_proc_init(struct net *net) { - if (!proc_net_fops_create(&init_net, "fib_trie", S_IRUGO, &fib_trie_fops)) + if (!proc_net_fops_create(net, "fib_trie", S_IRUGO, &fib_trie_fops)) goto out1; - if (!proc_net_fops_create(&init_net, "fib_triestat", S_IRUGO, &fib_triestat_fops)) + if (!proc_net_fops_create(net, "fib_triestat", S_IRUGO, + &fib_triestat_fops)) goto out2; - if (!proc_net_fops_create(&init_net, "route", S_IRUGO, &fib_route_fops)) + if (!proc_net_fops_create(net, "route", S_IRUGO, &fib_route_fops)) goto out3; return 0; out3: - proc_net_remove(&init_net, "fib_triestat"); + proc_net_remove(net, "fib_triestat"); out2: - proc_net_remove(&init_net, "fib_trie"); + proc_net_remove(net, "fib_trie"); out1: return -ENOMEM; } -void __init fib_proc_exit(void) +void __net_exit fib_proc_exit(struct net *net) { - proc_net_remove(&init_net, "fib_trie"); - proc_net_remove(&init_net, "fib_triestat"); - proc_net_remove(&init_net, "route"); + proc_net_remove(net, "fib_trie"); + proc_net_remove(net, "fib_triestat"); + proc_net_remove(net, "route"); } #endif /* CONFIG_PROC_FS */