.. | .. |
---|
3 | 3 | #include <linux/spinlock.h> |
---|
4 | 4 | #include <linux/once.h> |
---|
5 | 5 | #include <linux/random.h> |
---|
6 | | -#include <linux/module.h> |
---|
7 | 6 | |
---|
8 | 7 | struct once_work { |
---|
9 | 8 | struct work_struct work; |
---|
10 | 9 | struct static_key_true *key; |
---|
11 | | - struct module *module; |
---|
12 | 10 | }; |
---|
13 | 11 | |
---|
14 | 12 | static void once_deferred(struct work_struct *w) |
---|
.. | .. |
---|
18 | 16 | work = container_of(w, struct once_work, work); |
---|
19 | 17 | BUG_ON(!static_key_enabled(work->key)); |
---|
20 | 18 | static_branch_disable(work->key); |
---|
21 | | - module_put(work->module); |
---|
22 | 19 | kfree(work); |
---|
23 | 20 | } |
---|
24 | 21 | |
---|
25 | | -static void once_disable_jump(struct static_key_true *key, struct module *mod) |
---|
| 22 | +static void once_disable_jump(struct static_key_true *key) |
---|
26 | 23 | { |
---|
27 | 24 | struct once_work *w; |
---|
28 | 25 | |
---|
.. | .. |
---|
32 | 29 | |
---|
33 | 30 | INIT_WORK(&w->work, once_deferred); |
---|
34 | 31 | w->key = key; |
---|
35 | | - w->module = mod; |
---|
36 | | - __module_get(mod); |
---|
37 | 32 | schedule_work(&w->work); |
---|
38 | 33 | } |
---|
39 | 34 | |
---|
.. | .. |
---|
58 | 53 | EXPORT_SYMBOL(__do_once_start); |
---|
59 | 54 | |
---|
60 | 55 | void __do_once_done(bool *done, struct static_key_true *once_key, |
---|
61 | | - unsigned long *flags, struct module *mod) |
---|
| 56 | + unsigned long *flags) |
---|
62 | 57 | __releases(once_lock) |
---|
63 | 58 | { |
---|
64 | 59 | *done = true; |
---|
65 | 60 | spin_unlock_irqrestore(&once_lock, *flags); |
---|
66 | | - once_disable_jump(once_key, mod); |
---|
| 61 | + once_disable_jump(once_key); |
---|
67 | 62 | } |
---|
68 | 63 | EXPORT_SYMBOL(__do_once_done); |
---|
| 64 | + |
---|
| 65 | +static DEFINE_MUTEX(once_mutex); |
---|
| 66 | + |
---|
| 67 | +bool __do_once_slow_start(bool *done) |
---|
| 68 | + __acquires(once_mutex) |
---|
| 69 | +{ |
---|
| 70 | + mutex_lock(&once_mutex); |
---|
| 71 | + if (*done) { |
---|
| 72 | + mutex_unlock(&once_mutex); |
---|
| 73 | + /* Keep sparse happy by restoring an even lock count on |
---|
| 74 | + * this mutex. In case we return here, we don't call into |
---|
| 75 | + * __do_once_done but return early in the DO_ONCE_SLOW() macro. |
---|
| 76 | + */ |
---|
| 77 | + __acquire(once_mutex); |
---|
| 78 | + return false; |
---|
| 79 | + } |
---|
| 80 | + |
---|
| 81 | + return true; |
---|
| 82 | +} |
---|
| 83 | +EXPORT_SYMBOL(__do_once_slow_start); |
---|
| 84 | + |
---|
| 85 | +void __do_once_slow_done(bool *done, struct static_key_true *once_key, |
---|
| 86 | + struct module *mod) |
---|
| 87 | + __releases(once_mutex) |
---|
| 88 | +{ |
---|
| 89 | + *done = true; |
---|
| 90 | + mutex_unlock(&once_mutex); |
---|
| 91 | + once_disable_jump(once_key); |
---|
| 92 | +} |
---|
| 93 | +EXPORT_SYMBOL(__do_once_slow_done); |
---|