123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- From: Alexander Duyck <alexander.h.duyck@redhat.com>
- Date: Wed, 31 Dec 2014 10:55:29 -0800
- Subject: [PATCH] fib_trie: Update usage stats to be percpu instead of
- global variables
- The trie usage stats were currently being shared by all threads that were
- calling fib_table_lookup. As a result when multiple threads were
- performing lookups simultaneously the trie would begin to cache bounce
- between those threads.
- In order to prevent this I have updated the usage stats to use a set of
- percpu variables. By doing this we should be able to avoid the cache
- bouncing and still make use of these stats.
- Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com>
- Signed-off-by: David S. Miller <davem@davemloft.net>
- ---
- --- a/net/ipv4/fib_frontend.c
- +++ b/net/ipv4/fib_frontend.c
- @@ -67,7 +67,7 @@ static int __net_init fib4_rules_init(st
- return 0;
-
- fail:
- - kfree(local_table);
- + fib_free_table(local_table);
- return -ENOMEM;
- }
- #else
- --- a/net/ipv4/fib_trie.c
- +++ b/net/ipv4/fib_trie.c
- @@ -153,7 +153,7 @@ struct trie_stat {
- struct trie {
- struct rt_trie_node __rcu *trie;
- #ifdef CONFIG_IP_FIB_TRIE_STATS
- - struct trie_use_stats stats;
- + struct trie_use_stats __percpu *stats;
- #endif
- };
-
- @@ -631,7 +631,7 @@ static struct rt_trie_node *resize(struc
- if (IS_ERR(tn)) {
- tn = old_tn;
- #ifdef CONFIG_IP_FIB_TRIE_STATS
- - t->stats.resize_node_skipped++;
- + this_cpu_inc(t->stats->resize_node_skipped);
- #endif
- break;
- }
- @@ -658,7 +658,7 @@ static struct rt_trie_node *resize(struc
- if (IS_ERR(tn)) {
- tn = old_tn;
- #ifdef CONFIG_IP_FIB_TRIE_STATS
- - t->stats.resize_node_skipped++;
- + this_cpu_inc(t->stats->resize_node_skipped);
- #endif
- break;
- }
- @@ -1357,7 +1357,7 @@ static int check_leaf(struct fib_table *
- err = fib_props[fa->fa_type].error;
- if (err) {
- #ifdef CONFIG_IP_FIB_TRIE_STATS
- - t->stats.semantic_match_passed++;
- + this_cpu_inc(t->stats->semantic_match_passed);
- #endif
- return err;
- }
- @@ -1372,7 +1372,7 @@ static int check_leaf(struct fib_table *
- continue;
-
- #ifdef CONFIG_IP_FIB_TRIE_STATS
- - t->stats.semantic_match_passed++;
- + this_cpu_inc(t->stats->semantic_match_passed);
- #endif
- res->prefixlen = li->plen;
- res->nh_sel = nhsel;
- @@ -1388,7 +1388,7 @@ static int check_leaf(struct fib_table *
- }
-
- #ifdef CONFIG_IP_FIB_TRIE_STATS
- - t->stats.semantic_match_miss++;
- + this_cpu_inc(t->stats->semantic_match_miss);
- #endif
- }
-
- @@ -1399,6 +1399,9 @@ int fib_table_lookup(struct fib_table *t
- struct fib_result *res, int fib_flags)
- {
- struct trie *t = (struct trie *) tb->tb_data;
- +#ifdef CONFIG_IP_FIB_TRIE_STATS
- + struct trie_use_stats __percpu *stats = t->stats;
- +#endif
- int ret;
- struct rt_trie_node *n;
- struct tnode *pn;
- @@ -1417,7 +1420,7 @@ int fib_table_lookup(struct fib_table *t
- goto failed;
-
- #ifdef CONFIG_IP_FIB_TRIE_STATS
- - t->stats.gets++;
- + this_cpu_inc(stats->gets);
- #endif
-
- /* Just a leaf? */
- @@ -1441,7 +1444,7 @@ int fib_table_lookup(struct fib_table *t
-
- if (n == NULL) {
- #ifdef CONFIG_IP_FIB_TRIE_STATS
- - t->stats.null_node_hit++;
- + this_cpu_inc(stats->null_node_hit);
- #endif
- goto backtrace;
- }
- @@ -1576,7 +1579,7 @@ backtrace:
- chopped_off = 0;
-
- #ifdef CONFIG_IP_FIB_TRIE_STATS
- - t->stats.backtrack++;
- + this_cpu_inc(stats->backtrack);
- #endif
- goto backtrace;
- }
- @@ -1830,6 +1833,11 @@ int fib_table_flush(struct fib_table *tb
-
- void fib_free_table(struct fib_table *tb)
- {
- +#ifdef CONFIG_IP_FIB_TRIE_STATS
- + struct trie *t = (struct trie *)tb->tb_data;
- +
- + free_percpu(t->stats);
- +#endif /* CONFIG_IP_FIB_TRIE_STATS */
- kfree(tb);
- }
-
- @@ -1973,7 +1981,14 @@ struct fib_table *fib_trie_table(u32 id)
- tb->tb_num_default = 0;
-
- t = (struct trie *) tb->tb_data;
- - memset(t, 0, sizeof(*t));
- + RCU_INIT_POINTER(t->trie, NULL);
- +#ifdef CONFIG_IP_FIB_TRIE_STATS
- + t->stats = alloc_percpu(struct trie_use_stats);
- + if (!t->stats) {
- + kfree(tb);
- + tb = NULL;
- + }
- +#endif
-
- return tb;
- }
- @@ -2139,18 +2154,31 @@ static void trie_show_stats(struct seq_f
-
- #ifdef CONFIG_IP_FIB_TRIE_STATS
- static void trie_show_usage(struct seq_file *seq,
- - const struct trie_use_stats *stats)
- + const struct trie_use_stats __percpu *stats)
- {
- + struct trie_use_stats s = { 0 };
- + int cpu;
- +
- + /* loop through all of the CPUs and gather up the stats */
- + for_each_possible_cpu(cpu) {
- + const struct trie_use_stats *pcpu = per_cpu_ptr(stats, cpu);
- +
- + s.gets += pcpu->gets;
- + s.backtrack += pcpu->backtrack;
- + s.semantic_match_passed += pcpu->semantic_match_passed;
- + s.semantic_match_miss += pcpu->semantic_match_miss;
- + s.null_node_hit += pcpu->null_node_hit;
- + s.resize_node_skipped += pcpu->resize_node_skipped;
- + }
- +
- seq_printf(seq, "\nCounters:\n---------\n");
- - seq_printf(seq, "gets = %u\n", stats->gets);
- - seq_printf(seq, "backtracks = %u\n", stats->backtrack);
- + seq_printf(seq, "gets = %u\n", s.gets);
- + seq_printf(seq, "backtracks = %u\n", s.backtrack);
- seq_printf(seq, "semantic match passed = %u\n",
- - stats->semantic_match_passed);
- - seq_printf(seq, "semantic match miss = %u\n",
- - stats->semantic_match_miss);
- - seq_printf(seq, "null node hit= %u\n", stats->null_node_hit);
- - seq_printf(seq, "skipped node resize = %u\n\n",
- - stats->resize_node_skipped);
- + s.semantic_match_passed);
- + seq_printf(seq, "semantic match miss = %u\n", s.semantic_match_miss);
- + seq_printf(seq, "null node hit= %u\n", s.null_node_hit);
- + seq_printf(seq, "skipped node resize = %u\n\n", s.resize_node_skipped);
- }
- #endif /* CONFIG_IP_FIB_TRIE_STATS */
-
- @@ -2191,7 +2219,7 @@ static int fib_triestat_seq_show(struct
- trie_collect_stats(t, &stat);
- trie_show_stats(seq, &stat);
- #ifdef CONFIG_IP_FIB_TRIE_STATS
- - trie_show_usage(seq, &t->stats);
- + trie_show_usage(seq, t->stats);
- #endif
- }
- }
|