Fix "waiting for of0 to become free" message on deldp.
authorBen Pfaff <blp@nicira.com>
Thu, 5 Jun 2008 20:38:03 +0000 (13:38 -0700)
committerBen Pfaff <blp@nicira.com>
Thu, 5 Jun 2008 20:38:09 +0000 (13:38 -0700)
Thanks to Murphy for help debugging this.

datapath/datapath.c
datapath/forward.c
datapath/forward.h

index ed9c557c6381f4c3b97f289ff36b1965c8eac664..20d41cf9597384ae546f364f6335b8d9c69c179c 100644 (file)
@@ -415,6 +415,11 @@ static void del_dp(struct datapath *dp)
                del_switch_port(p);
        rcu_assign_pointer(dps[dp->dp_idx], NULL);
 
+       /* Kill off local_port dev references from buffered packets that have
+        * associated dst entries. */
+       synchronize_rcu();
+       fwd_discard_all();
+
        /* Destroy dp->netdev.  (Must follow deleting switch ports since
         * dp->local_port has a reference to it.) */
        dp_dev_destroy(dp);
index 2c5410eaddc4a7ea8d5e42e6b9f3debbf772d0a7..4496720326b8792636a0bca95a3a1a97f87964f7 100644 (file)
@@ -556,6 +556,19 @@ static struct sk_buff *retrieve_skb(uint32_t id)
        return skb;
 }
 
+void fwd_discard_all(void) 
+{
+       unsigned long int flags;
+       int i;
+
+       spin_lock_irqsave(&buffer_lock, flags);
+       for (i = 0; i < N_PKT_BUFFERS; i++) {
+               kfree_skb(buffers[i].skb);
+               buffers[i].skb = NULL;
+       }
+       spin_unlock_irqrestore(&buffer_lock, flags);
+}
+
 static void discard_skb(uint32_t id)
 {
        unsigned long int flags;
@@ -572,10 +585,7 @@ static void discard_skb(uint32_t id)
 
 void fwd_exit(void)
 {
-       int i;
-
-       for (i = 0; i < N_PKT_BUFFERS; i++)
-               kfree_skb(buffers[i].skb);
+       fwd_discard_all();
 }
 
 /* Utility functions. */
index ce4d3b145f5e6a041fcb6f6822157609e4d83a9f..05e5ac98adaf3ec55bf590f4cc550b9608df0c10 100644 (file)
@@ -27,6 +27,7 @@ int fwd_control_input(struct sw_chain *, const struct sender *,
                      const void *, size_t);
 
 uint32_t fwd_save_skb(struct sk_buff *skb);
+void fwd_discard_all(void);
 
 void fwd_exit(void);