[openib-general] [PATCH] ipoib: flush task race

Michael S. Tsirkin mst at mellanox.co.il
Mon Jan 9 07:08:48 PST 2006


Fix a race in IPoIB: flush task has started runnning and the user does ifconfig
ib0 down. This results in race conditions, e.g. ipoib_mcast_stop_thread might
be waiting for the same completion in parallel on two CPUs.
Solve this by moving flush_task to ipoib_wq.

Signed-off-by: Jack Morgenstein <jackm at mellanox.co.il>
Signed-off-by: Michael S. Tsirkin <mst at mellanox.co.il>

Index: openib/drivers/infiniband/ulp/ipoib/ipoib.h
===================================================================
--- openib.orig/drivers/infiniband/ulp/ipoib/ipoib.h	2006-01-09 12:06:31.000000000 +0200
+++ openib/drivers/infiniband/ulp/ipoib/ipoib.h	2006-01-09 13:47:21.000000000 +0200
@@ -252,7 +252,7 @@ void ipoib_ib_dev_cleanup(struct net_dev
 
 int ipoib_ib_dev_open(struct net_device *dev);
 int ipoib_ib_dev_up(struct net_device *dev);
-int ipoib_ib_dev_down(struct net_device *dev);
+int ipoib_ib_dev_down(struct net_device *dev, int flush);
 int ipoib_ib_dev_stop(struct net_device *dev);
 
 int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port);
Index: openib/drivers/infiniband/ulp/ipoib/ipoib_ib.c
===================================================================
--- openib.orig/drivers/infiniband/ulp/ipoib/ipoib_ib.c	2006-01-02 11:56:50.000000000 +0200
+++ openib/drivers/infiniband/ulp/ipoib/ipoib_ib.c	2006-01-09 13:47:21.000000000 +0200
@@ -434,7 +434,7 @@ int ipoib_ib_dev_up(struct net_device *d
 	return ipoib_mcast_start_thread(dev);
 }
 
-int ipoib_ib_dev_down(struct net_device *dev)
+int ipoib_ib_dev_down(struct net_device *dev, int flush)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
@@ -449,10 +449,11 @@ int ipoib_ib_dev_down(struct net_device 
 		set_bit(IPOIB_PKEY_STOP, &priv->flags);
 		cancel_delayed_work(&priv->pkey_task);
 		up(&pkey_sem);
-		flush_workqueue(ipoib_workqueue);
+		if (flush)
+			flush_workqueue(ipoib_workqueue);
 	}
 
-	ipoib_mcast_stop_thread(dev, 1);
+	ipoib_mcast_stop_thread(dev, flush);
 
 	/*
 	 * Flush the multicast groups first so we stop any multicast joins. The
@@ -599,7 +600,7 @@ void ipoib_ib_dev_flush(void *_dev)
 
 	ipoib_dbg(priv, "flushing\n");
 
-	ipoib_ib_dev_down(dev);
+	ipoib_ib_dev_down(dev, 0);
 
 	/*
 	 * The device could have been brought down between the start and when
Index: openib/drivers/infiniband/ulp/ipoib/ipoib_main.c
===================================================================
--- openib.orig/drivers/infiniband/ulp/ipoib/ipoib_main.c	2006-01-08 11:41:20.000000000 +0200
+++ openib/drivers/infiniband/ulp/ipoib/ipoib_main.c	2006-01-09 13:47:22.000000000 +0200
@@ -133,7 +133,7 @@ static int ipoib_stop(struct net_device 
 
 	netif_stop_queue(dev);
 
-	ipoib_ib_dev_down(dev);
+	ipoib_ib_dev_down(dev, 1);
 	ipoib_ib_dev_stop(dev);
 
 	if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
Index: openib/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
===================================================================
--- openib.orig/drivers/infiniband/ulp/ipoib/ipoib_verbs.c	2005-12-22 16:52:33.000000000 +0200
+++ openib/drivers/infiniband/ulp/ipoib/ipoib_verbs.c	2006-01-09 13:47:22.000000000 +0200
@@ -255,6 +255,6 @@ void ipoib_event(struct ib_event_handler
 	    record->event == IB_EVENT_LID_CHANGE  ||
 	    record->event == IB_EVENT_SM_CHANGE) {
 		ipoib_dbg(priv, "Port active event\n");
-		schedule_work(&priv->flush_task);
+		queue_work(ipoib_workqueue, &priv->flush_task);
 	}
 }

-- 
MST



More information about the general mailing list