X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=datapath%2Fflow.c;h=8be380182dbd963ea19c7ec67b5162995acb84dd;hb=9d73c9cac76ba557fdac4a89c1b7eafe132b85a3;hp=9b3d3a753e7b9773046ebd688a8bf5d37a14e787;hpb=4b6ab2b0ae49194e4ff78cc005921286aa9be140;p=sliver-openvswitch.git diff --git a/datapath/flow.c b/datapath/flow.c index 9b3d3a753..8be380182 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -87,17 +87,25 @@ void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb) spin_unlock(&stats->lock); } -static void stats_read(struct flow_stats *stats, +static void stats_read(struct flow_stats *stats, bool lock_bh, struct ovs_flow_stats *ovs_stats, unsigned long *used, __be16 *tcp_flags) { - spin_lock(&stats->lock); + if (lock_bh) + spin_lock_bh(&stats->lock); + else + spin_lock(&stats->lock); + if (time_after(stats->used, *used)) *used = stats->used; *tcp_flags |= stats->tcp_flags; ovs_stats->n_packets += stats->packet_count; ovs_stats->n_bytes += stats->byte_count; - spin_unlock(&stats->lock); + + if (lock_bh) + spin_unlock_bh(&stats->lock); + else + spin_unlock(&stats->lock); } void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats, @@ -110,33 +118,38 @@ void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats, memset(ovs_stats, 0, sizeof(*ovs_stats)); if (!flow->stats.is_percpu) { - stats_read(flow->stats.stat, ovs_stats, used, tcp_flags); + stats_read(flow->stats.stat, true, ovs_stats, used, tcp_flags); } else { cur_cpu = get_cpu(); + for_each_possible_cpu(cpu) { struct flow_stats *stats; - - if (cpu == cur_cpu) - local_bh_disable(); + bool lock_bh; stats = per_cpu_ptr(flow->stats.cpu_stats, cpu); - stats_read(stats, ovs_stats, used, tcp_flags); - - if (cpu == cur_cpu) - local_bh_enable(); + lock_bh = (cpu == cur_cpu); + stats_read(stats, lock_bh, ovs_stats, used, tcp_flags); } put_cpu(); } } -static void stats_reset(struct flow_stats *stats) +static void stats_reset(struct flow_stats *stats, bool lock_bh) { - spin_lock(&stats->lock); + if (lock_bh) + spin_lock_bh(&stats->lock); + else + spin_lock(&stats->lock); + stats->used = 0; stats->packet_count = 0; stats->byte_count = 0; stats->tcp_flags = 0; - spin_unlock(&stats->lock); + + if (lock_bh) + spin_unlock_bh(&stats->lock); + else + spin_unlock(&stats->lock); } void ovs_flow_stats_clear(struct sw_flow *flow) @@ -144,19 +157,15 @@ void ovs_flow_stats_clear(struct sw_flow *flow) int cpu, cur_cpu; if (!flow->stats.is_percpu) { - stats_reset(flow->stats.stat); + stats_reset(flow->stats.stat, true); } else { cur_cpu = get_cpu(); for_each_possible_cpu(cpu) { + bool lock_bh; - if (cpu == cur_cpu) - local_bh_disable(); - - stats_reset(per_cpu_ptr(flow->stats.cpu_stats, cpu)); - - if (cpu == cur_cpu) - local_bh_enable(); + lock_bh = (cpu == cur_cpu); + stats_reset(per_cpu_ptr(flow->stats.cpu_stats, cpu), lock_bh); } put_cpu(); }