From: Erez Shitrit Date: Sun, 27 Jan 2013 10:03:59 +0000 (+0200) Subject: ib_ipoib: Fixing issue with delayed work running after child is killed. X-Git-Tag: v4.1.12-92~293^2~1^2~94 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=ef5ca883fe4a64f9c8e1b48f7dee137f0bc1a7c7;p=users%2Fjedix%2Flinux-maple.git 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 --- diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 920bf1cab54e4..0e202d29606d0 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);