workqueue/lockdep: 'Fix' flush_work() annotation
authorPeter Zijlstra <peterz@infradead.org>
Wed, 23 Aug 2017 10:52:32 +0000 (12:52 +0200)
committerIngo Molnar <mingo@kernel.org>
Fri, 25 Aug 2017 09:06:32 +0000 (11:06 +0200)
commita1d14934ea4b9db816a8dbfeab1c3e7204a0d871
treef2d6a33fdf8eed83fbe4e2d04c7989700aab2138
parente91498589746065e3ae95d9a00b068e525eec34f
workqueue/lockdep: 'Fix' flush_work() annotation

The flush_work() annotation as introduced by commit:

  e159489baa71 ("workqueue: relax lockdep annotation on flush_work()")

hits on the lockdep problem with recursive read locks.

The situation as described is:

Work W1:                Work W2:        Task:

ARR(Q)                  ARR(Q) flush_workqueue(Q)
A(W1)                   A(W2)             A(Q)
  flush_work(W2)   R(Q)
    A(W2)
    R(W2)
    if (special)
      A(Q)
    else
      ARR(Q)
    R(Q)

where: A - acquire, ARR - acquire-read-recursive, R - release.

Where under 'special' conditions we want to trigger a lock recursion
deadlock, but otherwise allow the flush_work(). The allowing is done
by using recursive read locks (ARR), but lockdep is broken for
recursive stuff.

However, there appears to be no need to acquire the lock if we're not
'special', so if we remove the 'else' clause things become much
simpler and no longer need the recursion thing at all.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Tejun Heo <tj@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: boqun.feng@gmail.com
Cc: byungchul.park@lge.com
Cc: david@fromorbit.com
Cc: johannes@sipsolutions.net
Cc: oleg@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
kernel/workqueue.c