IB/ipoib: For sendonly join free the multicast group on leave
authorChristoph Lameter <cl@linux.com>
Sun, 11 Oct 2015 23:49:42 +0000 (18:49 -0500)
committerDoug Ledford <dledford@redhat.com>
Tue, 13 Oct 2015 20:43:59 +0000 (16:43 -0400)
When we leave the multicast group on expiration of a neighbor we
do not free the mcast structure. This results in a memory leak
that causes ib_dealloc_pd to fail and print a WARN_ON message
and backtrace.

Fixes: bd99b2e05c4d (IB/ipoib: Expire sendonly multicast joins)
Signed-off-by: Christoph Lameter <cl@linux.com>
Tested-by: Sagi Grimberg <sagig@mellanox.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c

index 4cd5428a2399a2cc73757c49382842094714d1bc..edc5b8565d6d9eb5ba6e22e1baefd21d53986b5f 100644 (file)
@@ -495,6 +495,7 @@ void ipoib_dev_cleanup(struct net_device *dev);
 void ipoib_mcast_join_task(struct work_struct *work);
 void ipoib_mcast_carrier_on_task(struct work_struct *work);
 void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb);
+void ipoib_mcast_free(struct ipoib_mcast *mc);
 
 void ipoib_mcast_restart_task(struct work_struct *work);
 int ipoib_mcast_start_thread(struct net_device *dev);
index f74316e679d2fc2b7b27212d47fc806e95844f01..babba05d7a0eb707f472d7de3cb06843a0844eff 100644 (file)
@@ -1207,8 +1207,10 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv)
 
 out_unlock:
        spin_unlock_irqrestore(&priv->lock, flags);
-       list_for_each_entry_safe(mcast, tmcast, &remove_list, list)
+       list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
                ipoib_mcast_leave(dev, mcast);
+               ipoib_mcast_free(mcast);
+       }
 }
 
 static void ipoib_reap_neigh(struct work_struct *work)
index 136cbefe00f87aeb79b02d6508d42fdac5741069..d750a86042f3d8da0736c23a52f41737b329c37d 100644 (file)
@@ -106,7 +106,7 @@ static void __ipoib_mcast_schedule_join_thread(struct ipoib_dev_priv *priv,
                queue_delayed_work(priv->wq, &priv->mcast_task, 0);
 }
 
-static void ipoib_mcast_free(struct ipoib_mcast *mcast)
+void ipoib_mcast_free(struct ipoib_mcast *mcast)
 {
        struct net_device *dev = mcast->dev;
        int tx_dropped = 0;