From ef5ca883fe4a64f9c8e1b48f7dee137f0bc1a7c7 Mon Sep 17 00:00:00 2001 From: Erez Shitrit Date: Sun, 27 Jan 2013 12:03:59 +0200 Subject: [PATCH] ib_ipoib: Fixing issue with delayed work running after child is killed. This patch addresses a common issues in the ipoib driver. it has the following form: Flow 1: 1) if (!test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags)) 2) queue_delayed_work(ipoib_workqueue, &priv->neigh_reap_task, arp_tbl.gc_interval); Flow 2: 3) set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); 4) cancel_delayed_work(&priv->neigh_reap_task); The Linux Kernel (Unlike the ESX Kernel ) is preemptable, which means that the this sequence of actions is feasible. 1 flow 1 3 flow 2 4 flow 2 2 flow 1 Now the effect of this sequence is that line #4 has no defacto effect. The work will be rescheduled and will run once again and only then will see that the bit value has changed. In the IPoIB driver this is benign because after each "set and cancel" sequence, flush is called which waits until the second run ends. This is not the case with the neigh_reap_task which does cancel without flush. took from 1.5.3 : b7abd8b0b071f0422b0c1018804033ee1b542eca by Alex Markuze Signed-off-by: Erez Shitrit (Ported from Mellanox OFED 2.4) Signed-off-by: Mukesh Kacker --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 920bf1cab54e..0e202d29606d 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1271,7 +1271,7 @@ static void ipoib_neigh_hash_uninit(struct net_device *dev) /* Stop GC if called at init fail need to cancel work */ stopped = test_and_set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags); if (!stopped) - cancel_delayed_work(&priv->neigh_reap_task); + cancel_delayed_work_sync(&priv->neigh_reap_task); ipoib_flush_neighs(priv); -- 2.50.1