mark_lock_irq() is going to deal with lock usages that gather multiple softirq vectors at once. Therefore the validation through check_usage_backwards() and check_usage_forwards() will need to handle expanded usage masks.
So enhance those functions to that purpose. Reviewed-by: David S. Miller <[email protected]> Signed-off-by: Frederic Weisbecker <[email protected]> Cc: Mauro Carvalho Chehab <[email protected]> Cc: Joel Fernandes <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Pavan Kondeti <[email protected]> Cc: Paul E . McKenney <[email protected]> Cc: David S . Miller <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Sebastian Andrzej Siewior <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> --- kernel/locking/lockdep.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 2321b5e16cdf..d1bfe5eff708 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -2662,9 +2662,12 @@ print_irq_inversion_bug(struct task_struct *curr, */ static int check_usage_forwards(struct task_struct *curr, struct held_lock *this, - u64 usage_mask, const char *irqclass) + u64 usage_mask, bool read) { int ret; + u64 intersec; + int intersec_bit; + const char *irqclass; struct lock_list root; struct lock_list *uninitialized_var(target_entry); @@ -2676,8 +2679,14 @@ check_usage_forwards(struct task_struct *curr, struct held_lock *this, if (ret == 1) return ret; + intersec = usage_mask & target_entry->class->usage_mask; + intersec_bit = __ffs64(intersec); + if (read) + intersec_bit += LOCK_USAGE_READ_MASK; + irqclass = state_name(intersec_bit); + return print_irq_inversion_bug(curr, &root, target_entry, - this, 1, irqclass); + this, 1, irqclass); } /* @@ -2686,9 +2695,12 @@ check_usage_forwards(struct task_struct *curr, struct held_lock *this, */ static int check_usage_backwards(struct task_struct *curr, struct held_lock *this, - u64 usage_mask, const char *irqclass) + u64 usage_mask, bool read) { int ret; + u64 intersec; + int intersec_bit; + const char *irqclass; struct lock_list root; struct lock_list *uninitialized_var(target_entry); @@ -2700,6 +2712,12 @@ check_usage_backwards(struct task_struct *curr, struct held_lock *this, if (ret == 1) return ret; + intersec = usage_mask & target_entry->class->usage_mask; + intersec_bit = __ffs64(intersec); + if (read) + intersec_bit += LOCK_USAGE_READ_MASK; + irqclass = state_name(intersec_bit); + return print_irq_inversion_bug(curr, &root, target_entry, this, 0, irqclass); } @@ -2753,7 +2771,7 @@ static inline int state_verbose(enum lock_usage_bit bit, } typedef int (*check_usage_f)(struct task_struct *, struct held_lock *, - u64 usage_mask, const char *name); + u64 usage_mask, bool read); static int mark_lock_irq(struct task_struct *curr, struct held_lock *this, @@ -2789,7 +2807,7 @@ mark_lock_irq(struct task_struct *curr, struct held_lock *this, * states. */ if ((!read || !dir || STRICT_READ_CHECKS) && - !usage(curr, this, lock_usage_mask(&excl_usage), state_name(new_usage->bit & ~LOCK_USAGE_READ_MASK))) + !usage(curr, this, lock_usage_mask(&excl_usage), false)) return 0; /* @@ -2803,7 +2821,7 @@ mark_lock_irq(struct task_struct *curr, struct held_lock *this, if (STRICT_READ_CHECKS && !usage(curr, this, lock_usage_mask(&excl_usage), - state_name(new_usage->bit + LOCK_USAGE_READ_MASK))) + true)) return 0; } -- 2.21.0

