Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f293ea92 authored by Oleg Nesterov's avatar Oleg Nesterov Committed by Linus Torvalds
Browse files

workqueue: don't save interrupts in run_workqueue()



work->func() may sleep, it's a bug to call run_workqueue() with irqs disabled.

Signed-off-by: default avatarOleg Nesterov <oleg@tv-sign.ru>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 7097a87a
Loading
Loading
Loading
Loading
+8 −10
Original line number Original line Diff line number Diff line
@@ -227,13 +227,7 @@ EXPORT_SYMBOL_GPL(queue_delayed_work_on);


static void run_workqueue(struct cpu_workqueue_struct *cwq)
static void run_workqueue(struct cpu_workqueue_struct *cwq)
{
{
	unsigned long flags;
	spin_lock_irq(&cwq->lock);

	/*
	 * Keep taking off work from the queue until
	 * done.
	 */
	spin_lock_irqsave(&cwq->lock, flags);
	cwq->run_depth++;
	cwq->run_depth++;
	if (cwq->run_depth > 3) {
	if (cwq->run_depth > 3) {
		/* morton gets to eat his hat */
		/* morton gets to eat his hat */
@@ -248,7 +242,7 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq)


		cwq->current_work = work;
		cwq->current_work = work;
		list_del_init(cwq->worklist.next);
		list_del_init(cwq->worklist.next);
		spin_unlock_irqrestore(&cwq->lock, flags);
		spin_unlock_irq(&cwq->lock);


		BUG_ON(get_wq_data(work) != cwq);
		BUG_ON(get_wq_data(work) != cwq);
		if (!test_bit(WORK_STRUCT_NOAUTOREL, work_data_bits(work)))
		if (!test_bit(WORK_STRUCT_NOAUTOREL, work_data_bits(work)))
@@ -266,11 +260,11 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq)
			dump_stack();
			dump_stack();
		}
		}


		spin_lock_irqsave(&cwq->lock, flags);
		spin_lock_irq(&cwq->lock);
		cwq->current_work = NULL;
		cwq->current_work = NULL;
	}
	}
	cwq->run_depth--;
	cwq->run_depth--;
	spin_unlock_irqrestore(&cwq->lock, flags);
	spin_unlock_irq(&cwq->lock);
}
}


/*
/*
@@ -399,6 +393,8 @@ static void flush_cpu_workqueue(struct cpu_workqueue_struct *cwq)
 */
 */
void fastcall flush_workqueue(struct workqueue_struct *wq)
void fastcall flush_workqueue(struct workqueue_struct *wq)
{
{
	might_sleep();

	if (is_single_threaded(wq))
	if (is_single_threaded(wq))
		flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, singlethread_cpu));
		flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, singlethread_cpu));
	else {
	else {
@@ -445,6 +441,8 @@ void flush_work(struct workqueue_struct *wq, struct work_struct *work)
{
{
	struct cpu_workqueue_struct *cwq;
	struct cpu_workqueue_struct *cwq;


	might_sleep();

	cwq = get_wq_data(work);
	cwq = get_wq_data(work);
	/* Was it ever queued ? */
	/* Was it ever queued ? */
	if (!cwq)
	if (!cwq)