once_lite: Simplify condition handling and fix context analysis
PATCH 1/1 once_lite: Simplify condition handling and fix context analysis
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.
--- include/linux/once_lite.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
include/linux/once_lite.h +5 -3
@@ -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); \
Signature · 1 line
2.55.0.970.g62bdec98f9-goog
[email protected]
AI reviewSashiko has reviewed this patch and found no issues. It looks great!
Quoted 21 lines
When
WARN_ON_ONCE()wraps a conditional lock acquisition (such asdown_write_trylock()) on architectures relying onDO_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_oncerather 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())
Quoted 8 lines
This simplifies the implementation, short-circuits evaluation so that
__ONCE_LITE()is not called when the condition is false, and ensures thatDO_ONCE_LITE_IF()only enters__ONCE_LITE()when__ret_do_onceis true.
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Quoted 21 lines · Marco Elver
When
WARN_ON_ONCE()wraps a conditional lock acquisition (such asdown_write_trylock()) on architectures relying onDO_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_oncerather 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())
Quoted 8 lines
This simplifies the implementation, short-circuits evaluation so that
__ONCE_LITE()is not called when the condition is false, and ensures thatDO_ONCE_LITE_IF()only enters__ONCE_LITE()when__ret_do_onceis true.
Thanks, this fixes that warning for me across all my builds.
Signature · 2 lines
Cheers, Nathan
Quoted 28 lines · Nathan Chancellor
Quoted 26 lines · Marco Elver
When
WARN_ON_ONCE()wraps a conditional lock acquisition (such asdown_write_trylock()) on architectures relying onDO_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_oncerather 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 thatDO_ONCE_LITE_IF()only enters__ONCE_LITE()when__ret_do_onceis true.
Quoted 7 lines
Quoted 3 lines
Thanks, this fixes that warning for me across all my builds.
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
reviewerQuoted 33 lines · Marco Elver
Quoted 32 lines · Nathan Chancellor
Quoted 29 lines · Marco Elver
When
WARN_ON_ONCE()wraps a conditional lock acquisition (such asdown_write_trylock()) on architectures relying onDO_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_oncerather 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 thatDO_ONCE_LITE_IF()only enters__ONCE_LITE()when__ret_do_onceis true.
Quoted 7 lines
Quoted 3 lines
Thanks, this fixes that warning for me across all my builds.
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.
Honza
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
Quoted 7 lines · Jan Kara
Quoted 3 lines · Marco Elver
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:
[email protected]: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
----------------------------------------------------------------
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(-)
Signature · 2 lines
Cheers, Nathan
Jan Kara
reviewerQuoted 23 lines · Nathan Chancellor
Quoted 7 lines · Jan Kara
Quoted 3 lines · Marco Elver
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:
[email protected]:pub/scm/linux/kernel/git/nathan/linux.git tags/clang-fixes-once_lite-for-7.4
Quoted 8 lines
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 foronce_lite.hcontext analysis fixSigned-off-by Nathan Chancellor <[email protected]>
OK, thanks. I've pulled this branch into my tree.
Honza
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR