File Index
Files and directories
Sign in
FILE

test_ratelimit.c

File preview with syntax highlighting.

linux-6.19.14/lib/tests/test_ratelimit.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2
  3#include <kunit/test.h>
  4
  5#include <linux/ratelimit.h>
  6#include <linux/module.h>
  7#include <linux/kthread.h>
  8#include <linux/cpumask.h>
  9
 10/* a simple boot-time regression test */
 11
 12#define TESTRL_INTERVAL (5 * HZ)
 13static DEFINE_RATELIMIT_STATE(testrl, TESTRL_INTERVAL, 3);
 14
 15#define test_ratelimited(test, expected) \
 16	KUNIT_ASSERT_EQ(test, ___ratelimit(&testrl, "test_ratelimit_smoke"), (expected))
 17
 18static void test_ratelimit_smoke(struct kunit *test)
 19{
 20	// Check settings.
 21	KUNIT_ASSERT_GE(test, TESTRL_INTERVAL, 100);
 22
 23	// Test normal operation.
 24	test_ratelimited(test, true);
 25	test_ratelimited(test, true);
 26	test_ratelimited(test, true);
 27	test_ratelimited(test, false);
 28
 29	schedule_timeout_idle(TESTRL_INTERVAL / 2);
 30	test_ratelimited(test, false);
 31
 32	schedule_timeout_idle(TESTRL_INTERVAL * 3 / 4);
 33	test_ratelimited(test, true);
 34
 35	schedule_timeout_idle(2 * TESTRL_INTERVAL);
 36	test_ratelimited(test, true);
 37	test_ratelimited(test, true);
 38
 39	schedule_timeout_idle(TESTRL_INTERVAL / 2 );
 40	test_ratelimited(test, true);
 41	schedule_timeout_idle(TESTRL_INTERVAL * 3 / 4);
 42	test_ratelimited(test, true);
 43	test_ratelimited(test, true);
 44	test_ratelimited(test, true);
 45	test_ratelimited(test, false);
 46
 47	// Test disabling.
 48	testrl.burst = 0;
 49	test_ratelimited(test, false);
 50	testrl.burst = 2;
 51	testrl.interval = 0;
 52	test_ratelimited(test, true);
 53	test_ratelimited(test, true);
 54	test_ratelimited(test, true);
 55	test_ratelimited(test, true);
 56	test_ratelimited(test, true);
 57	test_ratelimited(test, true);
 58	test_ratelimited(test, true);
 59
 60	// Testing re-enabling.
 61	testrl.interval = TESTRL_INTERVAL;
 62	test_ratelimited(test, true);
 63	test_ratelimited(test, true);
 64	test_ratelimited(test, false);
 65	test_ratelimited(test, false);
 66}
 67
 68static struct ratelimit_state stressrl = RATELIMIT_STATE_INIT_FLAGS("stressrl", HZ / 10, 3,
 69								    RATELIMIT_MSG_ON_RELEASE);
 70
 71static int doneflag;
 72static const int stress_duration = 2 * HZ;
 73
 74struct stress_kthread {
 75	unsigned long nattempts;
 76	unsigned long nunlimited;
 77	unsigned long nlimited;
 78	unsigned long nmissed;
 79	struct task_struct *tp;
 80};
 81
 82static int test_ratelimit_stress_child(void *arg)
 83{
 84	struct stress_kthread *sktp = arg;
 85
 86	set_user_nice(current, MAX_NICE);
 87	WARN_ON_ONCE(!sktp->tp);
 88
 89	while (!READ_ONCE(doneflag)) {
 90		sktp->nattempts++;
 91		if (___ratelimit(&stressrl, __func__))
 92			sktp->nunlimited++;
 93		else
 94			sktp->nlimited++;
 95		cond_resched();
 96	}
 97
 98	sktp->nmissed = ratelimit_state_reset_miss(&stressrl);
 99	return 0;
100}
101
102static void test_ratelimit_stress(struct kunit *test)
103{
104	int i;
105	const int n_stress_kthread = cpumask_weight(cpu_online_mask);
106	struct stress_kthread skt = { 0 };
107	struct stress_kthread *sktp = kcalloc(n_stress_kthread, sizeof(*sktp), GFP_KERNEL);
108
109	KUNIT_EXPECT_NOT_NULL_MSG(test, sktp, "Memory allocation failure");
110	for (i = 0; i < n_stress_kthread; i++) {
111		sktp[i].tp = kthread_run(test_ratelimit_stress_child, &sktp[i], "%s/%i",
112					 "test_ratelimit_stress_child", i);
113		KUNIT_EXPECT_NOT_NULL_MSG(test, sktp, "kthread creation failure");
114		pr_alert("Spawned test_ratelimit_stress_child %d\n", i);
115	}
116	schedule_timeout_idle(stress_duration);
117	WRITE_ONCE(doneflag, 1);
118	for (i = 0; i < n_stress_kthread; i++) {
119		kthread_stop(sktp[i].tp);
120		skt.nattempts += sktp[i].nattempts;
121		skt.nunlimited += sktp[i].nunlimited;
122		skt.nlimited += sktp[i].nlimited;
123		skt.nmissed += sktp[i].nmissed;
124	}
125	KUNIT_ASSERT_EQ_MSG(test, skt.nunlimited + skt.nlimited, skt.nattempts,
126			    "Outcomes not equal to attempts");
127	KUNIT_ASSERT_EQ_MSG(test, skt.nlimited, skt.nmissed, "Misses not equal to limits");
128}
129
130static struct kunit_case ratelimit_test_cases[] = {
131	KUNIT_CASE_SLOW(test_ratelimit_smoke),
132	KUNIT_CASE_SLOW(test_ratelimit_stress),
133	{}
134};
135
136static struct kunit_suite ratelimit_test_suite = {
137	.name = "lib_ratelimit",
138	.test_cases = ratelimit_test_cases,
139};
140
141kunit_test_suites(&ratelimit_test_suite);
142
143MODULE_DESCRIPTION("___ratelimit() KUnit test suite");
144MODULE_LICENSE("GPL");
~/ Read-only file preview.