Skip to content

Commit c2fda50

Browse files
Lai Jiangshanhtejun
authored andcommitted
workqueue: allow work_on_cpu() to be called recursively
If the @fn call work_on_cpu() again, the lockdep will complain: > [ INFO: possible recursive locking detected ] > 3.11.0-rc1-lockdep-fix-a #6 Not tainted > --------------------------------------------- > kworker/0:1/142 is trying to acquire lock: > ((&wfc.work)){+.+.+.}, at: [<ffffffff81077100>] flush_work+0x0/0xb0 > > but task is already holding lock: > ((&wfc.work)){+.+.+.}, at: [<ffffffff81075dd9>] process_one_work+0x169/0x610 > > other info that might help us debug this: > Possible unsafe locking scenario: > > CPU0 > ---- > lock((&wfc.work)); > lock((&wfc.work)); > > *** DEADLOCK *** It is false-positive lockdep report. In this sutiation, the two "wfc"s of the two work_on_cpu() are different, they are both on stack. flush_work() can't be deadlock. To fix this, we need to avoid the lockdep checking in this case, thus we instroduce a internal __flush_work() which skip the lockdep. tj: Minor comment adjustment. Signed-off-by: Lai Jiangshan <[email protected]> Reported-by: "Srivatsa S. Bhat" <[email protected]> Reported-by: Alexander Duyck <[email protected]> Signed-off-by: Tejun Heo <[email protected]>
1 parent ad81f05 commit c2fda50

File tree

1 file changed

+22
-10
lines changed

1 file changed

+22
-10
lines changed

kernel/workqueue.c

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2817,6 +2817,19 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr)
28172817
return false;
28182818
}
28192819

2820+
static bool __flush_work(struct work_struct *work)
2821+
{
2822+
struct wq_barrier barr;
2823+
2824+
if (start_flush_work(work, &barr)) {
2825+
wait_for_completion(&barr.done);
2826+
destroy_work_on_stack(&barr.work);
2827+
return true;
2828+
} else {
2829+
return false;
2830+
}
2831+
}
2832+
28202833
/**
28212834
* flush_work - wait for a work to finish executing the last queueing instance
28222835
* @work: the work to flush
@@ -2830,18 +2843,10 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr)
28302843
*/
28312844
bool flush_work(struct work_struct *work)
28322845
{
2833-
struct wq_barrier barr;
2834-
28352846
lock_map_acquire(&work->lockdep_map);
28362847
lock_map_release(&work->lockdep_map);
28372848

2838-
if (start_flush_work(work, &barr)) {
2839-
wait_for_completion(&barr.done);
2840-
destroy_work_on_stack(&barr.work);
2841-
return true;
2842-
} else {
2843-
return false;
2844-
}
2849+
return __flush_work(work);
28452850
}
28462851
EXPORT_SYMBOL_GPL(flush_work);
28472852

@@ -4756,7 +4761,14 @@ long work_on_cpu(int cpu, long (*fn)(void *), void *arg)
47564761

47574762
INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn);
47584763
schedule_work_on(cpu, &wfc.work);
4759-
flush_work(&wfc.work);
4764+
4765+
/*
4766+
* The work item is on-stack and can't lead to deadlock through
4767+
* flushing. Use __flush_work() to avoid spurious lockdep warnings
4768+
* when work_on_cpu()s are nested.
4769+
*/
4770+
__flush_work(&wfc.work);
4771+
47604772
return wfc.ret;
47614773
}
47624774
EXPORT_SYMBOL_GPL(work_on_cpu);

0 commit comments

Comments
 (0)