[PATCH] once_lite: Simplify condition handling and fix context analysis

2 views
Skip to first unread message

Marco Elver

unread,
Sep 3, 2026, 6:18:57 AM (8 days ago) Sep 3
to el...@google.com, Nathan Chancellor, linux-...@vger.kernel.org, kasa...@googlegroups.com, Jan Kara, Timothy Day, linux...@vger.kernel.org, Theodore Tso, linux-...@vger.kernel.org
When WARN_ON_ONCE() wraps a conditional lock acquisition (such as
down_write_trylock()) on architectures relying on DO_ONCE_LITE_IF()
(e.g. arm), Clang's context analysis (Thread Safety Analysis) failed
with a false positive:

fs/ext2/xattr.c:825:6: error: rw_semaphore 'EXT2_I().xattr_sem' is not held on every path through here [-Werror,-Wthread-safety-analysis]
825 | if (WARN_ON_ONCE(!down_write_trylock(&EXT2_I(inode)->xattr_sem)))
| ^

This happens because DO_ONCE_LITE_IF() branches on __ONCE_LITE_IF()'s
return value (__ret_once), creating an intermediate branch merge point
where the lock may or may not be held depending on whether the once-flag
(__already_done) was already set. Because the merge branch condition is
__ret_once rather than the trylock predicate (__ret_do_once), Clang
cannot reconcile the lockset at the branch merge points.

Fix it by refactoring __ONCE_LITE_IF() into an unconditional
__ONCE_LITE() primitive and redefining __ONCE_LITE_IF(condition) as:

(unlikely(condition) && __ONCE_LITE())

This simplifies the implementation, short-circuits evaluation so that
__ONCE_LITE() is not called when the condition is false, and ensures
that DO_ONCE_LITE_IF() only enters __ONCE_LITE() when __ret_do_once is
true.

Reported-by: Nathan Chancellor <nat...@kernel.org>
Link: https://lore.kernel.org/all/20260903072759.GA1750084@ax162/
Signed-off-by: Marco Elver <el...@google.com>
---
include/linux/once_lite.h | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/linux/once_lite.h b/include/linux/once_lite.h
index 236592c4eeb1..5e2b67039aaf 100644
--- a/include/linux/once_lite.h
+++ b/include/linux/once_lite.h
@@ -10,19 +10,21 @@
#define DO_ONCE_LITE(func, ...) \
DO_ONCE_LITE_IF(true, func, ##__VA_ARGS__)

-#define __ONCE_LITE_IF(condition) \
+#define __ONCE_LITE() \
({ \
static bool __section(".data..once") __already_done; \
- bool __ret_cond = !!(condition); \
bool __ret_once = false; \
\
- if (unlikely(__ret_cond) && unlikely(!__already_done)) {\
+ if (unlikely(!__already_done)) { \
__already_done = true; \
__ret_once = true; \
} \
unlikely(__ret_once); \
})

+#define __ONCE_LITE_IF(condition) \
+ (unlikely(condition) && __ONCE_LITE())
+
#define DO_ONCE_LITE_IF(condition, func, ...) \
({ \
bool __ret_do_once = !!(condition); \
--
2.55.0.970.g62bdec98f9-goog

Nathan Chancellor

unread,
Sep 7, 2026, 6:13:41 PM (4 days ago) Sep 7
to Marco Elver, linux-...@vger.kernel.org, kasa...@googlegroups.com, Jan Kara, Timothy Day, linux...@vger.kernel.org, Theodore Tso, linux-...@vger.kernel.org
On Thu, Sep 03, 2026 at 10:16:38AM +0000, Marco Elver wrote:
> When WARN_ON_ONCE() wraps a conditional lock acquisition (such as
> down_write_trylock()) on architectures relying on DO_ONCE_LITE_IF()
> (e.g. arm), Clang's context analysis (Thread Safety Analysis) failed
> with a false positive:
>
> fs/ext2/xattr.c:825:6: error: rw_semaphore 'EXT2_I().xattr_sem' is not held on every path through here [-Werror,-Wthread-safety-analysis]
> 825 | if (WARN_ON_ONCE(!down_write_trylock(&EXT2_I(inode)->xattr_sem)))
> | ^
>
> This happens because DO_ONCE_LITE_IF() branches on __ONCE_LITE_IF()'s
> return value (__ret_once), creating an intermediate branch merge point
> where the lock may or may not be held depending on whether the once-flag
> (__already_done) was already set. Because the merge branch condition is
> __ret_once rather than the trylock predicate (__ret_do_once), Clang
> cannot reconcile the lockset at the branch merge points.
>
> Fix it by refactoring __ONCE_LITE_IF() into an unconditional
> __ONCE_LITE() primitive and redefining __ONCE_LITE_IF(condition) as:
>
> (unlikely(condition) && __ONCE_LITE())
>
> This simplifies the implementation, short-circuits evaluation so that
> __ONCE_LITE() is not called when the condition is false, and ensures
> that DO_ONCE_LITE_IF() only enters __ONCE_LITE() when __ret_do_once is
> true.
>
> Reported-by: Nathan Chancellor <nat...@kernel.org>
> Link: https://lore.kernel.org/all/20260903072759.GA1750084@ax162/
> Signed-off-by: Marco Elver <el...@google.com>

Thanks, this fixes that warning for me across all my builds.

Tested-by: Nathan Chancellor <nat...@kernel.org> # build

--
Cheers,
Nathan

Marco Elver

unread,
Sep 7, 2026, 6:18:14 PM (4 days ago) Sep 7
to Nathan Chancellor, linux-...@vger.kernel.org, kasa...@googlegroups.com, Jan Kara, Timothy Day, linux...@vger.kernel.org, Theodore Tso, linux-...@vger.kernel.org
Thanks! I think this is one of those orphaned files - which tree can
this go through? Can it go through your tree, unless Jan already
picked it up with the other fix?

Jan Kara

unread,
Sep 8, 2026, 6:15:26 AM (3 days ago) Sep 8
to Marco Elver, Nathan Chancellor, linux-...@vger.kernel.org, kasa...@googlegroups.com, Jan Kara, Timothy Day, linux...@vger.kernel.org, Theodore Tso, linux-...@vger.kernel.org
If Nathan can take it through his tree, that would be great, otherwise I
can take it through mine. Just let me know.

Honza
--
Jan Kara <ja...@suse.com>
SUSE Labs, CR

Nathan Chancellor

unread,
Sep 8, 2026, 8:20:11 PM (3 days ago) Sep 8
to Jan Kara, Marco Elver, linux-...@vger.kernel.org, kasa...@googlegroups.com, Timothy Day, linux...@vger.kernel.org, Theodore Tso, linux-...@vger.kernel.org
I applied this to my clang-fixes tree and created an immutable tag for
you to pull from, as you should have it in your tree since you are
enabling context analysis there. If nobody else needs it and I do not
have any other material for 7.4 in that tree, I won't send a pull
request if the ext2 tree is merged with this included.

The following changes since commit cee9395acd8043be0644b25c34bfa86623f2b935:

Linux 7.3-rc1 (2026-08-30 13:34:40 -0700)

are available in the Git repository at:

g...@gitolite.kernel.org:pub/scm/linux/kernel/git/nathan/linux.git tags/clang-fixes-once_lite-for-7.4

for you to fetch changes up to 0bb666d5f5a2339a5692afb312c2161df9620503:

once_lite: Simplify condition handling and fix context analysis (2026-09-08 16:54:02 -0700)

----------------------------------------------------------------
Immutable branch for once_lite.h context analysis fix

Signed-off-by: Nathan Chancellor <nat...@kernel.org>

----------------------------------------------------------------
Marco Elver (1):
once_lite: Simplify condition handling and fix context analysis

include/linux/once_lite.h | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)

--
Cheers,
Nathan

Jan Kara

unread,
Sep 9, 2026, 5:46:49 AM (2 days ago) Sep 9
to Nathan Chancellor, Jan Kara, Marco Elver, linux-...@vger.kernel.org, kasa...@googlegroups.com, Timothy Day, linux...@vger.kernel.org, Theodore Tso, linux-...@vger.kernel.org
On Tue 08-09-26 17:20:05, Nathan Chancellor wrote:
> On Tue, Sep 08, 2026 at 12:15:13PM +0200, Jan Kara wrote:
> > On Tue 08-09-26 00:17:34, Marco Elver wrote:
> > > Thanks! I think this is one of those orphaned files - which tree can
> > > this go through? Can it go through your tree, unless Jan already
> > > picked it up with the other fix?
> >
> > If Nathan can take it through his tree, that would be great, otherwise I
> > can take it through mine. Just let me know.
>
> I applied this to my clang-fixes tree and created an immutable tag for
> you to pull from, as you should have it in your tree since you are
> enabling context analysis there. If nobody else needs it and I do not
> have any other material for 7.4 in that tree, I won't send a pull
> request if the ext2 tree is merged with this included.
>
> The following changes since commit cee9395acd8043be0644b25c34bfa86623f2b935:
>
> Linux 7.3-rc1 (2026-08-30 13:34:40 -0700)
>
> are available in the Git repository at:
>
> g...@gitolite.kernel.org:pub/scm/linux/kernel/git/nathan/linux.git tags/clang-fixes-once_lite-for-7.4
>
> for you to fetch changes up to 0bb666d5f5a2339a5692afb312c2161df9620503:
>
> once_lite: Simplify condition handling and fix context analysis (2026-09-08 16:54:02 -0700)
>
> ----------------------------------------------------------------
> Immutable branch for once_lite.h context analysis fix
>
> Signed-off-by: Nathan Chancellor <nat...@kernel.org>

OK, thanks. I've pulled this branch into my tree.
Reply all
Reply to author
Forward
0 new messages