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 int doneflag; 72 static const int stress_duration = 2 * HZ; 73 74 struct 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 82 static 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 102 static 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 130 static struct kunit_case ratelimit_test_cases[] = { 131 KUNIT_CASE_SLOW(test_ratelimit_smoke), 132 KUNIT_CASE_SLOW(test_ratelimit_stress), 133 {} 134 }; 135 136 static struct kunit_suite ratelimit_test_suite = { 137 .name = "lib_ratelimit", 138 .test_cases = ratelimit_test_cases, 139 }; 140 141 kunit_test_suites(&ratelimit_test_suite); 142 143 MODULE_DESCRIPTION("___ratelimit() KUnit test suite"); 144 MODULE_LICENSE("GPL"); 145