mirror of
https://github.com/torvalds/linux.git
synced 2024-11-19 18:41:48 +00:00
locking/rwsem: Fix down_write_killable() for CONFIG_RWSEM_GENERIC_SPINLOCK=y
We hang if SIGKILL has been sent, but the task is stuck in down_read() (after do_exit()), even though no task is doing down_write() on the rwsem in question: INFO: task libupnp:21868 blocked for more than 120 seconds. libupnp D 0 21868 1 0x08100008 ... Call Trace: __schedule() schedule() __down_read() do_exit() do_group_exit() __wake_up_parent() This bug has already been fixed for CONFIG_RWSEM_XCHGADD_ALGORITHM=y in the following commit:04cafed7fc
("locking/rwsem: Fix down_write_killable()") ... however, this bug also exists for CONFIG_RWSEM_GENERIC_SPINLOCK=y. Signed-off-by: Niklas Cassel <niklas.cassel@axis.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: <mhocko@suse.com> Cc: <stable@vger.kernel.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Niklas Cassel <niklass@axis.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Fixes:d47996082f
("locking/rwsem: Introduce basis for down_write_killable()") Link: http://lkml.kernel.org/r/1487981873-12649-1-git-send-email-niklass@axis.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
9bbb25afeb
commit
17fcbd590d
@ -213,10 +213,9 @@ int __sched __down_write_common(struct rw_semaphore *sem, int state)
|
|||||||
*/
|
*/
|
||||||
if (sem->count == 0)
|
if (sem->count == 0)
|
||||||
break;
|
break;
|
||||||
if (signal_pending_state(state, current)) {
|
if (signal_pending_state(state, current))
|
||||||
ret = -EINTR;
|
goto out_nolock;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
set_current_state(state);
|
set_current_state(state);
|
||||||
raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
|
raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
|
||||||
schedule();
|
schedule();
|
||||||
@ -224,12 +223,19 @@ int __sched __down_write_common(struct rw_semaphore *sem, int state)
|
|||||||
}
|
}
|
||||||
/* got the lock */
|
/* got the lock */
|
||||||
sem->count = -1;
|
sem->count = -1;
|
||||||
out:
|
|
||||||
list_del(&waiter.list);
|
list_del(&waiter.list);
|
||||||
|
|
||||||
raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
|
raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
out_nolock:
|
||||||
|
list_del(&waiter.list);
|
||||||
|
if (!list_empty(&sem->wait_list))
|
||||||
|
__rwsem_do_wake(sem, 1);
|
||||||
|
raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
|
||||||
|
|
||||||
|
return -EINTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __sched __down_write(struct rw_semaphore *sem)
|
void __sched __down_write(struct rw_semaphore *sem)
|
||||||
|
Loading…
Reference in New Issue
Block a user