1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Referrence tracker self test. |
4 | * |
5 | * Copyright (c) 2021 Eric Dumazet <edumazet@google.com> |
6 | */ |
7 | #include <linux/init.h> |
8 | #include <linux/module.h> |
9 | #include <linux/delay.h> |
10 | #include <linux/ref_tracker.h> |
11 | #include <linux/slab.h> |
12 | #include <linux/timer.h> |
13 | |
14 | static struct ref_tracker_dir ref_dir; |
15 | static struct ref_tracker *tracker[20]; |
16 | |
17 | #define TRT_ALLOC(X) static noinline void \ |
18 | alloctest_ref_tracker_alloc##X(struct ref_tracker_dir *dir, \ |
19 | struct ref_tracker **trackerp) \ |
20 | { \ |
21 | ref_tracker_alloc(dir, trackerp, GFP_KERNEL); \ |
22 | } |
23 | |
24 | TRT_ALLOC(1) |
25 | TRT_ALLOC(2) |
26 | TRT_ALLOC(3) |
27 | TRT_ALLOC(4) |
28 | TRT_ALLOC(5) |
29 | TRT_ALLOC(6) |
30 | TRT_ALLOC(7) |
31 | TRT_ALLOC(8) |
32 | TRT_ALLOC(9) |
33 | TRT_ALLOC(10) |
34 | TRT_ALLOC(11) |
35 | TRT_ALLOC(12) |
36 | TRT_ALLOC(13) |
37 | TRT_ALLOC(14) |
38 | TRT_ALLOC(15) |
39 | TRT_ALLOC(16) |
40 | TRT_ALLOC(17) |
41 | TRT_ALLOC(18) |
42 | TRT_ALLOC(19) |
43 | |
44 | #undef TRT_ALLOC |
45 | |
46 | static noinline void |
47 | alloctest_ref_tracker_free(struct ref_tracker_dir *dir, |
48 | struct ref_tracker **trackerp) |
49 | { |
50 | ref_tracker_free(dir, trackerp); |
51 | } |
52 | |
53 | |
54 | static struct timer_list test_ref_tracker_timer; |
55 | static atomic_t test_ref_timer_done = ATOMIC_INIT(0); |
56 | |
57 | static void test_ref_tracker_timer_func(struct timer_list *t) |
58 | { |
59 | ref_tracker_alloc(dir: &ref_dir, trackerp: &tracker[0], GFP_ATOMIC); |
60 | atomic_set(v: &test_ref_timer_done, i: 1); |
61 | } |
62 | |
63 | static int __init test_ref_tracker_init(void) |
64 | { |
65 | int i; |
66 | |
67 | ref_tracker_dir_init(dir: &ref_dir, quarantine_count: 100, name: "selftest" ); |
68 | |
69 | timer_setup(&test_ref_tracker_timer, test_ref_tracker_timer_func, 0); |
70 | mod_timer(timer: &test_ref_tracker_timer, expires: jiffies + 1); |
71 | |
72 | alloctest_ref_tracker_alloc1(dir: &ref_dir, trackerp: &tracker[1]); |
73 | alloctest_ref_tracker_alloc2(dir: &ref_dir, trackerp: &tracker[2]); |
74 | alloctest_ref_tracker_alloc3(dir: &ref_dir, trackerp: &tracker[3]); |
75 | alloctest_ref_tracker_alloc4(dir: &ref_dir, trackerp: &tracker[4]); |
76 | alloctest_ref_tracker_alloc5(dir: &ref_dir, trackerp: &tracker[5]); |
77 | alloctest_ref_tracker_alloc6(dir: &ref_dir, trackerp: &tracker[6]); |
78 | alloctest_ref_tracker_alloc7(dir: &ref_dir, trackerp: &tracker[7]); |
79 | alloctest_ref_tracker_alloc8(dir: &ref_dir, trackerp: &tracker[8]); |
80 | alloctest_ref_tracker_alloc9(dir: &ref_dir, trackerp: &tracker[9]); |
81 | alloctest_ref_tracker_alloc10(dir: &ref_dir, trackerp: &tracker[10]); |
82 | alloctest_ref_tracker_alloc11(dir: &ref_dir, trackerp: &tracker[11]); |
83 | alloctest_ref_tracker_alloc12(dir: &ref_dir, trackerp: &tracker[12]); |
84 | alloctest_ref_tracker_alloc13(dir: &ref_dir, trackerp: &tracker[13]); |
85 | alloctest_ref_tracker_alloc14(dir: &ref_dir, trackerp: &tracker[14]); |
86 | alloctest_ref_tracker_alloc15(dir: &ref_dir, trackerp: &tracker[15]); |
87 | alloctest_ref_tracker_alloc16(dir: &ref_dir, trackerp: &tracker[16]); |
88 | alloctest_ref_tracker_alloc17(dir: &ref_dir, trackerp: &tracker[17]); |
89 | alloctest_ref_tracker_alloc18(dir: &ref_dir, trackerp: &tracker[18]); |
90 | alloctest_ref_tracker_alloc19(dir: &ref_dir, trackerp: &tracker[19]); |
91 | |
92 | /* free all trackers but first 0 and 1. */ |
93 | for (i = 2; i < ARRAY_SIZE(tracker); i++) |
94 | alloctest_ref_tracker_free(dir: &ref_dir, trackerp: &tracker[i]); |
95 | |
96 | /* Attempt to free an already freed tracker. */ |
97 | alloctest_ref_tracker_free(dir: &ref_dir, trackerp: &tracker[2]); |
98 | |
99 | while (!atomic_read(v: &test_ref_timer_done)) |
100 | msleep(msecs: 1); |
101 | |
102 | /* This should warn about tracker[0] & tracker[1] being not freed. */ |
103 | ref_tracker_dir_exit(dir: &ref_dir); |
104 | |
105 | return 0; |
106 | } |
107 | |
108 | static void __exit test_ref_tracker_exit(void) |
109 | { |
110 | } |
111 | |
112 | module_init(test_ref_tracker_init); |
113 | module_exit(test_ref_tracker_exit); |
114 | |
115 | MODULE_LICENSE("GPL v2" ); |
116 | |