Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'ratelimit.2025.07.23a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu

Pull ratelimit test updates from Paul McKenney:
"Add functional and stress tests:

- Add trivial kunit test for ratelimit

- Make the ratelimit test more reliable (Petr Mladek)

- Add stress test for ratelimit"

* tag 'ratelimit.2025.07.23a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu:
lib: Add stress test for ratelimit
lib: Make the ratelimit test more reliable
lib: Add trivial kunit test for ratelimit

+156
+11
lib/Kconfig.debug
··· 3214 3214 3215 3215 If unsure, say N. 3216 3216 3217 + config RATELIMIT_KUNIT_TEST 3218 + tristate "KUnit Test for correctness and stress of ratelimit" if !KUNIT_ALL_TESTS 3219 + depends on KUNIT 3220 + default KUNIT_ALL_TESTS 3221 + help 3222 + This builds the "test_ratelimit" module that should be used 3223 + for correctness verification and concurrent testings of rate 3224 + limiting. 3225 + 3226 + If unsure, say N. 3227 + 3217 3228 config INT_POW_KUNIT_TEST 3218 3229 tristate "Integer exponentiation (int_pow) test" if !KUNIT_ALL_TESTS 3219 3230 depends on KUNIT
+1
lib/tests/Makefile
··· 46 46 obj-$(CONFIG_STRING_HELPERS_KUNIT_TEST) += string_helpers_kunit.o 47 47 obj-$(CONFIG_USERCOPY_KUNIT_TEST) += usercopy_kunit.o 48 48 obj-$(CONFIG_UTIL_MACROS_KUNIT) += util_macros_kunit.o 49 + obj-$(CONFIG_RATELIMIT_KUNIT_TEST) += test_ratelimit.o 49 50 50 51 obj-$(CONFIG_TEST_RUNTIME_MODULE) += module/
+144
lib/tests/test_ratelimit.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) 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");