xref: /linux/lib/tests/test_ratelimit.c (revision 1b78070aaef63512688aebfbc82365ef9d6660f1)
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)
13 static 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 
18 static 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 
68 static struct ratelimit_state stressrl = RATELIMIT_STATE_INIT_FLAGS("stressrl", HZ / 10, 3,
69 								    RATELIMIT_MSG_ON_RELEASE);
70 
71 static const int stress_duration = 2 * HZ;
72 
73 struct stress_kthread {
74 	unsigned long nattempts;
75 	unsigned long nunlimited;
76 	unsigned long nlimited;
77 	unsigned long nmissed;
78 	struct task_struct *tp;
79 };
80 
81 static int test_ratelimit_stress_child(void *arg)
82 {
83 	struct stress_kthread *sktp = arg;
84 
85 	set_user_nice(current, MAX_NICE);
86 
87 	while (!kthread_should_stop()) {
88 		sktp->nattempts++;
89 		if (___ratelimit(&stressrl, __func__))
90 			sktp->nunlimited++;
91 		else
92 			sktp->nlimited++;
93 		cond_resched();
94 	}
95 
96 	sktp->nmissed = ratelimit_state_reset_miss(&stressrl);
97 	return 0;
98 }
99 
100 static void test_ratelimit_stress(struct kunit *test)
101 {
102 	int i;
103 	const int n_stress_kthread = cpumask_weight(cpu_online_mask);
104 	struct stress_kthread skt = { 0 };
105 	struct stress_kthread *sktp = kzalloc_objs(*sktp, n_stress_kthread);
106 	int n_started = 0;
107 
108 	KUNIT_ASSERT_NOT_NULL_MSG(test, sktp, "Memory allocation failure");
109 	for (i = 0; i < n_stress_kthread; i++) {
110 		sktp[i].tp = kthread_run(test_ratelimit_stress_child, &sktp[i], "%s/%i",
111 					 "test_ratelimit_stress_child", i);
112 		if (IS_ERR(sktp[i].tp)) {
113 			KUNIT_FAIL(test, "kthread_run failed: %ld", PTR_ERR(sktp[i].tp));
114 			goto out_stop;
115 		}
116 		n_started++;
117 		pr_alert("Spawned test_ratelimit_stress_child %d\n", i);
118 	}
119 	schedule_timeout_idle(stress_duration);
120 
121 out_stop:
122 	for (i = 0; i < n_started; i++) {
123 		kthread_stop(sktp[i].tp);
124 		skt.nattempts += sktp[i].nattempts;
125 		skt.nunlimited += sktp[i].nunlimited;
126 		skt.nlimited += sktp[i].nlimited;
127 		skt.nmissed += sktp[i].nmissed;
128 	}
129 	if (n_started == n_stress_kthread) {
130 		KUNIT_ASSERT_EQ_MSG(test, skt.nunlimited + skt.nlimited, skt.nattempts,
131 				    "Outcomes not equal to attempts");
132 		KUNIT_ASSERT_EQ_MSG(test, skt.nlimited, skt.nmissed,
133 				    "Misses not equal to limits");
134 	}
135 
136 	kfree(sktp);
137 }
138 
139 static struct kunit_case ratelimit_test_cases[] = {
140 	KUNIT_CASE_SLOW(test_ratelimit_smoke),
141 	KUNIT_CASE_SLOW(test_ratelimit_stress),
142 	{}
143 };
144 
145 static struct kunit_suite ratelimit_test_suite = {
146 	.name = "lib_ratelimit",
147 	.test_cases = ratelimit_test_cases,
148 };
149 
150 kunit_test_suites(&ratelimit_test_suite);
151 
152 MODULE_DESCRIPTION("___ratelimit() KUnit test suite");
153 MODULE_LICENSE("GPL");
154