[openib-general] [PATCH] ipoib: stop_thread/join_complete race condition fix
Michael S. Tsirkin
mst at mellanox.co.il
Mon Jan 9 07:17:11 PST 2006
IPoIB is open to the following race: ipoib_mcast_join_complete
sets mcast->query to NULL, ipoib_mcast_stop_thread
tests query, and sees that it is NULL. We then destroy the mcast group.
ipoib_mcast_join_complete then calls complete on a non-existing group.
Signed-off-by: Michael S. Tsirkin <mst at mellanox.co.il>
Index: openib/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
===================================================================
--- openib/drivers/infiniband/ulp/ipoib/ipoib_multicast.c (revision 4743)
+++ openib/drivers/infiniband/ulp/ipoib/ipoib_multicast.c (working copy)
@@ -413,9 +413,11 @@ static void ipoib_mcast_join_complete(in
if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;
+ down(&mcast_mutex);
+
+ spin_lock_irq(&priv->lock);
mcast->query = NULL;
- down(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) {
if (status == -ETIMEDOUT)
queue_work(ipoib_workqueue, &priv->mcast_task);
@@ -424,6 +426,7 @@ static void ipoib_mcast_join_complete(in
mcast->backoff * HZ);
} else
complete(&mcast->done);
+ spin_unlock_irq(&priv->lock);
up(&mcast_mutex);
return;
@@ -600,21 +603,27 @@ int ipoib_mcast_stop_thread(struct net_d
if (flush)
flush_workqueue(ipoib_workqueue);
+ spin_lock_irq(&priv->lock);
if (priv->broadcast && priv->broadcast->query) {
ib_sa_cancel_query(priv->broadcast->query_id, priv->broadcast->query);
priv->broadcast->query = NULL;
+ spin_unlock_irq(&priv->lock);
ipoib_dbg_mcast(priv, "waiting for bcast\n");
wait_for_completion(&priv->broadcast->done);
- }
+ } else
+ spin_unlock_irq(&priv->lock);
list_for_each_entry(mcast, &priv->multicast_list, list) {
+ spin_lock_irq(&priv->lock);
if (mcast->query) {
ib_sa_cancel_query(mcast->query_id, mcast->query);
mcast->query = NULL;
+ spin_unlock_irq(&priv->lock);
ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n",
IPOIB_GID_ARG(mcast->mcmember.mgid));
wait_for_completion(&mcast->done);
- }
+ } else
+ spin_unlock_irq(&priv->lock);
}
return 0;
--
MST
More information about the general
mailing list