datapath/flow: Fix ovs_flow_stats_get/clear RCU dereference.
authorJarno Rajahalme <jrajahalme@nicira.com>
Wed, 2 Apr 2014 18:14:58 +0000 (11:14 -0700)
committerJarno Rajahalme <jrajahalme@nicira.com>
Wed, 2 Apr 2014 18:14:58 +0000 (11:14 -0700)
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 <jrajahalme@nicira.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
datapath/flow.c
datapath/flow.h

index 5d1d2f2..f270f3a 100644 (file)
@@ -123,8 +123,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;
@@ -134,7 +135,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
@@ -151,12 +152,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);
index 5587577..5043a6e 100644 (file)
@@ -182,10 +182,10 @@ struct arp_eth_header {
        unsigned char       ar_tip[4];          /* target IP address        */
 } __packed;
 
-void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb);
-void ovs_flow_stats_get(struct sw_flow *flow, struct ovs_flow_stats *stats,
+void ovs_flow_stats_update(struct sw_flow *, struct sk_buff *);
+void ovs_flow_stats_get(const struct sw_flow *, struct ovs_flow_stats *,
                        unsigned long *used, __be16 *tcp_flags);
-void ovs_flow_stats_clear(struct sw_flow *flow);
+void ovs_flow_stats_clear(struct sw_flow *);
 u64 ovs_flow_used_time(unsigned long flow_jiffies);
 
 int ovs_flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *);