datapath: Don't expect bottom-halves to be disabled.
authorJesse Gross <jesse@nicira.com>
Wed, 12 May 2010 19:40:45 +0000 (12:40 -0700)
committerJesse Gross <jesse@nicira.com>
Fri, 14 May 2010 22:10:45 +0000 (15:10 -0700)
We currently document that BHs need to be disabled when handling
received packets.  However, this isn't actually generally the
case (usually preemption is disabled but not BHs).  Only one place
actually relies on BHs being disabled so fix that and update the
documentation of our expectations.

datapath/datapath.c
datapath/vport-gre.c
datapath/vport.c

index 9fc778b..67c422a 100644 (file)
@@ -512,11 +512,12 @@ out:
        return err;
 }
 
-/* Must be called with rcu_read_lock and with bottom-halves disabled. */
+/* Must be called with rcu_read_lock. */
 void dp_process_received_packet(struct dp_port *p, struct sk_buff *skb)
 {
        struct datapath *dp = p->dp;
        struct dp_stats_percpu *stats;
+       int stats_counter_off;
        struct odp_flow_key key;
        struct tbl_node *flow_node;
 
@@ -525,14 +526,11 @@ void dp_process_received_packet(struct dp_port *p, struct sk_buff *skb)
 
        OVS_CB(skb)->dp_port = p;
 
-       /* BHs are off so we don't have to use get_cpu()/put_cpu() here. */
-       stats = percpu_ptr(dp->stats_percpu, smp_processor_id());
-
        if (flow_extract(skb, p ? p->port_no : ODPP_NONE, &key)) {
                if (dp->drop_frags) {
                        kfree_skb(skb);
-                       stats->n_frags++;
-                       return;
+                       stats_counter_off = offsetof(struct dp_stats_percpu, n_frags);
+                       goto out;
                }
        }
 
@@ -543,11 +541,17 @@ void dp_process_received_packet(struct dp_port *p, struct sk_buff *skb)
                flow_used(flow, skb);
                execute_actions(dp, skb, &key, acts->actions, acts->n_actions,
                                GFP_ATOMIC);
-               stats->n_hit++;
+               stats_counter_off = offsetof(struct dp_stats_percpu, n_hit);
        } else {
-               stats->n_missed++;
+               stats_counter_off = offsetof(struct dp_stats_percpu, n_missed);
                dp_output_control(dp, skb, _ODPL_MISS_NR, OVS_CB(skb)->tun_id);
        }
+
+out:
+       local_bh_disable();
+       stats = per_cpu_ptr(dp->stats_percpu, smp_processor_id());
+       (*(u64 *)((u8 *)stats + stats_counter_off))++;
+       local_bh_enable();
 }
 
 #if defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID)
index 654ead0..bd6d4a3 100644 (file)
@@ -735,7 +735,7 @@ handle_csum_offload(struct sk_buff *skb)
        }
 }
 
-/* Called with rcu_read_lock and bottom-halves disabled. */
+/* Called with rcu_read_lock. */
 static void
 gre_err(struct sk_buff *skb, u32 info)
 {
@@ -847,7 +847,7 @@ out:
        skb->protocol = htons(ETH_P_IP);
 }
 
-/* Called with rcu_read_lock and bottom-halves disabled. */
+/* Called with rcu_read_lock. */
 static int
 gre_rcv(struct sk_buff *skb)
 {
index 6b7381e..cc20959 100644 (file)
@@ -1087,10 +1087,9 @@ vport_get_mtu(const struct vport *vport)
  * @vport: vport that received the packet
  * @skb: skb that was received
  *
- * Must be called with rcu_read_lock and bottom halves disabled.  The packet
- * cannot be shared and skb->data should point to the Ethernet header.  The
- * caller must have already called compute_ip_summed() to initialize the
- * checksumming fields.
+ * Must be called with rcu_read_lock.  The packet cannot be shared and
+ * skb->data should point to the Ethernet header.  The caller must have already
+ * called compute_ip_summed() to initialize the checksumming fields.
  */
 void
 vport_receive(struct vport *vport, struct sk_buff *skb)