When kmod_dup_request_announce() announces the completion of a request_module() call to duplicate waiters, it queues a work item to invoke kmod_dup_request_complete(), and only that function calls complete_all(). This adds an arbitrary delay that is unnecessary and provides little benefit. Call complete_all() directly from kmod_dup_request_announce() instead.
Showing the changes to kernel/module (1 of 1 file). Show all
Unified · Split
| @@ -48,7 +48,6 @@ struct kmod_dup_req { · 47 unmodified lines | ||
| 48 | 48 | struct list_head list; |
| 49 | 49 | char name[MODULE_NAME_LEN]; |
| 50 | 50 | struct completion first_req_done; |
| 51 | − struct work_struct complete_work; | |
| 52 | 51 | struct delayed_work delete_work; |
| 53 | 52 | int dup_ret; |
| 54 | 53 | }; |
| @@ -93,29 +92,6 @@ static void kmod_dup_request_delete(struct work_struct *work) · 38 unmodified lines | ||
| 93 | 92 | kfree(kmod_req); |
| 94 | 93 | } |
| 95 | 94 | |
| 96 | −static void kmod_dup_request_complete(struct work_struct *work) | |
| 97 | −{ | |
| 98 | − struct kmod_dup_req *kmod_req; | |
| 99 | − | |
| 100 | − kmod_req = container_of(work, struct kmod_dup_req, complete_work); | |
| 101 | − | |
| 102 | − /* | |
| 103 | − * This will ensure that the kernel will let all the waiters get | |
| 104 | − * informed its time to check the return value. It's time to | |
| 105 | − * go home. | |
| 106 | − */ | |
| 107 | − complete_all(&kmod_req->first_req_done); | |
| 108 | − | |
| 109 | − /* | |
| 110 | − * Now that we have allowed prior request_module() calls to go on | |
| 111 | − * with life, let's schedule deleting this entry. We don't have | |
| 112 | − * to do it right away, but we *eventually* want to do it so to not | |
| 113 | − * let this linger forever as this is just a boot optimization for | |
| 114 | − * possible abuses of vmalloc() incurred by finit_module() thrashing. | |
| 115 | − */ | |
| 116 | − queue_delayed_work(system_dfl_wq, &kmod_req->delete_work, 60 * HZ); | |
| 117 | −} | |
| 118 | − | |
| 119 | 95 | bool kmod_dup_request_exists_wait(char *module_name, bool wait, int *dup_ret) |
| 120 | 96 | { |
| 121 | 97 | struct kmod_dup_req *kmod_req, *new_kmod_req; |
| @@ -130,7 +106,6 @@ bool kmod_dup_request_exists_wait(char *module_name, bool wait, int *dup_ret) · 8 unmodified lines | ||
| 130 | 106 | return false; |
| 131 | 107 | |
| 132 | 108 | strscpy(new_kmod_req->name, module_name); |
| 133 | − INIT_WORK(&new_kmod_req->complete_work, kmod_dup_request_complete); | |
| 134 | 109 | INIT_DELAYED_WORK(&new_kmod_req->delete_work, kmod_dup_request_delete); |
| 135 | 110 | init_completion(&new_kmod_req->first_req_done); |
| 136 | 111 | |
| @@ -230,17 +205,17 @@ void kmod_dup_request_announce(char *module_name, int ret) · 93 unmodified lines | ||
| 230 | 205 | |
| 231 | 206 | kmod_req->dup_ret = ret; |
| 232 | 207 | |
| 208 | + /* Inform all duplicate waiters to check the return value. */ | |
| 209 | + complete_all(&kmod_req->first_req_done); | |
| 210 | + | |
| 233 | 211 | /* |
| 234 | − * If we complete() here we may allow duplicate threads | |
| 235 | − * to continue before the first one that submitted the | |
| 236 | − * request. We're in no rush also, given that each and | |
| 237 | − * every bounce back to userspace is slow we avoid that | |
| 238 | − * with a slight delay here. So queueue up the completion | |
| 239 | − * and let duplicates suffer, just wait a tad bit longer. | |
| 240 | − * There is no rush. But we also don't want to hold the | |
| 241 | − * caller up forever or introduce any boot delays. | |
| 212 | + * Now that we have allowed prior request_module() calls to go on | |
| 213 | + * with life, let's schedule deleting this entry. We don't have | |
| 214 | + * to do it right away, but we *eventually* want to do it so to not | |
| 215 | + * let this linger forever as this is just a boot optimization for | |
| 216 | + * possible abuses of vmalloc() incurred by finit_module() thrashing. | |
| 242 | 217 | */ |
| 243 | − queue_work(system_dfl_wq, &kmod_req->complete_work); | |
| 218 | + queue_delayed_work(system_dfl_wq, &kmod_req->delete_work, 60 * HZ); | |
| 244 | 219 | |
| 245 | 220 | out: |
| 246 | 221 | mutex_unlock(&kmod_dup_mutex); |