1. 16 4月, 2015 5 次提交
    • D
      IB/ipoib: Use dedicated workqueues per interface · 0b39578b
      Doug Ledford 提交于
      During my recent work on the rtnl lock deadlock in the IPoIB driver, I
      saw that even once I fixed the apparent races for a single device, as
      soon as that device had any children, new races popped up.  It turns
      out that this is because no matter how well we protect against races
      on a single device, the fact that all devices use the same workqueue,
      and flush_workqueue() flushes *everything* from that workqueue means
      that we would also have to prevent all races between different devices
      (for instance, ipoib_mcast_restart_task on interface ib0 can race with
      ipoib_mcast_flush_dev on interface ib0.8002, resulting in a deadlock on
      the rtnl_lock).
      
      There are several possible solutions to this problem:
      
      Make carrier_on_task and mcast_restart_task try to take the rtnl for
      some set period of time and if they fail, then bail.  This runs the
      real risk of dropping work on the floor, which can end up being its
      own separate kind of deadlock.
      
      Set some global flag in the driver that says some device is in the
      middle of going down, letting all tasks know to bail.  Again, this can
      drop work on the floor.
      
      Or the method this patch attempts to use, which is when we bring an
      interface up, create a workqueue specifically for that interface, so
      that when we take it back down, we are flushing only those tasks
      associated with our interface.  In addition, keep the global
      workqueue, but now limit it to only flush tasks.  In this way, the
      flush tasks can always flush the device specific work queues without
      having deadlock issues.
      Signed-off-by: NDoug Ledford <dledford@redhat.com>
      0b39578b
    • D
      IB/ipoib: Make the carrier_on_task race aware · 894021a7
      Doug Ledford 提交于
      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: NDoug Ledford <dledford@redhat.com>
      894021a7
    • D
      IB/ipoib: Consolidate rtnl_lock tasks in workqueue · c84ca6d2
      Doug Ledford 提交于
      The ipoib_mcast_flush_dev routine is called with the rtnl_lock held and
      needs to keep it held.  It also needs to call flush_workqueue() to flush
      out any outstanding work.  In the past, we've had to try and make sure
      that we didn't flush out any outstanding join completions because they
      also wanted to grab rtnl_lock() and that would deadlock.  It turns out
      that the only thing in the join completion handler that needs this lock
      can be safely moved to our carrier_on_task, thereby reducing the
      potential for the join completion code and the flush code to deadlock
      against each other.
      Signed-off-by: NDoug Ledford <dledford@redhat.com>
      c84ca6d2
    • D
      IB/ipoib: change init sequence ordering · be7aa663
      Doug Ledford 提交于
      In preparation for using per device work queues, we need to move the
      start of the neighbor thread task to after ipoib_ib_dev_init and move
      the destruction of the neighbor task to before ipoib_ib_dev_cleanup.
      Otherwise we will end up freeing our workqueue with work possibly
      still on it.
      Signed-off-by: NDoug Ledford <dledford@redhat.com>
      be7aa663
    • D
      IB/ipoib: factor out ah flushing · e135106f
      Doug Ledford 提交于
      Create a an ipoib_flush_ah and ipoib_stop_ah routines to use at
      appropriate times to flush out all remaining ah entries before we shut
      the device down.
      
      Because neighbors and mcast entries can each have a reference on any
      given ah, we must make sure to free all of those first before our ah
      will actually have a 0 refcount and be able to be reaped.
      
      This factoring is needed in preparation for having per-device work
      queues.  The original per-device workqueue code resulted in the following
      error message:
      
      <ibdev>: ib_dealloc_pd failed
      
      That error was tracked down to this issue.  With the changes to which
      workqueues were flushed when, there were no flushes of the per device
      workqueue after the last ah's were freed, resulting in an attempt to
      dealloc the pd with outstanding resources still allocated.  This code
      puts the explicit flushes in the needed places to avoid that problem.
      Signed-off-by: NDoug Ledford <dledford@redhat.com>
      e135106f
  2. 15 4月, 2015 35 次提交