Jia He
unread,May 14, 2026, 1:08:25 AM (7 days ago) May 14Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to linux-...@vger.kernel.org, linux-...@vger.kernel.org, linux-pe...@vger.kernel.org, linux-k...@vger.kernel.org, kuni...@googlegroups.com, kasa...@googlegroups.com, linu...@kvack.org, Arnd Bergmann, Greg Kroah-Hartman, Alexander Viro, Christian Brauner, Jan Kara, Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter, James Clark, Brendan Higgins, David Gow, Rae Moar, Alexander Potapenko, Marco Elver, Dmitry Vyukov, Andrew Morton, Jia He, Paul E. McKenney, Petr Mladek, Kees Cook, David Disseldorp
The kthread return value was checked against the wrong variable (sktp
instead of sktp[i].tp), so WARN_ON_ONCE(!sktp->tp) fired at line 87.
Replace kthread_run() with kthread_create()+wake_up_process() so the
return value can be validated before assigning to sktp[i].tp. On
creation failure, jump to a common cleanup path that signals doneflag,
stops all already-started threads, and frees sktp. This avoids leaving
orphan kthreads and leaked memory when a mid-loop failure occurs.
Also reset doneflag before spawning threads so back-to-back test
invocations don't race on stale state.
To: "Paul E. McKenney" <
pau...@kernel.org>
To: Petr Mladek <
pml...@suse.com>
To: Kees Cook <
ke...@kernel.org>
lib/tests/test_ratelimit.c | 34 ++++++++++++++++++++++++++--------
1 file changed, 26 insertions(+), 8 deletions(-)
diff --git a/lib/tests/test_ratelimit.c b/lib/tests/test_ratelimit.c
index 33cea5f3d28b..64f26260c0d8 100644
--- a/lib/tests/test_ratelimit.c
+++ b/lib/tests/test_ratelimit.c
@@ -105,26 +105,44 @@ static void test_ratelimit_stress(struct kunit *test)
const int n_stress_kthread = cpumask_weight(cpu_online_mask);
struct stress_kthread skt = { 0 };
struct stress_kthread *sktp = kzalloc_objs(*sktp, n_stress_kthread);
+ int n_started = 0;
- KUNIT_EXPECT_NOT_NULL_MSG(test, sktp, "Memory allocation failure");
+ KUNIT_ASSERT_NOT_NULL_MSG(test, sktp, "Memory allocation failure");
+ WRITE_ONCE(doneflag, 0);
for (i = 0; i < n_stress_kthread; i++) {
- sktp[i].tp = kthread_run(test_ratelimit_stress_child, &sktp[i], "%s/%i",
- "test_ratelimit_stress_child", i);
- KUNIT_EXPECT_NOT_NULL_MSG(test, sktp, "kthread creation failure");
+ struct task_struct *tp;
+
+ tp = kthread_create(test_ratelimit_stress_child, &sktp[i],
+ "%s/%i", "test_ratelimit_stress_child", i);
+ if (IS_ERR(tp)) {
+ KUNIT_FAIL(test, "kthread_create failed: %ld", PTR_ERR(tp));
+ goto out_stop;
+ }
+
+ sktp[i].tp = tp;
+ wake_up_process(tp);
+ n_started++;
pr_alert("Spawned test_ratelimit_stress_child %d\n", i);
}
schedule_timeout_idle(stress_duration);
+
+out_stop:
WRITE_ONCE(doneflag, 1);
- for (i = 0; i < n_stress_kthread; i++) {
+ for (i = 0; i < n_started; i++) {
kthread_stop(sktp[i].tp);
skt.nattempts += sktp[i].nattempts;
skt.nunlimited += sktp[i].nunlimited;
skt.nlimited += sktp[i].nlimited;
skt.nmissed += sktp[i].nmissed;
}
- KUNIT_ASSERT_EQ_MSG(test, skt.nunlimited + skt.nlimited, skt.nattempts,
- "Outcomes not equal to attempts");
- KUNIT_ASSERT_EQ_MSG(test, skt.nlimited, skt.nmissed, "Misses not equal to limits");
+ if (n_started == n_stress_kthread) {
+ KUNIT_ASSERT_EQ_MSG(test, skt.nunlimited + skt.nlimited, skt.nattempts,
+ "Outcomes not equal to attempts");
+ KUNIT_ASSERT_EQ_MSG(test, skt.nlimited, skt.nmissed,
+ "Misses not equal to limits");
+ }
+
+ kfree(sktp);
}
static struct kunit_case ratelimit_test_cases[] = {
--
2.34.1