aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoug Ledford <dledford@redhat.com>2015-02-21 19:27:02 -0500
committerDoug Ledford <dledford@redhat.com>2015-04-15 16:06:17 -0400
commit894021a752912ef4c2b63c8d2c466c00bc3cd2e6 (patch)
tree1a7f18553a536407c558a61c038055a2acb3ffb4
parentc84ca6d2b1a1bfbdab2dd2bc243840e9589a5aaf (diff)
IB/ipoib: Make the carrier_on_task race aware
We blindly assume that we can just take the rtnl lock and that will prevent races with downing this interface. Unfortunately, that's not the case. In ipoib_mcast_stop_thread() we will call flush_workqueue() in an attempt to clear out all remaining instances of ipoib_join_task. But, since this task is put on the same workqueue as the join task, the flush_workqueue waits on this thread too. But this thread is deadlocked on the rtnl lock. The better thing here is to use trylock and loop on that until we either get the lock or we see that FLAG_OPER_UP has been cleared, in which case we don't need to do anything anyway and we just return. While investigating which flag should be used, FLAG_ADMIN_UP or FLAG_OPER_UP, it was determined that FLAG_OPER_UP was the more appropriate flag to use. However, there was a mix of these two flags in use in the existing code. So while we check for that flag here as part of this race fix, also cleanup the two places that had used the less appropriate flag for their tests. Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index eee66d13e5b9..c63a598d0b41 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -353,18 +353,27 @@ void ipoib_mcast_carrier_on_task(struct work_struct *work)
353 carrier_on_task); 353 carrier_on_task);
354 struct ib_port_attr attr; 354 struct ib_port_attr attr;
355 355
356 /*
357 * Take rtnl_lock to avoid racing with ipoib_stop() and
358 * turning the carrier back on while a device is being
359 * removed.
360 */
361 if (ib_query_port(priv->ca, priv->port, &attr) || 356 if (ib_query_port(priv->ca, priv->port, &attr) ||
362 attr.state != IB_PORT_ACTIVE) { 357 attr.state != IB_PORT_ACTIVE) {
363 ipoib_dbg(priv, "Keeping carrier off until IB port is active\n"); 358 ipoib_dbg(priv, "Keeping carrier off until IB port is active\n");
364 return; 359 return;
365 } 360 }
366 361
367 rtnl_lock(); 362 /*
363 * Take rtnl_lock to avoid racing with ipoib_stop() and
364 * turning the carrier back on while a device is being
365 * removed. However, ipoib_stop() will attempt to flush
366 * the workqueue while holding the rtnl lock, so loop
367 * on trylock until either we get the lock or we see
368 * FLAG_OPER_UP go away as that signals that we are bailing
369 * and can safely ignore the carrier on work.
370 */
371 while (!rtnl_trylock()) {
372 if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
373 return;
374 else
375 msleep(20);
376 }
368 if (!ipoib_cm_admin_enabled(priv->dev)) 377 if (!ipoib_cm_admin_enabled(priv->dev))
369 dev_set_mtu(priv->dev, min(priv->mcast_mtu, priv->admin_mtu)); 378 dev_set_mtu(priv->dev, min(priv->mcast_mtu, priv->admin_mtu));
370 netif_carrier_on(priv->dev); 379 netif_carrier_on(priv->dev);
@@ -535,7 +544,7 @@ void ipoib_mcast_join_task(struct work_struct *work)
535 if (!priv->broadcast) { 544 if (!priv->broadcast) {
536 struct ipoib_mcast *broadcast; 545 struct ipoib_mcast *broadcast;
537 546
538 if (!test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) 547 if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
539 return; 548 return;
540 549
541 broadcast = ipoib_mcast_alloc(dev, 1); 550 broadcast = ipoib_mcast_alloc(dev, 1);
@@ -882,7 +891,7 @@ void ipoib_mcast_restart_task(struct work_struct *work)
882 ipoib_mcast_free(mcast); 891 ipoib_mcast_free(mcast);
883 } 892 }
884 893
885 if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) 894 if (test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
886 ipoib_mcast_start_thread(dev); 895 ipoib_mcast_start_thread(dev);
887} 896}
888 897