diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 2989b57e154a..30427a1f961c 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -941,8 +941,12 @@ static void worker_enter_idle(struct worker *worker) /* idle_list is LIFO */ list_add(&worker->entry, &pool->idle_list); - if (too_many_workers(pool) && !timer_pending(&pool->idle_timer)) + if (too_many_workers(pool) && !timer_pending(&pool->idle_timer)) { + unsigned long flags; + raw_spin_unlock_irqrestore(&pool->lock, flags); mod_timer(&pool->idle_timer, jiffies + IDLE_WORKER_TIMEOUT); + raw_spin_lock_irqsave(&pool->lock, flags); + } /* Sanity check nr_running. */ WARN_ON_ONCE(pool->nr_workers == pool->nr_idle && pool->nr_running); @@ -2164,6 +2168,7 @@ static struct worker *create_worker(struct worker_pool *pool) struct worker *worker; int id; char id_buf[23]; + unsigned long flags; /* ID is needed to determine kthread name */ id = ida_alloc(&pool->worker_ida, GFP_KERNEL); @@ -2207,7 +2212,7 @@ static struct worker *create_worker(struct worker_pool *pool) worker_attach_to_pool(worker, pool); /* start the newly created worker */ - raw_spin_lock_irq(&pool->lock); + raw_spin_lock_irqsave(&pool->lock, flags); worker->pool->nr_workers++; worker_enter_idle(worker); @@ -2220,7 +2225,7 @@ static struct worker *create_worker(struct worker_pool *pool) */ wake_up_process(worker->task); - raw_spin_unlock_irq(&pool->lock); + raw_spin_unlock_irqrestore(&pool->lock, flags); return worker; @@ -2727,15 +2732,16 @@ static int worker_thread(void *__worker) { struct worker *worker = __worker; struct worker_pool *pool = worker->pool; + unsigned long flags; /* tell the scheduler that this is a workqueue worker */ set_pf_worker(true); woke_up: - raw_spin_lock_irq(&pool->lock); + raw_spin_lock_irqsave(&pool->lock, flags); /* am I supposed to die? */ if (unlikely(worker->flags & WORKER_DIE)) { - raw_spin_unlock_irq(&pool->lock); + raw_spin_unlock_irqsave(&pool->lock, flags); set_pf_worker(false); set_task_comm(worker->task, "kworker/dying"); @@ -2792,7 +2798,7 @@ static int worker_thread(void *__worker) */ worker_enter_idle(worker); __set_current_state(TASK_IDLE); - raw_spin_unlock_irq(&pool->lock); + raw_spin_unlock_irqrestore(&pool->lock, flags); schedule(); goto woke_up; }