diff options
author | delphij <delphij@FreeBSD.org> | 2013-05-08 17:45:22 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2013-05-08 17:45:22 +0000 |
commit | 55fe0cb833adb732625dc8457434d8e8ed2e799b (patch) | |
tree | fb02680fcf1e8dc3c5d9bfd051d035e48d46cb25 /sys/ofed | |
parent | 59a21e33a2e75a3e44a67142eefcc978133c557e (diff) | |
download | FreeBSD-src-55fe0cb833adb732625dc8457434d8e8ed2e799b.zip FreeBSD-src-55fe0cb833adb732625dc8457434d8e8ed2e799b.tar.gz |
According to the documentation, on Linux, cancel_delayed_work() does not
do drain (flush_workqueue() in Linux terms) but instead returns true if
the work was removed before it is run, or false otherwise.
Simulate this by removing the taskqueue_drain() and return the value
derived from taskqueue_cancel()'s return value.
This would solve a witness warning caused by calling taskqueue_drain()
with a non-sleepable lock held, like:
taskqueue_drain with the following non-sleepable locks held:
exclusive rw lle (lle) r = 0 (0xfffffe001450b410) locked @
/usr/src/sys/netinet/in.c:1484
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xffffff848d4f7690
kdb_backtrace() at kdb_backtrace+0x39/frame 0xffffff848d4f7740
witness_warn() at witness_warn+0x4a8/frame 0xffffff848d4f7800
taskqueue_drain() at taskqueue_drain+0x3a/frame 0xffffff848d4f7840
set_timeout() at set_timeout+0x4a/frame 0xffffff848d4f7860
netevent_callback() at netevent_callback+0x16/frame 0xffffff848d4f7870
arpintr() at arpintr+0x9b5/frame 0xffffff848d4f7930
This do not affect kernel without OFED compiled in.
Reported by: Garrett Cooper <yaneurabeya gmail com>
(who also tested an earlier version of this patch,
but bugs are mine)
MFC after: 2 weeks
Diffstat (limited to 'sys/ofed')
-rw-r--r-- | sys/ofed/include/linux/workqueue.h | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/sys/ofed/include/linux/workqueue.h b/sys/ofed/include/linux/workqueue.h index 77443fe..ce5759b 100644 --- a/sys/ofed/include/linux/workqueue.h +++ b/sys/ofed/include/linux/workqueue.h @@ -184,9 +184,9 @@ cancel_delayed_work(struct delayed_work *work) { callout_stop(&work->timer); - if (work->work.taskqueue && - taskqueue_cancel(work->work.taskqueue, &work->work.work_task, NULL)) - taskqueue_drain(work->work.taskqueue, &work->work.work_task); + if (work->work.taskqueue) + return (taskqueue_cancel(work->work.taskqueue, + &work->work.work_task, NULL) == 0); return 0; } |