On 3/17/26 10:24, Albert Esteve wrote:
> Some unit tests intentionally trigger warning backtraces by passing bad
> parameters to kernel API functions. Such unit tests typically check the
> return value from such calls, not the existence of the warning backtrace.
> 
> Such intentionally generated warning backtraces are neither desirable
> nor useful for a number of reasons:
> - They can result in overlooked real problems.
> - A warning that suddenly starts to show up in unit tests needs to be
>   investigated and has to be marked to be ignored, for example by
>   adjusting filter scripts. Such filters are ad hoc because there is
>   no real standard format for warnings. On top of that, such filter
>   scripts would require constant maintenance.
> 
> One option to address the problem would be to add messages such as
> "expected warning backtraces start/end here" to the kernel log.
> However, that would again require filter scripts, might result in
> missing real problematic warning backtraces triggered while the test
> is running, and the irrelevant backtrace(s) would still clog the
> kernel log.
> 
> Solve the problem by providing a means to identify and suppress specific
> warning backtraces while executing test code. Support suppressing multiple
> backtraces while at the same time limiting changes to generic code to the
> absolute minimum.
> 
> Overview:
> Patch#1 Introduces the suppression infrastructure.
> Patch#2 Mitigate the impact at WARN*() sites.
> Patch#3 Adds selftests to validate the functionality.
> Patch#4 Demonstrates real-world usage in the DRM subsystem.
> Patch#5 Documents the new API and usage guidelines.
> 
> Design Notes:
> The objective is to suppress unwanted WARN*() generated messages.
> 
> Although most major architectures share common bug handling via `lib/bug.c`
> and `report_bug()`, some minor or legacy architectures still rely on their
> own platform-specific handling. This divergence must be considered in any
> such feature. Additionally, a key challenge in implementing this feature is
> the fragmentation of `WARN*()` messages emission: specific part in the
> macro, common with BUG*() part in the exception handler.
> As a result, any intervention to suppress the message must occur before the
> illegal instruction.
> 
> Lessons from the Previous Attempt
> In earlier iterations, suppression logic was added inside the
> `__report_bug()` function to intercept WARN*() messages not producing
> messages in the macro.
> To implement the check in the bug handler code, two strategies were
> considered:
> 
> * Strategy #1: Use `kallsyms` to infer the originating functionid, namely
>   a pointer to the function. Since in any case, the user interface relies
>   on function names, they must be translated in addresses at suppression-
>   time or at check-time.
>   Assuming to translate at suppression-time, the `kallsyms` subsystem needs
>   to be used to determine the symbol address from the name, and again to
>   produce the functionid from `bugaddr`. This approach proved unreliable
>   due to compiler-induced transformations such as inlining, cloning, and
>   code fragmentation. Attempts to preventing them is also unconvenient
>   because several `WARN()` sites are in functions intentionally declared
>   as `__always_inline`.
> 
> * Strategy #2: Store function name `__func__` in `struct bug_entry` in
>   the `__bug_table`. This implementation was used in the previous version.
>   However, `__func__` is a compiler-generated symbol, which complicates
>   relocation and linking in position-independent code. Workarounds such as
>   storing offsets from `.rodata` or embedding string literals directly into
>   the table would have significantly either increased complexity or
>   increase the __bug_table size.
>   Additionally, architectures not using the unified `BUG()` path would
>   still require ad-hoc handling. Because current WARN*() message production
>   strategy, a few WARN*() macros still need a check to suppress the part of
>   the message produced in the macro itself.
> 
> As a result, previous version proposed a per-macro solution, which offers
> better control on where the suppression logic is applied.
> 
> For this iteration, the `__report_bug()` centralized approach was
> revisited after the discussion in the previous version [1].

Discussion with PeterZ, who is not CC'd here? (did it now for my reply).

> However, again this approach did not work because:
> - Some warning output is generated directly in the macros before calling
>   the centralized functions (e.g., `__warn_printk()` in `__WARN_printf()`)
> - Functions in the warning path like `warn_slowpath_fmt()` are marked
>   `__always_inline`, making it difficult to intercept early enough
> - So, by the time `__report_bug()` is called, output has already been written
>   to the console, making suppression ineffective
> 
> Current Proposal: Check Directly in the `WARN()` Macros.
> This avoids the need for function symbol resolution or ELF section
> modification.
> Suppression is implemented directly in the `WARN*()` macros.

So does that bloat every warn/bug site (as Peter objected to) or not?
And is it compatible with x86? I see you modify include/asm-generic/bug.h
but x86 has its own version of e.g. __WARN_printf ?

> A helper function, `__kunit_is_suppressed_warning()`, is used to determine
> whether suppression applies. It is marked as `noinstr`, since some `WARN*()`
> sites reside in non-instrumentable sections. The function uses a static
> branch for the fast path check (which is `noinstr`-safe), and only calls
> the actual suppression check (which uses `strcmp`, and is surrounded by
> instrumentation_begin()/end() calls) when suppressions are active.
> The list of suppressed warnings is protected with RCU (Read-Copy-Update)
> to allow concurrent read access without locks.
> 
> To minimize runtime impact when no suppressions are active, static branching
> is used via a static key (`kunit_suppress_warnings_key`). The branch is
> automatically enabled when the first suppression starts and disabled when the
> last suppression ends, tracked via an atomic counter. This keeps the 
> suppression
> check code out-of-line, reducing code bloat at each `WARN*()` site while
> maintaining minimal runtime overhead in the common case (no active 
> suppressions).
> 
> This series is based on the RFC patch and subsequent discussion at
> https://patchwork.kernel.org/project/linux-kselftest/patch/[email protected]/
> and offers a more comprehensive solution of the problem discussed there.
> 
> [1] 
> https://lore.kernel.org/all/cagegrw76x8fk_5qqobw_aqbwakqtsc8kxkheuu9ecexzdjw...@mail.gmail.com/
> 
> Changes since RFC:
> - Introduced CONFIG_KUNIT_SUPPRESS_BACKTRACE
> - Minor cleanups and bug fixes
> - Added support for all affected architectures
> - Added support for counting suppressed warnings
> - Added unit tests using those counters
> - Added patch to suppress warning backtraces in dev_addr_lists tests
> 
> Changes since v1:
> - Rebased to v6.9-rc1
> - Added Tested-by:, Acked-by:, and Reviewed-by: tags
>   [I retained those tags since there have been no functional changes]
> - Introduced KUNIT_SUPPRESS_BACKTRACE configuration option, enabled by
>   default.
> 
> Changes since v2:
> - Rebased to v6.9-rc2
> - Added comments to drm warning suppression explaining why it is needed.
> - Added patch to move conditional code in arch/sh/include/asm/bug.h
>   to avoid kerneldoc warning
> - Added architecture maintainers to Cc: for architecture specific patches
> - No functional changes
> 
> Changes since v3:
> - Rebased to v6.14-rc6
> - Dropped net: "kunit: Suppress lock warning noise at end of dev_addr_lists 
> tests"
>   since 3db3b62955cd6d73afde05a17d7e8e106695c3b9
> - Added __kunit_ and KUNIT_ prefixes.
> - Tested on interessed architectures.
> 
> Changes since v4:
> - Rebased to v6.15-rc7
> - Dropped all code in __report_bug()
> - Moved all checks in WARN*() macros.
> - Dropped all architecture specific code.
> - Made __kunit_is_suppressed_warning nice to noinstr functions.
> 
> Changes since v5:
> - Rebased to v7.0-rc3
> - Added RCU protection for the suppressed warnings list.
> - Added static key and branching optimization.
> - Removed custom `strcmp` implementation and reworked
>   __kunit_is_suppressed_warning() entrypoint function.
> 
> Alessandro Carminati (2):
>   bug/kunit: Core support for suppressing warning backtraces
>   bug/kunit: Suppressing warning backtraces reduced impact on WARN*()
>     sites
> 
> Guenter Roeck (3):
>   Add unit tests to verify that warning backtrace suppression works.
>   drm: Suppress intentional warning backtraces in scaling unit tests
>   kunit: Add documentation for warning backtrace suppression API
> 
>  Documentation/dev-tools/kunit/usage.rst |  30 ++++++-
>  drivers/gpu/drm/tests/drm_rect_test.c   |  16 ++++
>  include/asm-generic/bug.h               |  48 +++++++----
>  include/kunit/bug.h                     |  62 ++++++++++++++
>  include/kunit/test.h                    |   1 +
>  lib/kunit/Kconfig                       |   9 ++
>  lib/kunit/Makefile                      |   9 +-
>  lib/kunit/backtrace-suppression-test.c  | 105 ++++++++++++++++++++++++
>  lib/kunit/bug.c                         |  54 ++++++++++++
>  9 files changed, 316 insertions(+), 18 deletions(-)
>  create mode 100644 include/kunit/bug.h
>  create mode 100644 lib/kunit/backtrace-suppression-test.c
>  create mode 100644 lib/kunit/bug.c
> 
> --
> 2.34.1
> 
> ---
> Alessandro Carminati (2):
>       bug/kunit: Core support for suppressing warning backtraces
>       bug/kunit: Suppressing warning backtraces reduced impact on WARN*() 
> sites
> 
> Guenter Roeck (3):
>       Add unit tests to verify that warning backtrace suppression works.
>       drm: Suppress intentional warning backtraces in scaling unit tests
>       kunit: Add documentation for warning backtrace suppression API
> 
>  Documentation/dev-tools/kunit/usage.rst |  30 ++++++++-
>  drivers/gpu/drm/tests/drm_rect_test.c   |  16 +++++
>  include/asm-generic/bug.h               |  44 ++++++++-----
>  include/kunit/bug.h                     |  61 ++++++++++++++++++
>  include/kunit/test.h                    |   1 +
>  lib/kunit/Kconfig                       |   9 +++
>  lib/kunit/Makefile                      |   9 ++-
>  lib/kunit/backtrace-suppression-test.c  | 109 
> ++++++++++++++++++++++++++++++++
>  lib/kunit/bug.c                         |  71 +++++++++++++++++++++
>  9 files changed, 332 insertions(+), 18 deletions(-)
> ---
> base-commit: 80234b5ab240f52fa45d201e899e207b9265ef91
> change-id: 20260312-kunit_add_support-2f35806b19dd
> 
> Best regards,


Reply via email to