From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754111AbbDOOPA (ORCPT ); Wed, 15 Apr 2015 10:15:00 -0400 Received: from bombadil.infradead.org ([198.137.202.9]:59151 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753661AbbDOOOw (ORCPT ); Wed, 15 Apr 2015 10:14:52 -0400 Date: Wed, 15 Apr 2015 16:14:40 +0200 From: Peter Zijlstra To: Sebastian Andrzej Siewior Cc: linux-kernel@vger.kernel.org, Ingo Molnar Subject: Re: [PATCH] lockdep: make print_lock_name() robust against non-existing lock_class Message-ID: <20150415141440.GQ23123@twins.programming.kicks-ass.net> References: <1429104276-22412-1-git-send-email-bigeasy@linutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1429104276-22412-1-git-send-email-bigeasy@linutronix.de> User-Agent: Mutt/1.5.21 (2012-12-30) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, Apr 15, 2015 at 03:24:36PM +0200, Sebastian Andrzej Siewior wrote: > During sysrq's show-held-locks command it is possible that hlock_class() > returns NULL for a given lock. The result is then (after the warning): > > |BUG: unable to handle kernel NULL pointer dereference at 0000001c > |IP: [] get_usage_chars+0x5/0x100 > |Call Trace: > | [] print_lock_name+0x23/0x60 > | [] print_lock+0x5d/0x7e > | [] lockdep_print_held_locks+0x74/0xe0 > | [] debug_show_all_locks+0x132/0x1b0 > | [] sysrq_handle_showlocks+0x8/0x10 > > This *might* happen because the thread on the other CPU drops the lock > after we are looking ->lockdep_depth and ->held_locks points no longer > to a lock that is held. > The fix here is to simply ignore it and continue. Hmm, but in that case we might equally run into the hlock_class() debug check which would kill all of lockdep. Note that lock_release_nested() with CONFIG_DEBUG_LOCKDEP will actually clear those fields. Would something like the below work for you? --- kernel/locking/lockdep.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index ba77ab5f64dd..0ef89f830ff4 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -551,7 +551,18 @@ static void print_lockdep_cache(struct lockdep_map *lock) static void print_lock(struct held_lock *hlock) { - print_lock_name(hlock_class(hlock)); + /* + * We can be called locklessly through debug_show_all_locks() so be + * extra careful, the hlock might have been released and cleared. + */ + unsigned int class_idx = READ_ONCE(hlock->class_idx); + + if (!class_idx || (class_idx - 1) >= MAX_LOCKDEP_KEYS) { + printk("\n"); + return; + } + + print_lock_name(lock_classes + class_idx - 1); printk(", at: "); print_ip_sym(hlock->acquire_ip); }