datapath: Disable bottom-halves where necessary.
authorJesse Gross <jesse@nicira.com>
Wed, 12 May 2010 18:40:58 +0000 (11:40 -0700)
committerJesse Gross <jesse@nicira.com>
Fri, 14 May 2010 22:10:45 +0000 (15:10 -0700)
Places that update per-cpu stats without locking need to have bottom
halves disabled.  Otherwise we can be running in process context and
in the middle of an operation and be interrupted by a softirq.

datapath/datapath.c
datapath/vport-internal_dev.c

index 165f0a9..9fc778b 100644 (file)
@@ -830,9 +830,10 @@ dp_output_control(struct datapath *dp, struct sk_buff *skb, int queue_no,
 err_kfree_skb:
        kfree_skb(skb);
 err:
-       stats = percpu_ptr(dp->stats_percpu, get_cpu());
+       local_bh_disable();
+       stats = per_cpu_ptr(dp->stats_percpu, smp_processor_id());
        stats->n_lost++;
-       put_cpu();
+       local_bh_enable();
 
        return err;
 }
index d23b4c3..88d3444 100644 (file)
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/percpu.h>
-#include <linux/preempt.h>
 #include <linux/rcupdate.h>
 #include <linux/skbuff.h>
-#include <linux/workqueue.h>
 
 #include "datapath.h"
 #include "openvswitch/internal_dev.h"
@@ -81,8 +79,7 @@ static int internal_dev_mac_addr(struct net_device *dev, void *p)
        return 0;
 }
 
-/* Not reentrant (because it is called with BHs disabled), but may be called
- * simultaneously on different CPUs. */
+/* Called with rcu_read_lock and bottom-halves disabled. */
 static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
        struct internal_dev *internal_dev = internal_dev_priv(netdev);
@@ -101,9 +98,7 @@ static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
        skb_reset_mac_header(skb);
        compute_ip_summed(skb, true);
 
-       rcu_read_lock_bh();
        vport_receive(vport, skb);
-       rcu_read_unlock_bh();
 
        return 0;
 }
@@ -340,11 +335,11 @@ internal_dev_recv(struct vport *vport, struct sk_buff *skb)
                netif_rx_ni(skb);
        netdev->last_rx = jiffies;
 
-       preempt_disable();
+       local_bh_disable();
        lb_stats = per_cpu_ptr(internal_dev->lstats, smp_processor_id());
        lb_stats->rx_packets++;
        lb_stats->rx_bytes += len;
-       preempt_enable();
+       local_bh_enable();
 
        return len;
 }