datapath: Fix recv path for CONFIG_PREEMPT_RCU.
authorPravin B Shelar <pshelar@nicira.com>
Fri, 7 Oct 2011 02:45:09 +0000 (19:45 -0700)
committerPravin B Shelar <pshelar@nicira.com>
Fri, 7 Oct 2011 02:45:09 +0000 (19:45 -0700)
        In case CONFIG_PREEMPT_RCU, rcu grace period waits only for RCU
read-side critical sections that are delimited by rcu_read_lock() and
rcu_read_unlock(). internal_dev_xmit() is called in
rcu_read_lock_bh context. Therefore we need to explicitly take rcu
lock to prevent race with call_rcu() in PREEMPT_RCU case.

Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
datapath/vport-internal_dev.c

index ecfb37933cf4a8a3c86d468c0304cf509ec865d7..1c6897f4f1f0a0d3be2483287ae09dbf29199a33 100644 (file)
@@ -68,7 +68,7 @@ static int internal_dev_mac_addr(struct net_device *dev, void *p)
        return 0;
 }
 
-/* Called with rcu_read_lock and bottom-halves disabled. */
+/* Called with rcu_read_lock_bh. */
 static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
        if (unlikely(compute_ip_summed(skb, true))) {
@@ -79,7 +79,9 @@ static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
        vlan_copy_skb_tci(skb);
        OVS_CB(skb)->flow = NULL;
 
+       rcu_read_lock();
        vport_receive(internal_dev_priv(netdev)->vport, skb);
+       rcu_read_unlock();
        return 0;
 }