locking/rwsem: Prevent decrement of reader count before increment
Waiman Long authored
[ Upstream commit a9e9bcb4 ]

During my rwsem testing, it was found that after a down_read(), the
reader count may occasionally become 0 or even negative. Consequently,
a writer may steal the lock at that time and execute with the reader
in parallel thus breaking the mutual exclusion guarantee of the write
lock. In other words, both readers and writer can become rwsem owners
simultaneously.

The current reader wakeup code does it in one pass to clear waiter->task
and put them into wake_q before fully incrementing the reader count.
Once waiter->task is cleared, the corresponding reader may see it,
finish the critical section and do unlock to decrement the count before
the count is incremented. This is not a problem if there is only one
reader to wake up as the count has been pre-incremented by 1.  It is
a problem if there are more than one readers to be woken up and writer
can steal the lock.

The wakeup was a...
c48fddac
Name Last commit Last update
..
Makefile License cleanup: add SPDX GPL-2.0 license identifier to files with no license
lockdep.c locking/lockdep: Make lockdep_unregister_key() honor 'debug_locks' again
lockdep_internals.h locking/lockdep: Introduce lockdep_next_lockchain() and lock_chain_count()
lockdep_proc.c locking/lockdep: Introduce lockdep_next_lockchain() and lock_chain_count()
lockdep_states.h locking/lockdep: Rework FS_RECLAIM annotation
locktorture.c Merge branches 'doc.2019.01.26a', 'fixes.2019.01.26a', 'sil.2019.01.26a', 'spdx.2019.02.09a', 'srcu.2019.01.26a' and 'torture.2019.01.26a' into HEAD
mcs_spinlock.h locking/mcs: Use smp_cond_load_acquire() in MCS spin loop
mutex-debug.c locking/mutex: Replace spin_is_locked() with lockdep
mutex-debug.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license
mutex.c kernel/locking/mutex.c: remove caller signal_pending branch predictions
mutex.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license
osq_lock.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license
percpu-rwsem.c locking/percpu-rwsem: Replace waitqueue with rcuwait
qrwlock.c locking/qrwlock: Prevent slowpath writers getting held up by fastpath
qspinlock.c locking/qspinlock: Remove unnecessary BUG_ON() call
qspinlock_paravirt.h mm: remove include/linux/bootmem.h
qspinlock_stat.h locking/qspinlock_stat: Track the no MCS node available case
rtmutex-debug.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license
rtmutex-debug.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license
rtmutex.c futex: Handle early deadlock return correctly
rtmutex.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license
rtmutex_common.h locking/rtmutex: Handle non enqueued waiters gracefully in remove_waiter()
rwsem-spinlock.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license
rwsem-xadd.c locking/rwsem: Prevent decrement of reader count before increment
rwsem.c locking/rwsem: Make owner store task pointer of last owning reader
rwsem.h
semaphore.c
spinlock.c
spinlock_debug.c
test-ww_mutex.c