1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright (C) 2018 Joe Lawrence <joe.lawrence@redhat.com> |
3 | |
4 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
5 | |
6 | #include <linux/module.h> |
7 | #include <linux/kernel.h> |
8 | #include <linux/sched.h> |
9 | #include <linux/workqueue.h> |
10 | #include <linux/delay.h> |
11 | |
12 | /* load/run-time control from sysfs writer */ |
13 | static bool block_transition; |
14 | module_param(block_transition, bool, 0644); |
15 | MODULE_PARM_DESC(block_transition, "block_transition (default=false)" ); |
16 | |
17 | static void busymod_work_func(struct work_struct *work); |
18 | static DECLARE_WORK(work, busymod_work_func); |
19 | static DECLARE_COMPLETION(busymod_work_started); |
20 | |
21 | static void busymod_work_func(struct work_struct *work) |
22 | { |
23 | pr_info("%s enter\n" , __func__); |
24 | complete(&busymod_work_started); |
25 | |
26 | while (READ_ONCE(block_transition)) { |
27 | /* |
28 | * Busy-wait until the sysfs writer has acknowledged a |
29 | * blocked transition and clears the flag. |
30 | */ |
31 | msleep(msecs: 20); |
32 | } |
33 | |
34 | pr_info("%s exit\n" , __func__); |
35 | } |
36 | |
37 | static int test_klp_callbacks_busy_init(void) |
38 | { |
39 | pr_info("%s\n" , __func__); |
40 | schedule_work(work: &work); |
41 | |
42 | /* |
43 | * To synchronize kernel messages, hold the init function from |
44 | * exiting until the work function's entry message has printed. |
45 | */ |
46 | wait_for_completion(&busymod_work_started); |
47 | |
48 | if (!block_transition) { |
49 | /* |
50 | * Serialize output: print all messages from the work |
51 | * function before returning from init(). |
52 | */ |
53 | flush_work(work: &work); |
54 | } |
55 | |
56 | return 0; |
57 | } |
58 | |
59 | static void test_klp_callbacks_busy_exit(void) |
60 | { |
61 | WRITE_ONCE(block_transition, false); |
62 | flush_work(work: &work); |
63 | pr_info("%s\n" , __func__); |
64 | } |
65 | |
66 | module_init(test_klp_callbacks_busy_init); |
67 | module_exit(test_klp_callbacks_busy_exit); |
68 | MODULE_LICENSE("GPL" ); |
69 | MODULE_AUTHOR("Joe Lawrence <joe.lawrence@redhat.com>" ); |
70 | MODULE_DESCRIPTION("Livepatch test: busy target module" ); |
71 | |