summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/workqueue.c64
1 files changed, 40 insertions, 24 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 8c34981d90ad..8dd2e66e8383 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -3940,6 +3940,37 @@ static int wq_clamp_max_active(int max_active, unsigned int flags,
3940 return clamp_val(max_active, 1, lim); 3940 return clamp_val(max_active, 1, lim);
3941} 3941}
3942 3942
3943/*
3944 * Workqueues which may be used during memory reclaim should have a rescuer
3945 * to guarantee forward progress.
3946 */
3947static int init_rescuer(struct workqueue_struct *wq)
3948{
3949 struct worker *rescuer;
3950 int ret;
3951
3952 if (!(wq->flags & WQ_MEM_RECLAIM))
3953 return 0;
3954
3955 rescuer = alloc_worker(NUMA_NO_NODE);
3956 if (!rescuer)
3957 return -ENOMEM;
3958
3959 rescuer->rescue_wq = wq;
3960 rescuer->task = kthread_create(rescuer_thread, rescuer, "%s", wq->name);
3961 ret = PTR_ERR_OR_ZERO(rescuer->task);
3962 if (ret) {
3963 kfree(rescuer);
3964 return ret;
3965 }
3966
3967 wq->rescuer = rescuer;
3968 kthread_bind_mask(rescuer->task, cpu_possible_mask);
3969 wake_up_process(rescuer->task);
3970
3971 return 0;
3972}
3973
3943struct workqueue_struct *__alloc_workqueue_key(const char *fmt, 3974struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
3944 unsigned int flags, 3975 unsigned int flags,
3945 int max_active, 3976 int max_active,
@@ -4002,29 +4033,8 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
4002 if (alloc_and_link_pwqs(wq) < 0) 4033 if (alloc_and_link_pwqs(wq) < 0)
4003 goto err_free_wq; 4034 goto err_free_wq;
4004 4035
4005 /* 4036 if (wq_online && init_rescuer(wq) < 0)
4006 * Workqueues which may be used during memory reclaim should 4037 goto err_destroy;
4007 * have a rescuer to guarantee forward progress.
4008 */
4009 if (flags & WQ_MEM_RECLAIM) {
4010 struct worker *rescuer;
4011
4012 rescuer = alloc_worker(NUMA_NO_NODE);
4013 if (!rescuer)
4014 goto err_destroy;
4015
4016 rescuer->rescue_wq = wq;
4017 rescuer->task = kthread_create(rescuer_thread, rescuer, "%s",
4018 wq->name);
4019 if (IS_ERR(rescuer->task)) {
4020 kfree(rescuer);
4021 goto err_destroy;
4022 }
4023
4024 wq->rescuer = rescuer;
4025 kthread_bind_mask(rescuer->task, cpu_possible_mask);
4026 wake_up_process(rescuer->task);
4027 }
4028 4038
4029 if ((wq->flags & WQ_SYSFS) && workqueue_sysfs_register(wq)) 4039 if ((wq->flags & WQ_SYSFS) && workqueue_sysfs_register(wq))
4030 goto err_destroy; 4040 goto err_destroy;
@@ -5642,6 +5652,8 @@ int __init workqueue_init(void)
5642 * archs such as power and arm64. As per-cpu pools created 5652 * archs such as power and arm64. As per-cpu pools created
5643 * previously could be missing node hint and unbound pools NUMA 5653 * previously could be missing node hint and unbound pools NUMA
5644 * affinity, fix them up. 5654 * affinity, fix them up.
5655 *
5656 * Also, while iterating workqueues, create rescuers if requested.
5645 */ 5657 */
5646 wq_numa_init(); 5658 wq_numa_init();
5647 5659
@@ -5653,8 +5665,12 @@ int __init workqueue_init(void)
5653 } 5665 }
5654 } 5666 }
5655 5667
5656 list_for_each_entry(wq, &workqueues, list) 5668 list_for_each_entry(wq, &workqueues, list) {
5657 wq_update_unbound_numa(wq, smp_processor_id(), true); 5669 wq_update_unbound_numa(wq, smp_processor_id(), true);
5670 WARN(init_rescuer(wq),
5671 "workqueue: failed to create early rescuer for %s",
5672 wq->name);
5673 }
5658 5674
5659 mutex_unlock(&wq_pool_mutex); 5675 mutex_unlock(&wq_pool_mutex);
5660 5676