Re: [PATCH v3 1/8] locking/lockdep: Decrement irq context counters when removing lock chain

From: Waiman Long
Date: Thu Jan 16 2020 - 10:50:10 EST


On 1/16/20 10:32 AM, Peter Zijlstra wrote:
> On Wed, Jan 15, 2020 at 04:43:06PM -0500, Waiman Long wrote:
>> There are currently three counters to track the irq context of a lock
>> chain - nr_hardirq_chains, nr_softirq_chains and nr_process_chains.
>> They are incremented when a new lock chain is added, but they are
>> not decremented when a lock chain is removed. That causes some of the
>> statistic counts reported by /proc/lockdep_stats to be incorrect.
>>
>> Fix that by decrementing the right counter when a lock chain is removed.
>>
>> Fixes: a0b0fd53e1e6 ("locking/lockdep: Free lock classes that are no longer in use")
>> Signed-off-by: Waiman Long <longman@xxxxxxxxxx>
>> ---
>> kernel/locking/lockdep.c | 36 +++++++++++++++++++++---------
>> kernel/locking/lockdep_internals.h | 6 +++++
>> 2 files changed, 32 insertions(+), 10 deletions(-)
>>
>> diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
>> index 32282e7112d3..b20fa6236b2a 100644
>> --- a/kernel/locking/lockdep.c
>> +++ b/kernel/locking/lockdep.c
>> @@ -2299,16 +2299,24 @@ static int check_irq_usage(struct task_struct *curr, struct held_lock *prev,
>> return 0;
>> }
>>
>> -static void inc_chains(void)
>> +static void inc_chains(int irq_context)
>> {
>> - if (current->hardirq_context)
>> + if (irq_context & LOCK_CHAIN_HARDIRQ_CONTEXT)
>> nr_hardirq_chains++;
>> - else {
>> - if (current->softirq_context)
>> - nr_softirq_chains++;
>> - else
>> - nr_process_chains++;
>> - }
>> + else if (irq_context & LOCK_CHAIN_SOFTIRQ_CONTEXT)
>> + nr_softirq_chains++;
>> + else
>> + nr_process_chains++;
>> +}
>> +
>> +static void dec_chains(int irq_context)
>> +{
>> + if (irq_context & LOCK_CHAIN_HARDIRQ_CONTEXT)
>> + nr_hardirq_chains--;
>> + else if (irq_context & LOCK_CHAIN_SOFTIRQ_CONTEXT)
>> + nr_softirq_chains--;
>> + else
>> + nr_process_chains--;
>> }
>>
>> #else
>> @@ -2324,6 +2332,10 @@ static inline void inc_chains(void)
>> nr_process_chains++;
>> }
>>
>> +static void dec_chains(int irq_context)
>> +{
>> + nr_process_chains--;
>> +}
>> #endif /* CONFIG_TRACE_IRQFLAGS */
>>
> Is there really need for two versions of those functions? Would the
> @irq_context argument not always be 0 in the CONFIG_TRACE_IRQFLAGS=n
> case?
>
You are right. I changed the code so that inc_chains() won't look at
{hard|soft}irq_context directly. So I could take it out of
CONFIG_TRACE_IRQFLAGS as a single version.

I will make the change in the next version.

Cheers,
Longman