Message ID | 20230927160231.XRCDDSK4@linutronix.de |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:cae8:0:b0:403:3b70:6f57 with SMTP id r8csp3056091vqu; Wed, 27 Sep 2023 20:58:32 -0700 (PDT) X-Google-Smtp-Source: AGHT+IErgTgvsbtbK95TkbXszvGKePjL662yVRvGTC1jkcKiyreTkeuxw/VTxSxLAWgwqUH4cvBT X-Received: by 2002:a05:6a20:1607:b0:15d:b407:b0a0 with SMTP id l7-20020a056a20160700b0015db407b0a0mr138844pzj.26.1695873511992; Wed, 27 Sep 2023 20:58:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695873511; cv=none; d=google.com; s=arc-20160816; b=G12nmk07rUIqeJW3wSz0s5onMKMYHvGtSLWCBI30yI4DrEQnuyV2NI29HINU1fIG+6 mNhI7V/eVuqWCxNhKzLkcFizUuXTBTnWYZWxgK1KD/8ONU9ULehfEQHth9dHZVmgOobg c31lOFaUFmdm5LUGJQnsHHgTiUW8iJZUO4hDkekqj7Ygukn2w/RdySvzSv9z5vMtoAqZ tcH8WR7jUGXshZHU+yhkqMTc2NCdMnDJP60njI4nKYMRW+7C5nWWxzNpL3ag1Xv3s5Fp +35Eq87sLBdXN8tE8w7CG4K1Nf82u5JAO4siLaHL3AM0v3LYR60+TH/8U5WVXHMimhHF yapA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:content-disposition :mime-version:message-id:subject:cc:to:from:dkim-signature :dkim-signature:date; bh=EdCiO/WzKECbYs7KtcCYhKCOSLS8gRQvCAW/vFRb9F4=; fh=CvjwasYIGIUnqmxBvRAiLCy1NXiZncROBTI+6xPTls0=; b=HeuoKUNvtp9zEtGoRRKK+vFVC0636WzkKHTFg5sG/CDJTtZFfxb10CciCxoykGRZ6+ aRR/Jf7X+JwfZjIh4RYzCBnYsSMXGnbQyVm56OSiduca1NbwJMBcD2xcqv5odKNyg9KR 2x811pQXhQZX+1VVdiqM/h8kFLg2u/8tRJHpF5qCjyA0JnwdSF+IRrCWHbfzMuI3ZuqT CF4HkBrV6L+zybKs4Yx81j4qNbGooXGG5gBMFQ/nnfs+iaAfFcIjh3S33C2B1HS3qvaQ JYQJ1UYmgVXmDx5/WtJBOrsCUn8swIluBU1b7/bz8ZilnX1auFaZA3ab6RWY0nqZXX3X RjZQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b="gA8E7/z/"; dkim=neutral (no key) header.i=@linutronix.de; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: from snail.vger.email (snail.vger.email. [2620:137:e000::3:7]) by mx.google.com with ESMTPS id k8-20020a056a00134800b00690c1a57210si18363470pfu.115.2023.09.27.20.58.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 27 Sep 2023 20:58:31 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) client-ip=2620:137:e000::3:7; Authentication-Results: mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b="gA8E7/z/"; dkim=neutral (no key) header.i=@linutronix.de; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:7 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by snail.vger.email (Postfix) with ESMTP id 438A9821A175; Wed, 27 Sep 2023 09:03:29 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at snail.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232186AbjI0QD0 (ORCPT <rfc822;ruipengqi7@gmail.com> + 19 others); Wed, 27 Sep 2023 12:03:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55466 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232838AbjI0QDM (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Wed, 27 Sep 2023 12:03:12 -0400 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 70B7C121; Wed, 27 Sep 2023 09:02:35 -0700 (PDT) Date: Wed, 27 Sep 2023 18:02:31 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1695830553; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=EdCiO/WzKECbYs7KtcCYhKCOSLS8gRQvCAW/vFRb9F4=; b=gA8E7/z/ye+UWQvTptCUxfM7HS3iYd/tK9vXkmkbp6ehYQxjZfhSnwUbo4yeTQVXJ9IyaK 8wwAtn2uo82b34MM6QBT6xBYWLHHZHhUQxGiLRWHByNXFKXmbA2NGgWBwPixIIC7qn67Q0 rXHrEqx5L933ymrrywoXolbIUbAnG0yGsz7c0XyJmjfTWkMe8gKDoTyWp+Q9+TsYh6mrfE ZNxJCnQvTyxZ13dpeZ7/wj6oYmTKRHzkxrouy8xoZEUrQ6rMcvQcIQGGMWXBr8+Rz1ibrB q0E2C/9dyj2TETBAiMJrYc13NWVAl8mzXrUff1NU3ponoQLgs3BldvxYTFfGrg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1695830553; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=EdCiO/WzKECbYs7KtcCYhKCOSLS8gRQvCAW/vFRb9F4=; b=YReDyt9JG3c9HFVm3jjR59KBPrudAz6g1lOu804uGt8ruhv64qozjuWhLyNqZHyepfHAYV cCC1Rw8pXSmPDmAg== From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> To: linux-kernel@vger.kernel.org, rcu@vger.kernel.org Cc: "Paul E. McKenney" <paulmck@kernel.org>, Boqun Feng <boqun.feng@gmail.com>, Frederic Weisbecker <frederic@kernel.org>, Ingo Molnar <mingo@redhat.com>, Joel Fernandes <joel@joelfernandes.org>, John Ogness <john.ogness@linutronix.de>, Josh Triplett <josh@joshtriplett.org>, Lai Jiangshan <jiangshanlai@gmail.com>, Mathieu Desnoyers <mathieu.desnoyers@efficios.com>, Neeraj Upadhyay <quic_neeraju@quicinc.com>, Peter Zijlstra <peterz@infradead.org>, Steven Rostedt <rostedt@goodmis.org>, Thomas Gleixner <tglx@linutronix.de>, Waiman Long <longman@redhat.com>, Will Deacon <will@kernel.org>, Zqiang <qiang.zhang1211@gmail.com> Subject: [RFC PATCH] srcu: Use try-lock lockdep annotation for NMI-safe access. Message-ID: <20230927160231.XRCDDSK4@linutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (snail.vger.email [0.0.0.0]); Wed, 27 Sep 2023 09:03:29 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1778252263811338185 X-GMAIL-MSGID: 1778252263811338185 |
Series |
[RFC] srcu: Use try-lock lockdep annotation for NMI-safe access.
|
|
Commit Message
Sebastian Andrzej Siewior
Sept. 27, 2023, 4:02 p.m. UTC
It is claimed that srcu_read_lock_nmisafe() NMI-safe. However it
triggers a lockdep if used from NMI because lockdep expects a deadlock
since nothing disables NMIs while the lock is acquired.
Use a try-lock annotation for srcu_read_lock_nmisafe() to avoid lockdep
complains if used from NMI.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
The splat:
| ================================
| WARNING: inconsistent lock state
| 6.6.0-rc3-rt5+ #85 Not tainted
| --------------------------------
| inconsistent {INITIAL USE} -> {IN-NMI} usage.
| swapper/0/0 [HC1[1]:SC0[0]:HE0:SE1] takes:
| ffffffff828e6c90 (console_srcu){....}-{0:0}, at: console_srcu_read_lock+0x3a/0x50
| {INITIAL USE} state was registered at:
…
| CPU0
| ----
| lock(console_srcu);
| <Interrupt>
| lock(console_srcu);
|
| *** DEADLOCK ***
|
My guess is that trylock annotation should not apply to
rcu_lock_acquire(). This would distinguish it from from non-NMI safe
srcu_read_lock_nmisafe() and NMI check in rcu_read_unlock() is only
there to survive if accidentally used in-NMI.
include/linux/rcupdate.h | 6 ++++++
include/linux/srcu.h | 2 +-
2 files changed, 7 insertions(+), 1 deletion(-)
Comments
On Wed, Sep 27, 2023 at 06:02:31PM +0200, Sebastian Andrzej Siewior wrote: > It is claimed that srcu_read_lock_nmisafe() NMI-safe. However it > triggers a lockdep if used from NMI because lockdep expects a deadlock > since nothing disables NMIs while the lock is acquired. > > Use a try-lock annotation for srcu_read_lock_nmisafe() to avoid lockdep > complains if used from NMI. > > Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> > --- > > The splat: > | ================================ > | WARNING: inconsistent lock state > | 6.6.0-rc3-rt5+ #85 Not tainted > | -------------------------------- > | inconsistent {INITIAL USE} -> {IN-NMI} usage. > | swapper/0/0 [HC1[1]:SC0[0]:HE0:SE1] takes: > | ffffffff828e6c90 (console_srcu){....}-{0:0}, at: console_srcu_read_lock+0x3a/0x50 > | {INITIAL USE} state was registered at: > … > | CPU0 > | ---- > | lock(console_srcu); > | <Interrupt> > | lock(console_srcu); > | > | *** DEADLOCK *** > | > > My guess is that trylock annotation should not apply to > rcu_lock_acquire(). This would distinguish it from from non-NMI safe > srcu_read_lock_nmisafe() and NMI check in rcu_read_unlock() is only > there to survive if accidentally used in-NMI. I think this is a "side-effect" of commit f0f44752f5f6 ("rcu: Annotate SRCU's update-side lockdep dependencies"). In verify_lock_unused(), i.e. the checking for NMI lock usages, the logic is that 1) read lock usages in NMI conflicts with write lock usage in normal context (i.e. LOCKF_USED) 2) write lock usage in NMI conflicts with read and write lock usage in normal context (i.e. LOCKF_USED | LOCKF_USED_READ) before that commit, only read-side of SRCU is annotated, in other words, SRCU only has read lock usage from lockdep PoV, but after that commit, we annotate synchronize_srcu() as a write lock usage, so that we can detect deadlocks between *normal* srcu_read_lock() and synchronize_srcu(), however the side effect is now SRCU has a write lock usage from lockdep PoV. Actually in the above commit, I explicitly leave srcu_read_lock_nmisafe() alone since its locking rules may be different compared to srcu_read_lock(). In lockdep terms, srcu_read_lock_nmisafe() is a !check read lock and srcu_read_lock() is a check read lock. Maybe instead of using the trylock trick, we change lockdep to igore !check locks for NMI context detection? Untested code as below: diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index e85b5ad3e206..1af8d44e5eb4 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -5727,8 +5727,9 @@ void lock_acquire(struct lockdep_map *lock, unsigned int subclass, return; if (unlikely(!lockdep_enabled())) { + /* Only do NMI context checking if it's a check lock */ /* XXX allow trylock from NMI ?!? */ - if (lockdep_nmi() && !trylock) { + if (check && lockdep_nmi() && !trylock) { struct held_lock hlock; hlock.acquire_ip = ip; Peter, thoughts? Of course, either way, we need Fixes: f0f44752f5f6 ("rcu: Annotate SRCU's update-side lockdep dependencies") Regards, Boqun > > include/linux/rcupdate.h | 6 ++++++ > include/linux/srcu.h | 2 +- > 2 files changed, 7 insertions(+), 1 deletion(-) > > diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h > index 5e5f920ade909..44aab5c0bd2c1 100644 > --- a/include/linux/rcupdate.h > +++ b/include/linux/rcupdate.h > @@ -303,6 +303,11 @@ static inline void rcu_lock_acquire(struct lockdep_map *map) > lock_acquire(map, 0, 0, 2, 0, NULL, _THIS_IP_); > } > > +static inline void rcu_try_lock_acquire(struct lockdep_map *map) > +{ > + lock_acquire(map, 0, 1, 2, 0, NULL, _THIS_IP_); > +} > + > static inline void rcu_lock_release(struct lockdep_map *map) > { > lock_release(map, _THIS_IP_); > @@ -317,6 +322,7 @@ int rcu_read_lock_any_held(void); > #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ > > # define rcu_lock_acquire(a) do { } while (0) > +# define rcu_try_lock_acquire(a) do { } while (0) > # define rcu_lock_release(a) do { } while (0) > > static inline int rcu_read_lock_held(void) > diff --git a/include/linux/srcu.h b/include/linux/srcu.h > index 127ef3b2e6073..236610e4a8fa5 100644 > --- a/include/linux/srcu.h > +++ b/include/linux/srcu.h > @@ -229,7 +229,7 @@ static inline int srcu_read_lock_nmisafe(struct srcu_struct *ssp) __acquires(ssp > > srcu_check_nmi_safety(ssp, true); > retval = __srcu_read_lock_nmisafe(ssp); > - rcu_lock_acquire(&ssp->dep_map); > + rcu_try_lock_acquire(&ssp->dep_map); > return retval; > } > > -- > 2.40.1 >
On 2023-09-27 23:06:09 [-0700], Boqun Feng wrote: > SRCU only has read lock usage from lockdep PoV, but after that commit, > we annotate synchronize_srcu() as a write lock usage, so that we can > detect deadlocks between *normal* srcu_read_lock() and > synchronize_srcu(), however the side effect is now SRCU has a write lock > usage from lockdep PoV. Ach. There is a write annotation for SRCU and RCU has none. Okay that explains it. > Actually in the above commit, I explicitly leave > srcu_read_lock_nmisafe() alone since its locking rules may be different > compared to srcu_read_lock(). In lockdep terms, srcu_read_lock_nmisafe() > is a !check read lock and srcu_read_lock() is a check read lock. This was on v6.6-rc3 so it has the commit f0f44752f5f61 ("rcu: Annotate SRCU's update-side lockdep dependencies"). > Maybe > instead of using the trylock trick, we change lockdep to igore !check > locks for NMI context detection? Untested code as below: Just tested, no splat for the SRCU-in-NMI usage. Sebastian
On Wed, Sep 27, 2023 at 11:06:09PM -0700, Boqun Feng wrote: > diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c > index e85b5ad3e206..1af8d44e5eb4 100644 > --- a/kernel/locking/lockdep.c > +++ b/kernel/locking/lockdep.c > @@ -5727,8 +5727,9 @@ void lock_acquire(struct lockdep_map *lock, unsigned int subclass, > return; > > if (unlikely(!lockdep_enabled())) { > + /* Only do NMI context checking if it's a check lock */ > /* XXX allow trylock from NMI ?!? */ > - if (lockdep_nmi() && !trylock) { > + if (check && lockdep_nmi() && !trylock) { > struct held_lock hlock; > > hlock.acquire_ip = ip; > > Peter, thoughts? > I think I prefer the trylock one. Fundamentally trylock conveys the 'we wont block' thing. Making 'lock' sometimes work for NMI is just confusing.
On Wed, Sep 27, 2023 at 11:06:09PM -0700, Boqun Feng wrote: > I think this is a "side-effect" of commit f0f44752f5f6 ("rcu: Annotate > SRCU's update-side lockdep dependencies"). In verify_lock_unused(), i.e. > the checking for NMI lock usages, the logic is that I think I'm having a problem with this commit -- that is, by adding lockdep you're adding tracepoint, which rely on RCU being active. The result is that SRCU is now no longer usable from !RCU regions. Was this considered and intended?
On Thu, Sep 28, 2023 at 10:09:00AM +0200, Peter Zijlstra wrote: > On Wed, Sep 27, 2023 at 11:06:09PM -0700, Boqun Feng wrote: > > > I think this is a "side-effect" of commit f0f44752f5f6 ("rcu: Annotate > > SRCU's update-side lockdep dependencies"). In verify_lock_unused(), i.e. > > the checking for NMI lock usages, the logic is that > > I think I'm having a problem with this commit -- that is, by adding > lockdep you're adding tracepoint, which rely on RCU being active. > > The result is that SRCU is now no longer usable from !RCU regions. > Interesting > Was this considered and intended? > No, I don't think I have considered this before, I think I may still miss something here, maybe you or Paul can provide an example for such a case? One thing though, before the commit, srcu_read_lock() already has an rcu_lock_acquire() annotation which eventually calls lock_acquire() which has a tracepoint in it. Regards, Boqun
On Thu, Sep 28, 2023 at 07:54:10AM -0700, Boqun Feng wrote: > On Thu, Sep 28, 2023 at 10:09:00AM +0200, Peter Zijlstra wrote: > > On Wed, Sep 27, 2023 at 11:06:09PM -0700, Boqun Feng wrote: > > > > > I think this is a "side-effect" of commit f0f44752f5f6 ("rcu: Annotate > > > SRCU's update-side lockdep dependencies"). In verify_lock_unused(), i.e. > > > the checking for NMI lock usages, the logic is that > > > > I think I'm having a problem with this commit -- that is, by adding > > lockdep you're adding tracepoint, which rely on RCU being active. > > > > The result is that SRCU is now no longer usable from !RCU regions. > > > > Interesting > > > Was this considered and intended? > > > > No, I don't think I have considered this before, I think I may still > miss something here, maybe you or Paul can provide an example for such > a case? The whole trace_.*_rcuidle() machinery. Which I thought I had fully eradicated, but apparently still exists (with *one* user) :-/ Search for rcuidle in include/linux/tracepoint.h Also, git grep trace_.*_rcuidle
On Thu, Sep 28, 2023 at 05:29:42PM +0200, Peter Zijlstra wrote: > On Thu, Sep 28, 2023 at 07:54:10AM -0700, Boqun Feng wrote: > > On Thu, Sep 28, 2023 at 10:09:00AM +0200, Peter Zijlstra wrote: > > > On Wed, Sep 27, 2023 at 11:06:09PM -0700, Boqun Feng wrote: > > > > > > > I think this is a "side-effect" of commit f0f44752f5f6 ("rcu: Annotate > > > > SRCU's update-side lockdep dependencies"). In verify_lock_unused(), i.e. > > > > the checking for NMI lock usages, the logic is that > > > > > > I think I'm having a problem with this commit -- that is, by adding > > > lockdep you're adding tracepoint, which rely on RCU being active. > > > > > > The result is that SRCU is now no longer usable from !RCU regions. > > > > > > > Interesting > > > > > Was this considered and intended? > > > > > > > No, I don't think I have considered this before, I think I may still > > miss something here, maybe you or Paul can provide an example for such > > a case? > > The whole trace_.*_rcuidle() machinery. Which I thought I had fully > eradicated, but apparently still exists (with *one* user) :-/ > > Search for rcuidle in include/linux/tracepoint.h > > Also, git grep trace_.*_rcuidle > Thanks! But as I mentioned in the IRC, trace_.*_rcuidle() call the special APIs srcu_read_{un,}lock_notrace(), and these won't call lockdep annotation functions. And what the commit did was only changing the lockdep annotation of srcu_read_{un,}lock(), so we are still fine here? Regards, Boqun >
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 5e5f920ade909..44aab5c0bd2c1 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -303,6 +303,11 @@ static inline void rcu_lock_acquire(struct lockdep_map *map) lock_acquire(map, 0, 0, 2, 0, NULL, _THIS_IP_); } +static inline void rcu_try_lock_acquire(struct lockdep_map *map) +{ + lock_acquire(map, 0, 1, 2, 0, NULL, _THIS_IP_); +} + static inline void rcu_lock_release(struct lockdep_map *map) { lock_release(map, _THIS_IP_); @@ -317,6 +322,7 @@ int rcu_read_lock_any_held(void); #else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ # define rcu_lock_acquire(a) do { } while (0) +# define rcu_try_lock_acquire(a) do { } while (0) # define rcu_lock_release(a) do { } while (0) static inline int rcu_read_lock_held(void) diff --git a/include/linux/srcu.h b/include/linux/srcu.h index 127ef3b2e6073..236610e4a8fa5 100644 --- a/include/linux/srcu.h +++ b/include/linux/srcu.h @@ -229,7 +229,7 @@ static inline int srcu_read_lock_nmisafe(struct srcu_struct *ssp) __acquires(ssp srcu_check_nmi_safety(ssp, true); retval = __srcu_read_lock_nmisafe(ssp); - rcu_lock_acquire(&ssp->dep_map); + rcu_try_lock_acquire(&ssp->dep_map); return retval; }