- Avoid rwsem lockups in certain situations when handling the handoff bit
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEzv7L6UO9uDPlPSfHEsHwGGHeVUoFAmLmUPkACgkQEsHwGGHe VUqgow/+Oj8acqImjR1OGW0MGW5F4OBRxPlWYGRBem0PwtysKSOUEuLKFGrfUPP8 9/o/WDK7sKm0A0Ph4++zyuxQVUdww1kWR1BaOzBBJZMhB3dYk511JW2EZc7TPQg8 qnBWOh1WGztaIATImo1JtN7GVlz6mWEq5i7CkyYWOfqqgMMfzS5N548KtFs37k1F GPwR2fntThsgYlL7+5ekHVBabx3Lf5CvpUkct484LtIrvO9xvBr+R5fzxdkd/j7s xGVFpt0sMEGjnOatLP+Q41E6n4Vugzjk9FdxOAYLcSl8NPGj/7HUtXB0oLcU7jSn eFxr2vurueVxpueNieBKJNiSicFsgx+QNsEtERtzLfyosgKtDkWtl5cP6k7qzqVm 9KGAWc5tiQJ5DcIoxf+pKBEXBnf6EKFS7PrknYFTbWPFnbun0nw4OnFLufUgeg9c qB6afbWUOwKLWYIcJZadmnvmE2ZhaPAv1KPvqeE7E8ln5ERbg2UKY4qV37bvyJFg N+gVv+acSip4KtGswGUBKFriJ/vvN1dh/PiBqqJC3AHwlz+CxYsOVgpk9tkhlaQ9 1HsQ51hyN/pb688J9SshqZf2BH3qS6Kz4eLa1eXGPEywsRBJfg4lufncn1JbrCg8 CzkUfVPbS31LahMDs5U3IWGSiYSUsy1JDRLZ2zns9ZEMaaZWPKQ= =SBw2 -----END PGP SIGNATURE----- Merge tag 'locking_urgent_for_v5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull locking fix from Borislav Petkov: - Avoid rwsem lockups in certain situations when handling the handoff bit * tag 'locking_urgent_for_v5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: locking/rwsem: Allow slowpath writer to ignore handoff bit if not set by first waiter
This commit is contained in:
commit
5e4823e6da
|
@ -335,8 +335,6 @@ struct rwsem_waiter {
|
||||||
struct task_struct *task;
|
struct task_struct *task;
|
||||||
enum rwsem_waiter_type type;
|
enum rwsem_waiter_type type;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
|
||||||
/* Writer only, not initialized in reader */
|
|
||||||
bool handoff_set;
|
bool handoff_set;
|
||||||
};
|
};
|
||||||
#define rwsem_first_waiter(sem) \
|
#define rwsem_first_waiter(sem) \
|
||||||
|
@ -459,10 +457,12 @@ static void rwsem_mark_wake(struct rw_semaphore *sem,
|
||||||
* to give up the lock), request a HANDOFF to
|
* to give up the lock), request a HANDOFF to
|
||||||
* force the issue.
|
* force the issue.
|
||||||
*/
|
*/
|
||||||
if (!(oldcount & RWSEM_FLAG_HANDOFF) &&
|
if (time_after(jiffies, waiter->timeout)) {
|
||||||
time_after(jiffies, waiter->timeout)) {
|
if (!(oldcount & RWSEM_FLAG_HANDOFF)) {
|
||||||
adjustment -= RWSEM_FLAG_HANDOFF;
|
adjustment -= RWSEM_FLAG_HANDOFF;
|
||||||
lockevent_inc(rwsem_rlock_handoff);
|
lockevent_inc(rwsem_rlock_handoff);
|
||||||
|
}
|
||||||
|
waiter->handoff_set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
atomic_long_add(-adjustment, &sem->count);
|
atomic_long_add(-adjustment, &sem->count);
|
||||||
|
@ -599,7 +599,7 @@ rwsem_del_wake_waiter(struct rw_semaphore *sem, struct rwsem_waiter *waiter,
|
||||||
static inline bool rwsem_try_write_lock(struct rw_semaphore *sem,
|
static inline bool rwsem_try_write_lock(struct rw_semaphore *sem,
|
||||||
struct rwsem_waiter *waiter)
|
struct rwsem_waiter *waiter)
|
||||||
{
|
{
|
||||||
bool first = rwsem_first_waiter(sem) == waiter;
|
struct rwsem_waiter *first = rwsem_first_waiter(sem);
|
||||||
long count, new;
|
long count, new;
|
||||||
|
|
||||||
lockdep_assert_held(&sem->wait_lock);
|
lockdep_assert_held(&sem->wait_lock);
|
||||||
|
@ -609,11 +609,20 @@ static inline bool rwsem_try_write_lock(struct rw_semaphore *sem,
|
||||||
bool has_handoff = !!(count & RWSEM_FLAG_HANDOFF);
|
bool has_handoff = !!(count & RWSEM_FLAG_HANDOFF);
|
||||||
|
|
||||||
if (has_handoff) {
|
if (has_handoff) {
|
||||||
if (!first)
|
/*
|
||||||
|
* Honor handoff bit and yield only when the first
|
||||||
|
* waiter is the one that set it. Otherwisee, we
|
||||||
|
* still try to acquire the rwsem.
|
||||||
|
*/
|
||||||
|
if (first->handoff_set && (waiter != first))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* First waiter inherits a previously set handoff bit */
|
/*
|
||||||
waiter->handoff_set = true;
|
* First waiter can inherit a previously set handoff
|
||||||
|
* bit and spin on rwsem if lock acquisition fails.
|
||||||
|
*/
|
||||||
|
if (waiter == first)
|
||||||
|
waiter->handoff_set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
new = count;
|
new = count;
|
||||||
|
@ -1027,6 +1036,7 @@ queue:
|
||||||
waiter.task = current;
|
waiter.task = current;
|
||||||
waiter.type = RWSEM_WAITING_FOR_READ;
|
waiter.type = RWSEM_WAITING_FOR_READ;
|
||||||
waiter.timeout = jiffies + RWSEM_WAIT_TIMEOUT;
|
waiter.timeout = jiffies + RWSEM_WAIT_TIMEOUT;
|
||||||
|
waiter.handoff_set = false;
|
||||||
|
|
||||||
raw_spin_lock_irq(&sem->wait_lock);
|
raw_spin_lock_irq(&sem->wait_lock);
|
||||||
if (list_empty(&sem->wait_list)) {
|
if (list_empty(&sem->wait_list)) {
|
||||||
|
|
Loading…
Reference in New Issue