summaryrefslogtreecommitdiff
path: root/drivers/of/pdt.c
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2015-11-19 07:36:50 -0500
committerMike Snitzer <snitzer@redhat.com>2015-11-19 13:38:30 -0500
commitbcbd94ff481ec1d7b5c824d90df82d0faafabd35 (patch)
treeac755d832487bd9cce6ee61ac319be6ed09574e9 /drivers/of/pdt.c
parent43e43c9ea60a7a1831ec823773e924d2dadefd44 (diff)
dm crypt: fix a possible hang due to race condition on exit
A kernel thread executes __set_current_state(TASK_INTERRUPTIBLE), __add_wait_queue, spin_unlock_irq and then tests kthread_should_stop(). It is possible that the processor reorders memory accesses so that kthread_should_stop() is executed before __set_current_state(). If such reordering happens, there is a possible race on thread termination: CPU 0: calls kthread_should_stop() it tests KTHREAD_SHOULD_STOP bit, returns false CPU 1: calls kthread_stop(cc->write_thread) sets the KTHREAD_SHOULD_STOP bit calls wake_up_process on the kernel thread, that sets the thread state to TASK_RUNNING CPU 0: sets __set_current_state(TASK_INTERRUPTIBLE) spin_unlock_irq(&cc->write_thread_wait.lock) schedule() - and the process is stuck and never terminates, because the state is TASK_INTERRUPTIBLE and wake_up_process on CPU 1 already terminated Fix this race condition by using a new flag DM_CRYPT_EXIT_THREAD to signal that the kernel thread should exit. The flag is set and tested while holding cc->write_thread_wait.lock, so there is no possibility of racy access to the flag. Also, remove the unnecessary set_task_state(current, TASK_RUNNING) following the schedule() call. When the process was woken up, its state was already set to TASK_RUNNING. Other kernel code also doesn't set the state to TASK_RUNNING following schedule() (for example, do_wait_for_common in completion.c doesn't do it). Fixes: dc2676210c42 ("dm crypt: offload writes to thread") Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Cc: stable@vger.kernel.org # v4.0+ Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/of/pdt.c')
0 files changed, 0 insertions, 0 deletions