Author: delphij
Date: Wed May  8 17:45:22 2013
New Revision: 250374
URL: http://svnweb.freebsd.org/changeset/base/250374

Log:
  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

Modified:
  head/sys/ofed/include/linux/workqueue.h

Modified: head/sys/ofed/include/linux/workqueue.h
==============================================================================
--- head/sys/ofed/include/linux/workqueue.h     Wed May  8 16:43:52 2013        
(r250373)
+++ head/sys/ofed/include/linux/workqueue.h     Wed May  8 17:45:22 2013        
(r250374)
@@ -184,9 +184,9 @@ cancel_delayed_work(struct delayed_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;
 }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to