Messages in this thread Patch in this message | | | From | Guoyong Wang <> | Subject | [PATCH v2] random: Fix the issue of '_might_sleep' function running in an atomic contex | Date | Fri, 19 Apr 2024 18:54:53 +0800 |
| |
In the case that a delay is acceptable for 'crng_set_ready', it can be deferred to a workqueue in order to accommodate different contexts.
Signed-off-by: Guoyong Wang <guoyong.wang@mediatek.com> --- v2: Compared to version 1, version 2 has removed the definition of 'execute_in_non_atomic_context' and always uses a workqueue to execute 'crng_set_ready'.
Send out the patch again for further discussion.
[1]: https://patchwork.kernel.org/patch/13595066
--- drivers/char/random.c | 10 +++++----- include/linux/workqueue.h | 1 - kernel/workqueue.c | 26 -------------------------- 3 files changed, 5 insertions(+), 32 deletions(-)
diff --git a/drivers/char/random.c b/drivers/char/random.c index 00be9426a6fc..2597cb43f438 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -702,7 +702,7 @@ static void extract_entropy(void *buf, size_t len) static void __cold _credit_init_bits(size_t bits) { - static struct execute_work set_ready; + static DECLARE_WORK(set_ready, crng_set_ready); unsigned int new, orig, add; unsigned long flags; @@ -718,8 +718,8 @@ static void __cold _credit_init_bits(size_t bits) if (orig < POOL_READY_BITS && new >= POOL_READY_BITS) { crng_reseed(NULL); /* Sets crng_init to CRNG_READY under base_crng.lock. */ - if (static_key_initialized) - execute_in_non_atomic_context(crng_set_ready, &set_ready); + if (static_key_initialized && system_unbound_wq) + queue_work(system_unbound_wq, &set_ready); atomic_notifier_call_chain(&random_ready_notifier, 0, NULL); wake_up_interruptible(&crng_init_wait); kill_fasync(&fasync, SIGIO, POLL_IN); @@ -890,8 +890,8 @@ void __init random_init(void) /* * If we were initialized by the cpu or bootloader before jump labels - * are initialized, then we should enable the static branch here, where - * it's guaranteed that jump labels have been initialized. + * or workqueues are initialized, then we should enable the static + * branch here, where it's guaranteed that these have been initialized. */ if (!static_branch_likely(&crng_is_ready) && crng_init >= CRNG_READY) crng_set_ready(NULL); diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index eb17c62d23aa..158784dd189a 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -550,7 +550,6 @@ extern void drain_workqueue(struct workqueue_struct *wq); extern int schedule_on_each_cpu(work_func_t func); int execute_in_process_context(work_func_t fn, struct execute_work *); -int execute_in_non_atomic_context(work_func_t fn, struct execute_work *ew); extern bool flush_work(struct work_struct *work); extern bool cancel_work(struct work_struct *work); diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 8f212346da7a..bf2bdac46843 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -4449,32 +4449,6 @@ int execute_in_process_context(work_func_t fn, struct execute_work *ew) } EXPORT_SYMBOL_GPL(execute_in_process_context); -/** - * execute_in_non_atomic_context - reliably execute the routine with user context - * @fn: the function to execute - * @ew: guaranteed storage for the execute work structure (must - * be available when the work executes) - * - * Schedules the function for delayed execution if atomic context is available, - * otherwise executes the function immediately . - * - * Return: 0 - function was executed - * 1 - function was scheduled for execution - */ -int execute_in_non_atomic_context(work_func_t fn, struct execute_work *ew) -{ - if (!in_atomic()) { - fn(&ew->work); - return 0; - } - - INIT_WORK(&ew->work, fn); - schedule_work(&ew->work); - - return 1; -} -EXPORT_SYMBOL_GPL(execute_in_non_atomic_context); - /** * free_workqueue_attrs - free a workqueue_attrs * @attrs: workqueue_attrs to free -- 2.18.0
| |