From patchwork Tue Mar 4 09:21:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Elver X-Patchwork-Id: 14000261 Received: from mail-ed1-f73.google.com (mail-ed1-f73.google.com [209.85.208.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D1C31FFC4C for ; Tue, 4 Mar 2025 09:25:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741080336; cv=none; b=bJgSXfp3txe+K7caTrncwG6nmaVN4QsS5d9vSDtiFgqXXH7toL2iTU6BI3wMvq+8pG11QWnOEc/B0KkVX/ekVA7a245jqhwnS1DrjgFTdqLI3qNioomrP4yGxS4Z01RlGW4QRDuPSfgROhTnXtrhWV16WAX5JgUumAiHqc2NoVo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741080336; c=relaxed/simple; bh=TLyEQUYL7r6oDXGxc1hiNLMwzZ9LFVmZKfS7DKxQEFY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=dNltBD4LiZY9u1gIa0065Zvbg6DJr5hQApJ0nVp8dRzi7tYQPyOGI+95zm4KWql/NLNODfqAEbLRxB0JOtXxFEC3EGxatm7lp4zT/+CuZGP5CTNyKGJiOvl8tYzR4gbtZbTh2WgOv7BHTJzLEOen4esMnc4bVgK8J2nvZjcld/A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--elver.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=SHMk7EWS; arc=none smtp.client-ip=209.85.208.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--elver.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="SHMk7EWS" Received: by mail-ed1-f73.google.com with SMTP id 4fb4d7f45d1cf-5d9e4d33f04so5780460a12.0 for ; Tue, 04 Mar 2025 01:25:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1741080333; x=1741685133; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=3N8S7JUPE1q89goF9WrUxLudC8JOfTuJ5GayTplf0i0=; b=SHMk7EWSuWukqRqMG8iYYRQiPbClEgA6m01WDa3uJvnK9TaTbWOhbeqwvd7TvEyXud b+PcBsu4NuG0t8xqKC9GEmUdt6fRvFYDoypC3kTJTTZYWGpm0hvSMicCMhk120S4QasX Y2+J5bdQFuJz6d5Bl5eVoKX5C++MBYrHD1Xaq6/SzbnF2l6MuDx2WeikcrAUTKdUyGNg LVOAXdfCwezYkmETkYRoftOx9m0mtVFPrWloz+9KKlhFVXsxzwOTkbzm7Actf3VcJ4n2 lPwwu//qOmaIIa/kpQS0Nv19v6KfuKAIqGAg6+YecZCbKDiPoQsL79Pv59Dmx1Ku6cMp suQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741080333; x=1741685133; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=3N8S7JUPE1q89goF9WrUxLudC8JOfTuJ5GayTplf0i0=; b=MGPv48O3dA4nB0R+BfctzjNXRrRlTuvunSyqtaLwPdDKCxBUVGpy+QVkvs+oqeGz0+ w4wsfGQpfCbwJ81APcnF+hu4J/Upkk9g8QUItIxeFh2o7kqqz+UCI6Mb1YZAu5kV0Dd8 ZnYnEGtaDyKVQeBtZ/wOg6sfyWQs3tyADtkh+yFtHLJxlXo87NAsf0mOzGps1H5+kDED oJWY4/X55ZdZjVRjLOui8X/XmrOBnzQU4H297EumybP3ikKWTCQjT+XelPGPqtNPTH3Q khmfUkon2hGD3laUVX4vzcD0ephKVX7HB1EU+sFBmftsMt/1oBR5hS1L2hwyTV8NRFQt MXgg== X-Forwarded-Encrypted: i=1; AJvYcCXTPRu0Eku38Ka0bWHSrm4yYjPjU52T3pqhxE2lfLteDGu4eoeuZaRKlr5k8KsDbqk4SyY=@vger.kernel.org X-Gm-Message-State: AOJu0YweSUUrjNknctSbhakLQSCCqSZaLL4Y/DBBfGM5itdKl3efjR1/ 2YS7+jjOnjOJcHM84HWBBTszE1R9UaVVD9n1GvXdxvxqpuccfy78br0PlTgf9yQhXVGJUaInFA= = X-Google-Smtp-Source: AGHT+IG3w3Av+LCgyTZprIzkeKZapwa6ti8rnRN5LRNN20fd/po8CjvPaQjDhiyO2RBifz8hQtZRzFukLg== X-Received: from edc18.prod.google.com ([2002:a05:6402:4612:b0:5e5:29f3:27af]) (user=elver job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6402:4603:b0:5e5:4807:5441 with SMTP id 4fb4d7f45d1cf-5e5480755bfmr7319106a12.30.1741080333339; Tue, 04 Mar 2025 01:25:33 -0800 (PST) Date: Tue, 4 Mar 2025 10:21:08 +0100 In-Reply-To: <20250304092417.2873893-1-elver@google.com> Precedence: bulk X-Mailing-List: rcu@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250304092417.2873893-1-elver@google.com> X-Mailer: git-send-email 2.48.1.711.g2feabab25a-goog Message-ID: <20250304092417.2873893-10-elver@google.com> Subject: [PATCH v2 09/34] compiler-capability-analysis: Change __cond_acquires to take return value From: Marco Elver To: elver@google.com Cc: "David S. Miller" , Luc Van Oostenryck , "Paul E. McKenney" , Alexander Potapenko , Arnd Bergmann , Bart Van Assche , Bill Wendling , Boqun Feng , Dmitry Vyukov , Eric Dumazet , Frederic Weisbecker , Greg Kroah-Hartman , Herbert Xu , Ingo Molnar , Jann Horn , Jiri Slaby , Joel Fernandes , Jonathan Corbet , Josh Triplett , Justin Stitt , Kees Cook , Kentaro Takeda , Mark Rutland , Mathieu Desnoyers , Miguel Ojeda , Nathan Chancellor , Neeraj Upadhyay , Peter Zijlstra , Steven Rostedt , Tetsuo Handa , Thomas Gleixner , Uladzislau Rezki , Waiman Long , Will Deacon , kasan-dev@googlegroups.com, linux-kernel@vger.kernel.org, llvm@lists.linux.dev, rcu@vger.kernel.org, linux-crypto@vger.kernel.org, linux-serial@vger.kernel.org While Sparse is oblivious to the return value of conditional acquire functions, Clang's capability analysis needs to know the return value which indicates successful acquisition. Add the additional argument, and convert existing uses. Notably, Clang's interpretation of the value merely relates to the use in a later conditional branch, i.e. 1 ==> capability acquired in branch taken if condition non-zero, and 0 ==> capability acquired in branch taken if condition is zero. Given the precise value does not matter, introduce symbolic variants to use instead of either 0 or 1, which should be more intuitive. No functional change intended. Signed-off-by: Marco Elver --- v2: * Use symbolic values for __cond_acquires() and __cond_acquires_shared() (suggested by Bart). --- fs/dlm/lock.c | 2 +- include/linux/compiler-capability-analysis.h | 31 ++++++++++++++++---- include/linux/refcount.h | 6 ++-- include/linux/spinlock.h | 6 ++-- include/linux/spinlock_api_smp.h | 8 ++--- net/ipv4/tcp_sigpool.c | 2 +- 6 files changed, 38 insertions(+), 17 deletions(-) diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index c8ff88f1cdcf..6799cb0c8f50 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -343,7 +343,7 @@ void dlm_hold_rsb(struct dlm_rsb *r) /* TODO move this to lib/refcount.c */ static __must_check bool dlm_refcount_dec_and_write_lock_bh(refcount_t *r, rwlock_t *lock) -__cond_acquires(lock) + __cond_acquires(true, lock) { if (refcount_dec_not_one(r)) return false; diff --git a/include/linux/compiler-capability-analysis.h b/include/linux/compiler-capability-analysis.h index c47d9ed18303..832727fea140 100644 --- a/include/linux/compiler-capability-analysis.h +++ b/include/linux/compiler-capability-analysis.h @@ -240,7 +240,7 @@ # define __must_hold(x) __attribute__((context(x,1,1))) # define __must_not_hold(x) # define __acquires(x) __attribute__((context(x,0,1))) -# define __cond_acquires(x) __attribute__((context(x,0,-1))) +# define __cond_acquires(ret, x) __attribute__((context(x,0,-1))) # define __releases(x) __attribute__((context(x,1,0))) # define __acquire(x) __context__(x,1) # define __release(x) __context__(x,-1) @@ -283,15 +283,32 @@ */ # define __acquires(x) __acquires_cap(x) +/* + * Clang's analysis does not care precisely about the value, only that it is + * either zero or non-zero. So the __cond_acquires() interface might be + * misleading if we say that @ret is the value returned if acquired. Instead, + * provide symbolic variants which we translate. + */ +#define __cond_acquires_impl_true(x, ...) __try_acquires##__VA_ARGS__##_cap(1, x) +#define __cond_acquires_impl_false(x, ...) __try_acquires##__VA_ARGS__##_cap(0, x) +#define __cond_acquires_impl_nonzero(x, ...) __try_acquires##__VA_ARGS__##_cap(1, x) +#define __cond_acquires_impl_0(x, ...) __try_acquires##__VA_ARGS__##_cap(0, x) +#define __cond_acquires_impl_nonnull(x, ...) __try_acquires##__VA_ARGS__##_cap(1, x) +#define __cond_acquires_impl_NULL(x, ...) __try_acquires##__VA_ARGS__##_cap(0, x) + /** * __cond_acquires() - function attribute, function conditionally * acquires a capability exclusively + * @ret: abstract value returned by function if capability acquired * @x: capability instance pointer * * Function attribute declaring that the function conditionally acquires the - * given capability instance @x exclusively, but does not release it. + * given capability instance @x exclusively, but does not release it. The + * function return value @ret denotes when the capability is acquired. + * + * @ret may be one of: true, false, nonzero, 0, nonnull, NULL. */ -# define __cond_acquires(x) __try_acquires_cap(1, x) +# define __cond_acquires(ret, x) __cond_acquires_impl_##ret(x) /** * __releases() - function attribute, function releases a capability exclusively @@ -358,12 +375,16 @@ /** * __cond_acquires_shared() - function attribute, function conditionally * acquires a capability shared + * @ret: abstract value returned by function if capability acquired * @x: capability instance pointer * * Function attribute declaring that the function conditionally acquires the - * given capability instance @x with shared access, but does not release it. + * given capability instance @x with shared access, but does not release it. The + * function return value @ret denotes when the capability is acquired. + * + * @ret may be one of: true, false, nonzero, 0, nonnull, NULL. */ -# define __cond_acquires_shared(x) __try_acquires_shared_cap(1, x) +# define __cond_acquires_shared(ret, x) __cond_acquires_impl_##ret(x, _shared) /** * __releases_shared() - function attribute, function releases a diff --git a/include/linux/refcount.h b/include/linux/refcount.h index 35f039ecb272..88a6e292271d 100644 --- a/include/linux/refcount.h +++ b/include/linux/refcount.h @@ -353,9 +353,9 @@ static inline void refcount_dec(refcount_t *r) extern __must_check bool refcount_dec_if_one(refcount_t *r); extern __must_check bool refcount_dec_not_one(refcount_t *r); -extern __must_check bool refcount_dec_and_mutex_lock(refcount_t *r, struct mutex *lock) __cond_acquires(lock); -extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock) __cond_acquires(lock); +extern __must_check bool refcount_dec_and_mutex_lock(refcount_t *r, struct mutex *lock) __cond_acquires(true, lock); +extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock) __cond_acquires(true, lock); extern __must_check bool refcount_dec_and_lock_irqsave(refcount_t *r, spinlock_t *lock, - unsigned long *flags) __cond_acquires(lock); + unsigned long *flags) __cond_acquires(true, lock); #endif /* _LINUX_REFCOUNT_H */ diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index 09124713b115..12369fa9e3bb 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -362,7 +362,7 @@ static __always_inline void spin_lock_bh(spinlock_t *lock) } static __always_inline int spin_trylock(spinlock_t *lock) - __cond_acquires(lock) __no_capability_analysis + __cond_acquires(true, lock) __no_capability_analysis { return raw_spin_trylock(&lock->rlock); } @@ -420,13 +420,13 @@ static __always_inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned lo } static __always_inline int spin_trylock_bh(spinlock_t *lock) - __cond_acquires(lock) __no_capability_analysis + __cond_acquires(true, lock) __no_capability_analysis { return raw_spin_trylock_bh(&lock->rlock); } static __always_inline int spin_trylock_irq(spinlock_t *lock) - __cond_acquires(lock) __no_capability_analysis + __cond_acquires(true, lock) __no_capability_analysis { return raw_spin_trylock_irq(&lock->rlock); } diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_smp.h index fab02d8bf0c9..a77b76003ebb 100644 --- a/include/linux/spinlock_api_smp.h +++ b/include/linux/spinlock_api_smp.h @@ -34,8 +34,8 @@ unsigned long __lockfunc _raw_spin_lock_irqsave(raw_spinlock_t *lock) unsigned long __lockfunc _raw_spin_lock_irqsave_nested(raw_spinlock_t *lock, int subclass) __acquires(lock); -int __lockfunc _raw_spin_trylock(raw_spinlock_t *lock) __cond_acquires(lock); -int __lockfunc _raw_spin_trylock_bh(raw_spinlock_t *lock) __cond_acquires(lock); +int __lockfunc _raw_spin_trylock(raw_spinlock_t *lock) __cond_acquires(true, lock); +int __lockfunc _raw_spin_trylock_bh(raw_spinlock_t *lock) __cond_acquires(true, lock); void __lockfunc _raw_spin_unlock(raw_spinlock_t *lock) __releases(lock); void __lockfunc _raw_spin_unlock_bh(raw_spinlock_t *lock) __releases(lock); void __lockfunc _raw_spin_unlock_irq(raw_spinlock_t *lock) __releases(lock); @@ -84,7 +84,7 @@ _raw_spin_unlock_irqrestore(raw_spinlock_t *lock, unsigned long flags) #endif static inline int __raw_spin_trylock(raw_spinlock_t *lock) - __cond_acquires(lock) + __cond_acquires(true, lock) { preempt_disable(); if (do_raw_spin_trylock(lock)) { @@ -177,7 +177,7 @@ static inline void __raw_spin_unlock_bh(raw_spinlock_t *lock) } static inline int __raw_spin_trylock_bh(raw_spinlock_t *lock) - __cond_acquires(lock) + __cond_acquires(true, lock) { __local_bh_disable_ip(_RET_IP_, SOFTIRQ_LOCK_OFFSET); if (do_raw_spin_trylock(lock)) { diff --git a/net/ipv4/tcp_sigpool.c b/net/ipv4/tcp_sigpool.c index d8a4f192873a..10b2e5970c40 100644 --- a/net/ipv4/tcp_sigpool.c +++ b/net/ipv4/tcp_sigpool.c @@ -257,7 +257,7 @@ void tcp_sigpool_get(unsigned int id) } EXPORT_SYMBOL_GPL(tcp_sigpool_get); -int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c) __cond_acquires(RCU_BH) +int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c) __cond_acquires(0, RCU_BH) { struct crypto_ahash *hash;