]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ib_ipoib: Fixing issue with delayed work running after child is killed.
authorErez Shitrit <erezsh@mellanox.com>
Sun, 27 Jan 2013 10:03:59 +0000 (12:03 +0200)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Tue, 7 Jul 2015 21:45:07 +0000 (14:45 -0700)
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 <erezsh@mellanox.com>
(Ported from Mellanox OFED 2.4)

Signed-off-by: Mukesh Kacker <mukesh.kacker@oracle.com>
drivers/infiniband/ulp/ipoib/ipoib_main.c

index 920bf1cab54e4239842c361c23846d0c7bd1e0f4..0e202d29606d0aea76757d954efc223359c74a0a 100644 (file)
@@ -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);