From 86ec8dbae27e5fa2b5d54f10f77286d9ef55732a Mon Sep 17 00:00:00 2001 From: Jarno Rajahalme Date: Mon, 5 May 2014 14:17:28 -0700 Subject: openvswitch: Fix ovs_flow_stats_get/clear RCU dereference. For ovs_flow_stats_get() using ovsl_dereference() was wrong, since flow dumps call this with RCU read lock. ovs_flow_stats_clear() is always called with ovs_mutex, so can use ovsl_dereference(). Also, make the ovs_flow_stats_get() 'flow' argument const to make later patches cleaner. Signed-off-by: Jarno Rajahalme Signed-off-by: Pravin B Shelar --- net/openvswitch/flow.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'net/openvswitch/flow.c') diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 1019fc1db06e..334751cb1528 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c @@ -122,8 +122,9 @@ unlock: spin_unlock(&stats->lock); } -/* Called with ovs_mutex. */ -void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats, +/* Must be called with rcu_read_lock or ovs_mutex. */ +void ovs_flow_stats_get(const struct sw_flow *flow, + struct ovs_flow_stats *ovs_stats, unsigned long *used, __be16 *tcp_flags) { int node; @@ -133,7 +134,7 @@ void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats, memset(ovs_stats, 0, sizeof(*ovs_stats)); for_each_node(node) { - struct flow_stats *stats = ovsl_dereference(flow->stats[node]); + struct flow_stats *stats = rcu_dereference_ovsl(flow->stats[node]); if (stats) { /* Local CPU may write on non-local stats, so we must @@ -150,12 +151,13 @@ void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *ovs_stats, } } +/* Called with ovs_mutex. */ void ovs_flow_stats_clear(struct sw_flow *flow) { int node; for_each_node(node) { - struct flow_stats *stats = rcu_dereference(flow->stats[node]); + struct flow_stats *stats = ovsl_dereference(flow->stats[node]); if (stats) { spin_lock_bh(&stats->lock); -- cgit