locking/lockdep: Fix "USED" <- "IN-NMI" inversions
authorpeterz@infradead.org <peterz@infradead.org>
Wed, 2 Sep 2020 16:03:23 +0000 (18:03 +0200)
committerIngo Molnar <mingo@kernel.org>
Thu, 3 Sep 2020 09:19:42 +0000 (11:19 +0200)
commit23870f1227680d2aacff6f79c3ab2222bd04e86e
tree46cfafbbcc57f372200072c6784d91145c6b6984
parentfc3abb53250a90ba2150eebd182137c136f4d25a
locking/lockdep: Fix "USED" <- "IN-NMI" inversions

During the LPC RCU BoF Paul asked how come the "USED" <- "IN-NMI"
detector doesn't trip over rcu_read_lock()'s lockdep annotation.

Looking into this I found a very embarrasing typo in
verify_lock_unused():

- if (!(class->usage_mask & LOCK_USED))
+ if (!(class->usage_mask & LOCKF_USED))

fixing that will indeed cause rcu_read_lock() to insta-splat :/

The above typo means that instead of testing for: 0x100 (1 <<
LOCK_USED), we test for 8 (LOCK_USED), which corresponds to (1 <<
LOCK_ENABLED_HARDIRQ).

So instead of testing for _any_ used lock, it will only match any lock
used with interrupts enabled.

The rcu_read_lock() annotation uses .check=0, which means it will not
set any of the interrupt bits and will thus never match.

In order to properly fix the situation and allow rcu_read_lock() to
correctly work, split LOCK_USED into LOCK_USED and LOCK_USED_READ and by
having .read users set USED_READ and test USED, pure read-recursive
locks are permitted.

Fixes: f6f48e180404 ("lockdep: Teach lockdep about "USED" <- "IN-NMI" inversions")
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Tested-by: Masami Hiramatsu <mhiramat@kernel.org>
Acked-by: Paul E. McKenney <paulmck@kernel.org>
Link: https://lore.kernel.org/r/20200902160323.GK1362448@hirez.programming.kicks-ass.net
kernel/locking/lockdep.c
kernel/locking/lockdep_internals.h