Skip to content

Commit

Permalink
Merge branch 'for-4.16' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/tj/wq

Pull workqueue updates from Tejun Heo:
 "Workqueue has an early init trick where workqueues can be created and
  work items queued on them before the workqueue subsystem is online.
  This helps simplifying early init and operation of low level
  subsystems which use workqueues for managerial things which aren't
  depended upon early during boot.

  Out of laziness, the early init didn't cover workqueues with
  WQ_MEM_RECLAIM, which is inconsistent and confusing because adding the
  flag simply makes the system fail to boot. Cover WQ_MEM_RECLAIM too.

  This was originally brought up for RCU but RCU didn't actually need
  this. I still think it's a good idea to cover it"

* 'for-4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq:
  workqueue: allow WQ_MEM_RECLAIM on early init workqueues
  workqueue: separate out init_rescuer()
  • Loading branch information
torvalds committed Jan 30, 2018
2 parents 2afe738 + 40c17f7 commit f8cc87b
Showing 1 changed file with 40 additions and 24 deletions.
64 changes: 40 additions & 24 deletions kernel/workqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -3940,6 +3940,37 @@ static int wq_clamp_max_active(int max_active, unsigned int flags,
return clamp_val(max_active, 1, lim);
}

/*
* Workqueues which may be used during memory reclaim should have a rescuer
* to guarantee forward progress.
*/
static int init_rescuer(struct workqueue_struct *wq)
{
struct worker *rescuer;
int ret;

if (!(wq->flags & WQ_MEM_RECLAIM))
return 0;

rescuer = alloc_worker(NUMA_NO_NODE);
if (!rescuer)
return -ENOMEM;

rescuer->rescue_wq = wq;
rescuer->task = kthread_create(rescuer_thread, rescuer, "%s", wq->name);
ret = PTR_ERR_OR_ZERO(rescuer->task);
if (ret) {
kfree(rescuer);
return ret;
}

wq->rescuer = rescuer;
kthread_bind_mask(rescuer->task, cpu_possible_mask);
wake_up_process(rescuer->task);

return 0;
}

struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
unsigned int flags,
int max_active,
Expand Down Expand Up @@ -4002,29 +4033,8 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt,
if (alloc_and_link_pwqs(wq) < 0)
goto err_free_wq;

/*
* Workqueues which may be used during memory reclaim should
* have a rescuer to guarantee forward progress.
*/
if (flags & WQ_MEM_RECLAIM) {
struct worker *rescuer;

rescuer = alloc_worker(NUMA_NO_NODE);
if (!rescuer)
goto err_destroy;

rescuer->rescue_wq = wq;
rescuer->task = kthread_create(rescuer_thread, rescuer, "%s",
wq->name);
if (IS_ERR(rescuer->task)) {
kfree(rescuer);
goto err_destroy;
}

wq->rescuer = rescuer;
kthread_bind_mask(rescuer->task, cpu_possible_mask);
wake_up_process(rescuer->task);
}
if (wq_online && init_rescuer(wq) < 0)
goto err_destroy;

if ((wq->flags & WQ_SYSFS) && workqueue_sysfs_register(wq))
goto err_destroy;
Expand Down Expand Up @@ -5642,6 +5652,8 @@ int __init workqueue_init(void)
* archs such as power and arm64. As per-cpu pools created
* previously could be missing node hint and unbound pools NUMA
* affinity, fix them up.
*
* Also, while iterating workqueues, create rescuers if requested.
*/
wq_numa_init();

Expand All @@ -5653,8 +5665,12 @@ int __init workqueue_init(void)
}
}

list_for_each_entry(wq, &workqueues, list)
list_for_each_entry(wq, &workqueues, list) {
wq_update_unbound_numa(wq, smp_processor_id(), true);
WARN(init_rescuer(wq),
"workqueue: failed to create early rescuer for %s",
wq->name);
}

mutex_unlock(&wq_pool_mutex);

Expand Down

0 comments on commit f8cc87b

Please sign in to comment.