aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoug Ledford <dledford@redhat.com>2014-12-10 11:47:01 -0500
committerRoland Dreier <roland@purestorage.com>2014-12-15 21:11:14 -0500
commite5d1dcf1b0951f4ba00d93653942dda6196109d8 (patch)
treec3bdcd7ee0365915e15b25525a839c82b33c47db
parent016d9fb25cd9817ea9c723f4f7ecd978636b4489 (diff)
IPoIB: fix mcast_dev_flush/mcast_restart_task race
Our mcast_dev_flush routine and our mcast_restart_task can race against each other. In particular, they both hold the priv->lock while manipulating the rbtree and while removing mcast entries from the multicast_list and while adding entries to the remove_list, but they also both drop their locks prior to doing the actual removes. The mcast_dev_flush routine is run entirely under the rtnl lock and so has at least some locking. The actual race condition is like this: Thread 1 Thread 2 ifconfig ib0 up start multicast join for broadcast multicast join completes for broadcast start to add more multicast joins call mcast_restart_task to add new entries ifconfig ib0 down mcast_dev_flush mcast_leave(mcast A) mcast_leave(mcast A) As mcast_leave calls ib_sa_multicast_leave, and as member in core/multicast.c is ref counted, we run into an unbalanced refcount issue. To avoid stomping on each others removes, take the rtnl lock specifically when we are deleting the entries from the remove list. Signed-off-by: Doug Ledford <dledford@redhat.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c37
1 files changed, 32 insertions, 5 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index a52c9f3f7e42..41325960e4e0 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -802,7 +802,10 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
802 802
803 spin_unlock_irqrestore(&priv->lock, flags); 803 spin_unlock_irqrestore(&priv->lock, flags);
804 804
805 /* seperate between the wait to the leave*/ 805 /*
806 * make sure the in-flight joins have finished before we attempt
807 * to leave
808 */
806 list_for_each_entry_safe(mcast, tmcast, &remove_list, list) 809 list_for_each_entry_safe(mcast, tmcast, &remove_list, list)
807 if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)) 810 if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
808 wait_for_completion(&mcast->done); 811 wait_for_completion(&mcast->done);
@@ -923,14 +926,38 @@ void ipoib_mcast_restart_task(struct work_struct *work)
923 netif_addr_unlock(dev); 926 netif_addr_unlock(dev);
924 local_irq_restore(flags); 927 local_irq_restore(flags);
925 928
926 /* We have to cancel outside of the spinlock */ 929 /*
930 * make sure the in-flight joins have finished before we attempt
931 * to leave
932 */
933 list_for_each_entry_safe(mcast, tmcast, &remove_list, list)
934 if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
935 wait_for_completion(&mcast->done);
936
937 /*
938 * We have to cancel outside of the spinlock, but we have to
939 * take the rtnl lock or else we race with the removal of
940 * entries from the remove list in mcast_dev_flush as part
941 * of ipoib_stop() which will call mcast_stop_thread with
942 * flush == 1 while holding the rtnl lock, and the
943 * flush_workqueue won't complete until this restart_mcast_task
944 * completes. So do like the carrier on task and attempt to
945 * take the rtnl lock, but if we can't before the ADMIN_UP flag
946 * goes away, then just return and know that the remove list will
947 * get flushed later by mcast_dev_flush.
948 */
949 while (!rtnl_trylock()) {
950 if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
951 return;
952 else
953 msleep(20);
954 }
927 list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { 955 list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
928 ipoib_mcast_leave(mcast->dev, mcast); 956 ipoib_mcast_leave(mcast->dev, mcast);
929 ipoib_mcast_free(mcast); 957 ipoib_mcast_free(mcast);
930 } 958 }
931 959 ipoib_mcast_start_thread(dev);
932 if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) 960 rtnl_unlock();
933 ipoib_mcast_start_thread(dev);
934} 961}
935 962
936#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG 963#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG