summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2016-09-16 15:49:32 -0400
committerTejun Heo <tj@kernel.org>2016-09-17 13:18:21 -0400
commit3347fa0928210d96aaa2bd6cd5a8391d5e630873 (patch)
tree6b2b82cee1af9a916679e9713878ceaf81d13e45
parentfa07fb6a4ecad41d373eaf1574b9d54b4f0c1e75 (diff)
workqueue: make workqueue available early during boot
Workqueue is currently initialized in an early init call; however, there are cases where early boot code has to be split and reordered to come after workqueue initialization or the same code path which makes use of workqueues is used both before workqueue initailization and after. The latter cases have to gate workqueue usages with keventd_up() tests, which is nasty and easy to get wrong. Workqueue usages have become widespread and it'd be a lot more convenient if it can be used very early from boot. This patch splits workqueue initialization into two steps. workqueue_init_early() which sets up the basic data structures so that workqueues can be created and work items queued, and workqueue_init() which actually brings up workqueues online and starts executing queued work items. The former step can be done very early during boot once memory allocation, cpumasks and idr are initialized. The latter right after kthreads become available. This allows work item queueing and canceling from very early boot which is what most of these use cases want. * As systemd_wq being initialized doesn't indicate that workqueue is fully online anymore, update keventd_up() to test wq_online instead. The follow-up patches will get rid of all its usages and the function itself. * Flushing doesn't make sense before workqueue is fully initialized. The flush functions trigger WARN and return immediately before fully online. * Work items are never in-flight before fully online. Canceling can always succeed by skipping the flush step. * Some code paths can no longer assume to be called with irq enabled as irq is disabled during early boot. Use irqsave/restore operations instead. v2: Watchdog init, which requires timer to be running, moved from workqueue_init_early() to workqueue_init(). Signed-off-by: Tejun Heo <tj@kernel.org> Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Link: http://lkml.kernel.org/r/CA+55aFx0vPuMuxn00rBSM192n-Du5uxy+4AvKa0SBSOVJeuCGg@mail.gmail.com
-rw-r--r--include/linux/workqueue.h7
-rw-r--r--init/main.c10
-rw-r--r--kernel/workqueue.c76
3 files changed, 76 insertions, 17 deletions
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 26cc1df280d6..91d416f9c0a7 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -358,6 +358,8 @@ extern struct workqueue_struct *system_freezable_wq;
358extern struct workqueue_struct *system_power_efficient_wq; 358extern struct workqueue_struct *system_power_efficient_wq;
359extern struct workqueue_struct *system_freezable_power_efficient_wq; 359extern struct workqueue_struct *system_freezable_power_efficient_wq;
360 360
361extern bool wq_online;
362
361extern struct workqueue_struct * 363extern struct workqueue_struct *
362__alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active, 364__alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active,
363 struct lock_class_key *key, const char *lock_name, ...) __printf(1, 6); 365 struct lock_class_key *key, const char *lock_name, ...) __printf(1, 6);
@@ -594,7 +596,7 @@ static inline bool schedule_delayed_work(struct delayed_work *dwork,
594 */ 596 */
595static inline bool keventd_up(void) 597static inline bool keventd_up(void)
596{ 598{
597 return system_wq != NULL; 599 return wq_online;
598} 600}
599 601
600#ifndef CONFIG_SMP 602#ifndef CONFIG_SMP
@@ -631,4 +633,7 @@ int workqueue_online_cpu(unsigned int cpu);
631int workqueue_offline_cpu(unsigned int cpu); 633int workqueue_offline_cpu(unsigned int cpu);
632#endif 634#endif
633 635
636int __init workqueue_init_early(void);
637int __init workqueue_init(void);
638
634#endif 639#endif
diff --git a/init/main.c b/init/main.c
index a8a58e2794a5..5c4fd68a8671 100644
--- a/init/main.c
+++ b/init/main.c
@@ -551,6 +551,14 @@ asmlinkage __visible void __init start_kernel(void)
551 "Interrupts were enabled *very* early, fixing it\n")) 551 "Interrupts were enabled *very* early, fixing it\n"))
552 local_irq_disable(); 552 local_irq_disable();
553 idr_init_cache(); 553 idr_init_cache();
554
555 /*
556 * Allow workqueue creation and work item queueing/cancelling
557 * early. Work item execution depends on kthreads and starts after
558 * workqueue_init().
559 */
560 workqueue_init_early();
561
554 rcu_init(); 562 rcu_init();
555 563
556 /* trace_printk() and trace points may be used after this */ 564 /* trace_printk() and trace points may be used after this */
@@ -1005,6 +1013,8 @@ static noinline void __init kernel_init_freeable(void)
1005 1013
1006 smp_prepare_cpus(setup_max_cpus); 1014 smp_prepare_cpus(setup_max_cpus);
1007 1015
1016 workqueue_init();
1017
1008 do_pre_smp_initcalls(); 1018 do_pre_smp_initcalls();
1009 lockup_detector_init(); 1019 lockup_detector_init();
1010 1020
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 4eaec8b86d65..15d0811c9e91 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -290,6 +290,8 @@ module_param_named(disable_numa, wq_disable_numa, bool, 0444);
290static bool wq_power_efficient = IS_ENABLED(CONFIG_WQ_POWER_EFFICIENT_DEFAULT); 290static bool wq_power_efficient = IS_ENABLED(CONFIG_WQ_POWER_EFFICIENT_DEFAULT);
291module_param_named(power_efficient, wq_power_efficient, bool, 0444); 291module_param_named(power_efficient, wq_power_efficient, bool, 0444);
292 292
293bool wq_online; /* can kworkers be created yet? */
294
293static bool wq_numa_enabled; /* unbound NUMA affinity enabled */ 295static bool wq_numa_enabled; /* unbound NUMA affinity enabled */
294 296
295/* buf for wq_update_unbound_numa_attrs(), protected by CPU hotplug exclusion */ 297/* buf for wq_update_unbound_numa_attrs(), protected by CPU hotplug exclusion */
@@ -2583,6 +2585,9 @@ void flush_workqueue(struct workqueue_struct *wq)
2583 }; 2585 };
2584 int next_color; 2586 int next_color;
2585 2587
2588 if (WARN_ON(!wq_online))
2589 return;
2590
2586 lock_map_acquire(&wq->lockdep_map); 2591 lock_map_acquire(&wq->lockdep_map);
2587 lock_map_release(&wq->lockdep_map); 2592 lock_map_release(&wq->lockdep_map);
2588 2593
@@ -2843,6 +2848,9 @@ bool flush_work(struct work_struct *work)
2843{ 2848{
2844 struct wq_barrier barr; 2849 struct wq_barrier barr;
2845 2850
2851 if (WARN_ON(!wq_online))
2852 return false;
2853
2846 lock_map_acquire(&work->lockdep_map); 2854 lock_map_acquire(&work->lockdep_map);
2847 lock_map_release(&work->lockdep_map); 2855 lock_map_release(&work->lockdep_map);
2848 2856
@@ -2913,7 +2921,13 @@ static bool __cancel_work_timer(struct work_struct *work, bool is_dwork)
2913 mark_work_canceling(work); 2921 mark_work_canceling(work);
2914 local_irq_restore(flags); 2922 local_irq_restore(flags);
2915 2923
2916 flush_work(work); 2924 /*
2925 * This allows canceling during early boot. We know that @work
2926 * isn't executing.
2927 */
2928 if (wq_online)
2929 flush_work(work);
2930
2917 clear_work_data(work); 2931 clear_work_data(work);
2918 2932
2919 /* 2933 /*
@@ -3352,7 +3366,7 @@ static struct worker_pool *get_unbound_pool(const struct workqueue_attrs *attrs)
3352 goto fail; 3366 goto fail;
3353 3367
3354 /* create and start the initial worker */ 3368 /* create and start the initial worker */
3355 if (!create_worker(pool)) 3369 if (wq_online && !create_worker(pool))
3356 goto fail; 3370 goto fail;
3357 3371
3358 /* install */ 3372 /* install */
@@ -3417,6 +3431,7 @@ static void pwq_adjust_max_active(struct pool_workqueue *pwq)
3417{ 3431{
3418 struct workqueue_struct *wq = pwq->wq; 3432 struct workqueue_struct *wq = pwq->wq;
3419 bool freezable = wq->flags & WQ_FREEZABLE; 3433 bool freezable = wq->flags & WQ_FREEZABLE;
3434 unsigned long flags;
3420 3435
3421 /* for @wq->saved_max_active */ 3436 /* for @wq->saved_max_active */
3422 lockdep_assert_held(&wq->mutex); 3437 lockdep_assert_held(&wq->mutex);
@@ -3425,7 +3440,8 @@ static void pwq_adjust_max_active(struct pool_workqueue *pwq)
3425 if (!freezable && pwq->max_active == wq->saved_max_active) 3440 if (!freezable && pwq->max_active == wq->saved_max_active)
3426 return; 3441 return;
3427 3442
3428 spin_lock_irq(&pwq->pool->lock); 3443 /* this function can be called during early boot w/ irq disabled */
3444 spin_lock_irqsave(&pwq->pool->lock, flags);
3429 3445
3430 /* 3446 /*
3431 * During [un]freezing, the caller is responsible for ensuring that 3447 * During [un]freezing, the caller is responsible for ensuring that
@@ -3448,7 +3464,7 @@ static void pwq_adjust_max_active(struct pool_workqueue *pwq)
3448 pwq->max_active = 0; 3464 pwq->max_active = 0;
3449 } 3465 }
3450 3466
3451 spin_unlock_irq(&pwq->pool->lock); 3467 spin_unlock_irqrestore(&pwq->pool->lock, flags);
3452} 3468}
3453 3469
3454/* initialize newly alloced @pwq which is associated with @wq and @pool */ 3470/* initialize newly alloced @pwq which is associated with @wq and @pool */
@@ -5457,7 +5473,17 @@ static void __init wq_numa_init(void)
5457 wq_numa_enabled = true; 5473 wq_numa_enabled = true;
5458} 5474}
5459 5475
5460static int __init init_workqueues(void) 5476/**
5477 * workqueue_init_early - early init for workqueue subsystem
5478 *
5479 * This is the first half of two-staged workqueue subsystem initialization
5480 * and invoked as soon as the bare basics - memory allocation, cpumasks and
5481 * idr are up. It sets up all the data structures and system workqueues
5482 * and allows early boot code to create workqueues and queue/cancel work
5483 * items. Actual work item execution starts only after kthreads can be
5484 * created and scheduled right before early initcalls.
5485 */
5486int __init workqueue_init_early(void)
5461{ 5487{
5462 int std_nice[NR_STD_WORKER_POOLS] = { 0, HIGHPRI_NICE_LEVEL }; 5488 int std_nice[NR_STD_WORKER_POOLS] = { 0, HIGHPRI_NICE_LEVEL };
5463 int i, cpu; 5489 int i, cpu;
@@ -5490,16 +5516,6 @@ static int __init init_workqueues(void)
5490 } 5516 }
5491 } 5517 }
5492 5518
5493 /* create the initial worker */
5494 for_each_online_cpu(cpu) {
5495 struct worker_pool *pool;
5496
5497 for_each_cpu_worker_pool(pool, cpu) {
5498 pool->flags &= ~POOL_DISASSOCIATED;
5499 BUG_ON(!create_worker(pool));
5500 }
5501 }
5502
5503 /* create default unbound and ordered wq attrs */ 5519 /* create default unbound and ordered wq attrs */
5504 for (i = 0; i < NR_STD_WORKER_POOLS; i++) { 5520 for (i = 0; i < NR_STD_WORKER_POOLS; i++) {
5505 struct workqueue_attrs *attrs; 5521 struct workqueue_attrs *attrs;
@@ -5536,8 +5552,36 @@ static int __init init_workqueues(void)
5536 !system_power_efficient_wq || 5552 !system_power_efficient_wq ||
5537 !system_freezable_power_efficient_wq); 5553 !system_freezable_power_efficient_wq);
5538 5554
5555 return 0;
5556}
5557
5558/**
5559 * workqueue_init - bring workqueue subsystem fully online
5560 *
5561 * This is the latter half of two-staged workqueue subsystem initialization
5562 * and invoked as soon as kthreads can be created and scheduled.
5563 * Workqueues have been created and work items queued on them, but there
5564 * are no kworkers executing the work items yet. Populate the worker pools
5565 * with the initial workers and enable future kworker creations.
5566 */
5567int __init workqueue_init(void)
5568{
5569 struct worker_pool *pool;
5570 int cpu, bkt;
5571
5572 /* create the initial workers */
5573 for_each_online_cpu(cpu) {
5574 for_each_cpu_worker_pool(pool, cpu) {
5575 pool->flags &= ~POOL_DISASSOCIATED;
5576 BUG_ON(!create_worker(pool));
5577 }
5578 }
5579
5580 hash_for_each(unbound_pool_hash, bkt, pool, hash_node)
5581 BUG_ON(!create_worker(pool));
5582
5583 wq_online = true;
5539 wq_watchdog_init(); 5584 wq_watchdog_init();
5540 5585
5541 return 0; 5586 return 0;
5542} 5587}
5543early_initcall(init_workqueues);