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