Skip to content

Commit de46e65

Browse files
suryasaimadhugregkh
authored andcommitted
EDAC: Robustify workqueues destruction
commit fcd5c4d upstream. EDAC workqueue destruction is really fragile. We cancel delayed work but if it is still running and requeues itself, we still go ahead and destroy the workqueue and the queued work explodes when workqueue core attempts to run it. Make the destruction more robust by switching op_state to offline so that requeuing stops. Cancel any pending work *synchronously* too. EDAC i7core: Driver loaded. general protection fault: 0000 [#1] SMP CPU 12 Modules linked in: Supported: Yes Pid: 0, comm: kworker/0:1 Tainted: G IE 3.0.101-0-default #1 HP ProLiant DL380 G7 RIP: 0010:[<ffffffff8107dcd7>] [<ffffffff8107dcd7>] __queue_work+0x17/0x3f0 < ... regs ...> Process kworker/0:1 (pid: 0, threadinfo ffff88019def6000, task ffff88019def4600) Stack: ... Call Trace: call_timer_fn run_timer_softirq __do_softirq call_softirq do_softirq irq_exit smp_apic_timer_interrupt apic_timer_interrupt intel_idle cpuidle_idle_call cpu_idle Code: ... RIP __queue_work RSP <...> Signed-off-by: Borislav Petkov <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent a869e6b commit de46e65

File tree

3 files changed

+11
-23
lines changed

3 files changed

+11
-23
lines changed

drivers/edac/edac_device.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -435,16 +435,13 @@ void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
435435
*/
436436
void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev)
437437
{
438-
int status;
439-
440438
if (!edac_dev->edac_check)
441439
return;
442440

443-
status = cancel_delayed_work(&edac_dev->work);
444-
if (status == 0) {
445-
/* workq instance might be running, wait for it */
446-
flush_workqueue(edac_workqueue);
447-
}
441+
edac_dev->op_state = OP_OFFLINE;
442+
443+
cancel_delayed_work_sync(&edac_dev->work);
444+
flush_workqueue(edac_workqueue);
448445
}
449446

450447
/*

drivers/edac/edac_mc.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -586,18 +586,10 @@ static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec,
586586
*/
587587
static void edac_mc_workq_teardown(struct mem_ctl_info *mci)
588588
{
589-
int status;
590-
591-
if (mci->op_state != OP_RUNNING_POLL)
592-
return;
593-
594-
status = cancel_delayed_work(&mci->work);
595-
if (status == 0) {
596-
edac_dbg(0, "not canceled, flush the queue\n");
589+
mci->op_state = OP_OFFLINE;
597590

598-
/* workq instance might be running, wait for it */
599-
flush_workqueue(edac_workqueue);
600-
}
591+
cancel_delayed_work_sync(&mci->work);
592+
flush_workqueue(edac_workqueue);
601593
}
602594

603595
/*

drivers/edac/edac_pci.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -274,13 +274,12 @@ static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci,
274274
*/
275275
static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci)
276276
{
277-
int status;
278-
279277
edac_dbg(0, "\n");
280278

281-
status = cancel_delayed_work(&pci->work);
282-
if (status == 0)
283-
flush_workqueue(edac_workqueue);
279+
pci->op_state = OP_OFFLINE;
280+
281+
cancel_delayed_work_sync(&pci->work);
282+
flush_workqueue(edac_workqueue);
284283
}
285284

286285
/*

0 commit comments

Comments
 (0)