linux/include
Tejun Heo 28a4e95363 workqueue: fix hang involving racing cancel[_delayed]_work_sync()'s for PREEMPT_NONE
commit 8603e1b300 upstream.

cancel[_delayed]_work_sync() are implemented using
__cancel_work_timer() which grabs the PENDING bit using
try_to_grab_pending() and then flushes the work item with PENDING set
to prevent the on-going execution of the work item from requeueing
itself.

try_to_grab_pending() can always grab PENDING bit without blocking
except when someone else is doing the above flushing during
cancelation.  In that case, try_to_grab_pending() returns -ENOENT.  In
this case, __cancel_work_timer() currently invokes flush_work().  The
assumption is that the completion of the work item is what the other
canceling task would be waiting for too and thus waiting for the same
condition and retrying should allow forward progress without excessive
busy looping

Unfortunately, this doesn't work if preemption is disabled or the
latter task has real time priority.  Let's say task A just got woken
up from flush_work() by the completion of the target work item.  If,
before task A starts executing, task B gets scheduled and invokes
__cancel_work_timer() on the same work item, its try_to_grab_pending()
will return -ENOENT as the work item is still being canceled by task A
and flush_work() will also immediately return false as the work item
is no longer executing.  This puts task B in a busy loop possibly
preventing task A from executing and clearing the canceling state on
the work item leading to a hang.

task A			task B			worker

						executing work
__cancel_work_timer()
  try_to_grab_pending()
  set work CANCELING
  flush_work()
    block for work completion
						completion, wakes up A
			__cancel_work_timer()
			while (forever) {
			  try_to_grab_pending()
			    -ENOENT as work is being canceled
			  flush_work()
			    false as work is no longer executing
			}

This patch removes the possible hang by updating __cancel_work_timer()
to explicitly wait for clearing of CANCELING rather than invoking
flush_work() after try_to_grab_pending() fails with -ENOENT.

Link: http://lkml.kernel.org/g/20150206171156.GA8942@axis.com

v3: bit_waitqueue() can't be used for work items defined in vmalloc
    area.  Switched to custom wake function which matches the target
    work item and exclusive wait and wakeup.

v2: v1 used wake_up() on bit_waitqueue() which leads to NULL deref if
    the target bit waitqueue has wait_bit_queue's on it.  Use
    DEFINE_WAIT_BIT() and __wake_up_bit() instead.  Reported by Tomeu
    Vizoso.

Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Rabin Vincent <rabin.vincent@axis.com>
Cc: Tomeu Vizoso <tomeu.vizoso@gmail.com>
Tested-by: Jesper Nilsson <jesper.nilsson@axis.com>
Tested-by: Rabin Vincent <rabin.vincent@axis.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
History 2015-03-26 15:06:54 +01:00
..
acpi ACPI / hotplug: Generate online uevents for ACPI containers 2014-10-05 14:52:16 -07:00
asm-generic mm: use paravirt friendly ops for NUMA hinting ptes 2014-05-31 13:20:30 -07:00
clocksource drivers: clocksource: add support for ARM architected timer event stream 2013-09-26 09:48:00 +01:00
crypto crypto: scatterwalk - Use sg_chain_ptr on chain entries 2013-12-09 19:58:52 +08:00
drm drm/radeon: remove invalid pci id 2014-11-14 09:00:12 -08:00
dt-bindings pinctrl: dra: dt-bindings: Fix output pull up/down 2014-11-21 09:23:02 -08:00
keys KEYS: Separate the kernel signature checking keyring from module signing 2013-09-25 17:17:01 +01:00
kvm ARM: KVM: fix non-VGIC compilation 2014-03-06 09:47:42 +01:00
linux workqueue: fix hang involving racing cancel[_delayed]_work_sync()'s for PREEMPT_NONE 2015-03-26 15:06:54 +01:00
math-emu math-emu: fix floating-point to integer overflow detection 2014-01-07 18:36:24 -06:00
media media: vb2: fix VBI/poll regression 2014-10-09 12:21:27 -07:00
memory ddr: add LPDDR2 data from JESD209-2 2012-05-02 00:04:06 -07:00
misc [media] altera-stapl: it is time to move out from staging 2011-09-23 15:00:57 -03:00
net ipv4: tcp: get rid of ugly unicast_sock 2015-02-26 17:50:12 -08:00
pcmcia pcmcia/ds.h: introduce helper for pcmcia_driver module boilerplate 2013-03-15 12:26:03 -07:00
ras edac: add support for error type "Info" 2013-02-21 14:16:27 -03:00
rdma IB/core: Don't resolve passive side RoCE L2 address in CMA REQ handler 2014-05-06 07:59:28 -07:00
rxrpc atomic: use <linux/atomic.h> 2011-07-26 16:49:47 -07:00
scsi scsi: do not issue SCSI RSOC command to Promise Vtrak E610f 2014-09-17 09:19:14 -07:00
sound ALSA: ak411x: Fix stall in work callback 2015-02-11 14:54:49 +08:00
target target: Fix PR_APTPL_BUF_LEN buffer size limitation 2015-03-18 13:31:24 +01:00
trace mm: when stealing freepages, also take pages created by splitting buddy page 2015-03-18 13:31:23 +01:00
uapi in6: fix conflict with glibc 2015-01-27 08:18:53 -08:00
video video: pxa168fb: Cleanup pxa168fb.h file 2014-01-17 10:57:43 +02:00
xen Merge branch 'for-linus' of git://git.kernel.dk/linux-block 2014-02-14 10:45:18 -08:00
Kbuild UAPI: remove empty Kbuild files 2013-04-30 17:04:09 -07:00