diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2017-11-12 07:02:51 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2017-11-12 07:15:14 -0500 |
commit | d00a08cf9ee986ad6689ce8c6fd176aff679c106 (patch) | |
tree | ad39bb22f22d5613e7c40b5e39552c334192dd46 | |
parent | 9dc505d6df5c607a4ea088b5f1907540079a9859 (diff) |
irq/work: Use llist_for_each_entry_safe
The llist_for_each_entry() loop in irq_work_run_list() is unsafe because
once the works PENDING bit is cleared it can be requeued on another CPU.
Use llist_for_each_entry_safe() instead.
Fixes: 16c0890dc66d ("irq/work: Don't reinvent the wheel but use existing llist API")
Reported-by:Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Frederic Weisbecker <frederic@kernel.org>
Cc: Byungchul Park <byungchul.park@lge.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Petri Latvala <petri.latvala@intel.com>
Link: http://lkml.kernel.org/r/151027307351.14762.4611888896020658384@mail.alporthouse.com
-rw-r--r-- | kernel/irq_work.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/kernel/irq_work.c b/kernel/irq_work.c index e2ebe8c71e8f..6647b33f7eb0 100644 --- a/kernel/irq_work.c +++ b/kernel/irq_work.c | |||
@@ -128,9 +128,9 @@ bool irq_work_needs_cpu(void) | |||
128 | 128 | ||
129 | static void irq_work_run_list(struct llist_head *list) | 129 | static void irq_work_run_list(struct llist_head *list) |
130 | { | 130 | { |
131 | unsigned long flags; | 131 | struct irq_work *work, *tmp; |
132 | struct irq_work *work; | ||
133 | struct llist_node *llnode; | 132 | struct llist_node *llnode; |
133 | unsigned long flags; | ||
134 | 134 | ||
135 | BUG_ON(!irqs_disabled()); | 135 | BUG_ON(!irqs_disabled()); |
136 | 136 | ||
@@ -138,7 +138,7 @@ static void irq_work_run_list(struct llist_head *list) | |||
138 | return; | 138 | return; |
139 | 139 | ||
140 | llnode = llist_del_all(list); | 140 | llnode = llist_del_all(list); |
141 | llist_for_each_entry(work, llnode, llnode) { | 141 | llist_for_each_entry_safe(work, tmp, llnode, llnode) { |
142 | /* | 142 | /* |
143 | * Clear the PENDING bit, after this point the @work | 143 | * Clear the PENDING bit, after this point the @work |
144 | * can be re-used. | 144 | * can be re-used. |