diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2021-05-17 00:17:27 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2021-05-17 00:17:27 +0000 |
commit | 4f439bc370e9c3aae03cdd731f6f7e8700db4501 (patch) | |
tree | 1e12aa2d403ed8b22a93a4dab447df00c4f8e05c /sys/dev/pci/drm | |
parent | 274991700c5f6c93939fded8d93e1480a10ff658 (diff) |
return early if work is cancelled before being scheduled
cheloha@ noticed that task_del(9) was being called with a NULL taskq
from inteldrm(4), which was not noticed as the function returns early
from testing a flag in the task. This situation occurs when work is
cancelled before it is scheduled.
ok kettenis@ cheloha@
Diffstat (limited to 'sys/dev/pci/drm')
-rw-r--r-- | sys/dev/pci/drm/include/linux/workqueue.h | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/sys/dev/pci/drm/include/linux/workqueue.h b/sys/dev/pci/drm/include/linux/workqueue.h index 703d2f06b9c..a0c7134c88e 100644 --- a/sys/dev/pci/drm/include/linux/workqueue.h +++ b/sys/dev/pci/drm/include/linux/workqueue.h @@ -1,4 +1,4 @@ -/* $OpenBSD: workqueue.h,v 1.4 2021/02/14 03:42:55 jsg Exp $ */ +/* $OpenBSD: workqueue.h,v 1.5 2021/05/17 00:17:26 jsg Exp $ */ /* * Copyright (c) 2015 Mark Kettenis * @@ -95,7 +95,8 @@ queue_work(struct workqueue_struct *wq, struct work_struct *work) static inline void cancel_work_sync(struct work_struct *work) { - task_del(work->tq, &work->task); + if (work->tq != NULL) + task_del(work->tq, &work->task); } #define work_pending(work) task_pending(&(work)->task) @@ -169,6 +170,8 @@ mod_delayed_work(struct workqueue_struct *wq, static inline bool cancel_delayed_work(struct delayed_work *dwork) { + if (dwork->tq == NULL) + return false; if (timeout_del(&dwork->to)) return true; return task_del(dwork->tq, &dwork->work.task); @@ -177,6 +180,8 @@ cancel_delayed_work(struct delayed_work *dwork) static inline bool cancel_delayed_work_sync(struct delayed_work *dwork) { + if (dwork->tq == NULL) + return false; if (timeout_del(&dwork->to)) return true; return task_del(dwork->tq, &dwork->work.task); |