From: Albert Esteve <aesteve@redhat.com>
To: Arnd Bergmann <arnd@arndb.de>,
Brendan Higgins <brendan.higgins@linux.dev>,
David Gow <david@davidgow.net>, Rae Moar <raemoar63@gmail.com>,
Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Maxime Ripard <mripard@kernel.org>,
Thomas Zimmermann <tzimmermann@suse.de>,
David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>,
Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
Andrew Morton <akpm@linux-foundation.org>,
Paul Walmsley <pjw@kernel.org>,
Palmer Dabbelt <palmer@dabbelt.com>,
Albert Ou <aou@eecs.berkeley.edu>,
Alexandre Ghiti <alex@ghiti.fr>
Cc: linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org,
linux-kselftest@vger.kernel.org, kunit-dev@googlegroups.com,
dri-devel@lists.freedesktop.org, workflows@vger.kernel.org,
linux-riscv@lists.infradead.org, linux-doc@vger.kernel.org,
peterz@infradead.org, Guenter Roeck <linux@roeck-us.net>,
Linux Kernel Functional Testing <lkft@linaro.org>,
Alessandro Carminati <acarmina@redhat.com>,
Dan Carpenter <error27@gmail.com>, Kees Cook <kees@kernel.org>
Subject: Re: [PATCH v13 2/4] kunit: Add backtrace suppression self-tests
Date: Fri, 15 May 2026 16:14:07 +0200 [thread overview]
Message-ID: <CADSE00LZD0+TMxkCgH5YEwjdPggx8X5ZrHEFx_ku0wBSjS_Oyw@mail.gmail.com> (raw)
In-Reply-To: <20260515-kunit_add_support-v13-2-18ee42f96e7b@redhat.com>
On Fri, May 15, 2026 at 2:30 PM Albert Esteve <aesteve@redhat.com> wrote:
>
> From: Guenter Roeck <linux@roeck-us.net>
>
> Add unit tests to verify that warning backtrace suppression works.
>
> Tests cover both API forms:
> - Scoped: kunit_warning_suppress() with in-block count verification
> and post-block inactivity check.
> - Direct functions: kunit_start/end_suppress_warning() with
> sequential independent suppression blocks and per-block counts.
>
> Furthermore, tests verify incremental warning counting, that
> kunit_has_active_suppress_warning() transitions correctly around
> suppression boundaries, and that suppression active in the test
> kthread does not leak to a separate kthread.
>
> If backtrace suppression does _not_ work, the unit tests will likely
> trigger unsuppressed backtraces, which should actually help to get
> the affected architectures / platforms fixed.
>
Another set of sashiko comments for this patch
https://sashiko.dev/#/patchset/20260515-kunit_add_support-v13-0-18ee42f96e7b%40redhat.com?part=2
here:
1. CPU spike from while (!kthread_should_stop()) schedule()
Ha! I expected this one because I saw it in a previous review from the
bot. schedule() from TASK_RUNNING yields the CPU; it does not
spin-wait. The thread is rescheduled only when the scheduler gives it
time, not in a tight loop. But the important thing is that the window
where this loop actually runs is negligible: the parent calls
kthread_stop() immediately after wait_for_completion() returns. Using
set_current_state(TASK_INTERRUPTIBLE) would be slightly more
CPU-friendly, but for a test that probably runs and exits in
microseconds, it makes no practical difference. And it unnecessarily
adds complexity.
2. Orphaned kthread on early abort
This cannot happen in this test. The only KUNIT_ASSERT_* that could
abort early is KUNIT_ASSERT_FALSE(test, IS_ERR(task)). If that
assertion fails, it means kthread_run() itself returned an error,
therefore, the kthread was never started and there is nothing to
orphan. If kthread_run() succeeds, the assertion passes, and execution
continues sequentially to kthread_stop(). No code path allows a live
kthread to exist while bypassing kthread_stop().
> Tested-by: Linux Kernel Functional Testing <lkft@linaro.org>
> Acked-by: Dan Carpenter <dan.carpenter@linaro.org>
> Reviewed-by: Kees Cook <keescook@chromium.org>
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
> Signed-off-by: Alessandro Carminati <acarmina@redhat.com>
> Reviewed-by: David Gow <david@davidgow.net>
> Signed-off-by: Albert Esteve <aesteve@redhat.com>
> ---
> lib/kunit/Makefile | 1 +
> lib/kunit/backtrace-suppression-test.c | 192 +++++++++++++++++++++++++++++++++
> 2 files changed, 193 insertions(+)
>
> diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
> index 4592f9d0aa8dd..2e8a6b71a2ab0 100644
> --- a/lib/kunit/Makefile
> +++ b/lib/kunit/Makefile
> @@ -22,6 +22,7 @@ obj-$(if $(CONFIG_KUNIT),y) += hooks.o
>
> obj-$(CONFIG_KUNIT_TEST) += kunit-test.o
> obj-$(CONFIG_KUNIT_TEST) += platform-test.o
> +obj-$(CONFIG_KUNIT_TEST) += backtrace-suppression-test.o
>
> # string-stream-test compiles built-in only.
> ifeq ($(CONFIG_KUNIT_TEST),y)
> diff --git a/lib/kunit/backtrace-suppression-test.c b/lib/kunit/backtrace-suppression-test.c
> new file mode 100644
> index 0000000000000..59a038b2739f5
> --- /dev/null
> +++ b/lib/kunit/backtrace-suppression-test.c
> @@ -0,0 +1,192 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * KUnit test for suppressing warning tracebacks.
> + *
> + * Copyright (C) 2024, Guenter Roeck
> + * Author: Guenter Roeck <linux@roeck-us.net>
> + */
> +
> +#include <kunit/test.h>
> +#include <linux/bug.h>
> +#include <linux/completion.h>
> +#include <linux/kthread.h>
> +
> +static void backtrace_suppression_test_warn_direct(struct kunit *test)
> +{
> + if (!IS_ENABLED(CONFIG_BUG))
> + kunit_skip(test, "requires CONFIG_BUG");
> +
> + kunit_warning_suppress(test) {
> + WARN(1, "This backtrace should be suppressed");
> + /*
> + * Count must be checked inside the scope; the handle
> + * is not accessible after the block exits.
> + */
> + KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1);
> + }
> + KUNIT_EXPECT_FALSE(test, kunit_has_active_suppress_warning());
> +}
> +
> +static noinline void trigger_backtrace_warn(void)
> +{
> + WARN(1, "This backtrace should be suppressed");
> +}
> +
> +static void backtrace_suppression_test_warn_indirect(struct kunit *test)
> +{
> + if (!IS_ENABLED(CONFIG_BUG))
> + kunit_skip(test, "requires CONFIG_BUG");
> +
> + kunit_warning_suppress(test) {
> + trigger_backtrace_warn();
> + KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1);
> + }
> +}
> +
> +static void backtrace_suppression_test_warn_multi(struct kunit *test)
> +{
> + if (!IS_ENABLED(CONFIG_BUG))
> + kunit_skip(test, "requires CONFIG_BUG");
> +
> + kunit_warning_suppress(test) {
> + WARN(1, "This backtrace should be suppressed");
> + trigger_backtrace_warn();
> + KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 2);
> + }
> +}
> +
> +static void backtrace_suppression_test_warn_on_direct(struct kunit *test)
> +{
> + if (!IS_ENABLED(CONFIG_BUG))
> + kunit_skip(test, "requires CONFIG_BUG");
> +
> + kunit_warning_suppress(test) {
> + WARN_ON(1);
> + KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1);
> + }
> +}
> +
> +static noinline void trigger_backtrace_warn_on(void)
> +{
> + WARN_ON(1);
> +}
> +
> +static void backtrace_suppression_test_warn_on_indirect(struct kunit *test)
> +{
> + if (!IS_ENABLED(CONFIG_BUG))
> + kunit_skip(test, "requires CONFIG_BUG");
> +
> + kunit_warning_suppress(test) {
> + trigger_backtrace_warn_on();
> + KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1);
> + }
> +}
> +
> +static void backtrace_suppression_test_count(struct kunit *test)
> +{
> + if (!IS_ENABLED(CONFIG_BUG))
> + kunit_skip(test, "requires CONFIG_BUG");
> +
> + kunit_warning_suppress(test) {
> + KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 0);
> +
> + WARN(1, "suppressed");
> + KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 1);
> +
> + WARN(1, "suppressed again");
> + KUNIT_EXPECT_SUPPRESSED_WARNING_COUNT(test, 2);
> + }
> +}
> +
> +static void backtrace_suppression_test_active_state(struct kunit *test)
> +{
> + KUNIT_EXPECT_FALSE(test, kunit_has_active_suppress_warning());
> +
> + kunit_warning_suppress(test) {
> + KUNIT_EXPECT_TRUE(test, kunit_has_active_suppress_warning());
> + }
> +
> + KUNIT_EXPECT_FALSE(test, kunit_has_active_suppress_warning());
> +
> + kunit_warning_suppress(test) {
> + KUNIT_EXPECT_TRUE(test, kunit_has_active_suppress_warning());
> + }
> +
> + KUNIT_EXPECT_FALSE(test, kunit_has_active_suppress_warning());
> +}
> +
> +static void backtrace_suppression_test_multi_scope(struct kunit *test)
> +{
> + struct kunit_suppressed_warning *sw1, *sw2;
> +
> + if (!IS_ENABLED(CONFIG_BUG))
> + kunit_skip(test, "requires CONFIG_BUG");
> +
> + sw1 = kunit_start_suppress_warning(test);
> + trigger_backtrace_warn_on();
> + WARN(1, "suppressed by sw1");
> + kunit_end_suppress_warning(test, sw1);
> +
> + sw2 = kunit_start_suppress_warning(test);
> + WARN(1, "suppressed by sw2");
> + kunit_end_suppress_warning(test, sw2);
> +
> + KUNIT_EXPECT_EQ(test, kunit_suppressed_warning_count(sw1), 2);
> + KUNIT_EXPECT_EQ(test, kunit_suppressed_warning_count(sw2), 1);
> +}
> +
> +struct cross_kthread_data {
> + bool was_active;
> + struct completion done;
> +};
> +
> +static int cross_kthread_fn(void *data)
> +{
> + struct cross_kthread_data *d = data;
> +
> + d->was_active = kunit_has_active_suppress_warning();
> + complete(&d->done);
> + while (!kthread_should_stop())
> + schedule();
> + return 0;
> +}
> +
> +static void backtrace_suppression_test_cross_kthread(struct kunit *test)
> +{
> + struct cross_kthread_data data;
> + struct task_struct *task;
> +
> + data.was_active = false;
> + init_completion(&data.done);
> +
> + kunit_warning_suppress(test) {
> + task = kthread_run(cross_kthread_fn, &data, "kunit-cross-test");
> + KUNIT_ASSERT_FALSE(test, IS_ERR(task));
> + wait_for_completion(&data.done);
> + kthread_stop(task);
> + }
> +
> + KUNIT_EXPECT_FALSE(test, data.was_active);
> +}
> +
> +static struct kunit_case backtrace_suppression_test_cases[] = {
> + KUNIT_CASE(backtrace_suppression_test_warn_direct),
> + KUNIT_CASE(backtrace_suppression_test_warn_indirect),
> + KUNIT_CASE(backtrace_suppression_test_warn_multi),
> + KUNIT_CASE(backtrace_suppression_test_warn_on_direct),
> + KUNIT_CASE(backtrace_suppression_test_warn_on_indirect),
> + KUNIT_CASE(backtrace_suppression_test_count),
> + KUNIT_CASE(backtrace_suppression_test_active_state),
> + KUNIT_CASE(backtrace_suppression_test_multi_scope),
> + KUNIT_CASE(backtrace_suppression_test_cross_kthread),
> + {}
> +};
> +
> +static struct kunit_suite backtrace_suppression_test_suite = {
> + .name = "backtrace-suppression-test",
> + .test_cases = backtrace_suppression_test_cases,
> +};
> +kunit_test_suites(&backtrace_suppression_test_suite);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("KUnit test to verify warning backtrace suppression");
>
> --
> 2.53.0
>
next prev parent reply other threads:[~2026-05-15 14:14 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-15 12:29 [PATCH v13 0/4] kunit: Add support for suppressing warning backtraces Albert Esteve
2026-05-15 12:29 ` [PATCH v13 1/4] bug/kunit: Core " Albert Esteve
2026-05-15 13:36 ` Albert Esteve
2026-05-15 23:18 ` Claude review: " Claude Code Review Bot
2026-05-15 12:29 ` [PATCH v13 2/4] kunit: Add backtrace suppression self-tests Albert Esteve
2026-05-15 14:14 ` Albert Esteve [this message]
2026-05-15 23:18 ` Claude review: " Claude Code Review Bot
2026-05-15 12:29 ` [PATCH v13 3/4] drm: Suppress intentional warning backtraces in scaling unit tests Albert Esteve
2026-05-15 23:18 ` Claude review: " Claude Code Review Bot
2026-05-15 12:29 ` [PATCH v13 4/4] kunit: Add documentation for warning backtrace suppression API Albert Esteve
2026-05-15 23:18 ` Claude review: " Claude Code Review Bot
2026-05-15 13:51 ` [PATCH v13 0/4] kunit: Add support for suppressing warning backtraces Guenter Roeck
2026-05-15 14:25 ` Albert Esteve
2026-05-15 23:18 ` Claude review: " Claude Code Review Bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CADSE00LZD0+TMxkCgH5YEwjdPggx8X5ZrHEFx_ku0wBSjS_Oyw@mail.gmail.com \
--to=aesteve@redhat.com \
--cc=acarmina@redhat.com \
--cc=airlied@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=alex@ghiti.fr \
--cc=aou@eecs.berkeley.edu \
--cc=arnd@arndb.de \
--cc=brendan.higgins@linux.dev \
--cc=corbet@lwn.net \
--cc=david@davidgow.net \
--cc=dri-devel@lists.freedesktop.org \
--cc=error27@gmail.com \
--cc=kees@kernel.org \
--cc=kunit-dev@googlegroups.com \
--cc=linux-arch@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=linux@roeck-us.net \
--cc=lkft@linaro.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=palmer@dabbelt.com \
--cc=peterz@infradead.org \
--cc=pjw@kernel.org \
--cc=raemoar63@gmail.com \
--cc=simona@ffwll.ch \
--cc=skhan@linuxfoundation.org \
--cc=tzimmermann@suse.de \
--cc=workflows@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox