]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.9.162/locking-rwsem-fix-possible-missed-wakeup.patch
Linux 4.9.162
[thirdparty/kernel/stable-queue.git] / releases / 4.9.162 / locking-rwsem-fix-possible-missed-wakeup.patch
CommitLineData
a9593ee3
SL
1From 012a134056bf40d5c46fe729385b47e4a099a891 Mon Sep 17 00:00:00 2001
2From: Xie Yongji <xieyongji@baidu.com>
3Date: Thu, 29 Nov 2018 20:50:30 +0800
4Subject: locking/rwsem: Fix (possible) missed wakeup
5
6[ Upstream commit e158488be27b157802753a59b336142dc0eb0380 ]
7
8Because wake_q_add() can imply an immediate wakeup (cmpxchg failure
9case), we must not rely on the wakeup being delayed. However, commit:
10
11 e38513905eea ("locking/rwsem: Rework zeroing reader waiter->task")
12
13relies on exactly that behaviour in that the wakeup must not happen
14until after we clear waiter->task.
15
16[ peterz: Added changelog. ]
17
18Signed-off-by: Xie Yongji <xieyongji@baidu.com>
19Signed-off-by: Zhang Yu <zhangyu31@baidu.com>
20Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
21Cc: Linus Torvalds <torvalds@linux-foundation.org>
22Cc: Peter Zijlstra <peterz@infradead.org>
23Cc: Thomas Gleixner <tglx@linutronix.de>
24Fixes: e38513905eea ("locking/rwsem: Rework zeroing reader waiter->task")
25Link: https://lkml.kernel.org/r/1543495830-2644-1-git-send-email-xieyongji@baidu.com
26Signed-off-by: Ingo Molnar <mingo@kernel.org>
27Signed-off-by: Sasha Levin <sashal@kernel.org>
28---
29 kernel/locking/rwsem-xadd.c | 11 +++++++++--
30 1 file changed, 9 insertions(+), 2 deletions(-)
31
32diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c
33index a4112dfcd0fb1..be06c45cbe4f9 100644
34--- a/kernel/locking/rwsem-xadd.c
35+++ b/kernel/locking/rwsem-xadd.c
36@@ -195,15 +195,22 @@ static void __rwsem_mark_wake(struct rw_semaphore *sem,
37 woken++;
38 tsk = waiter->task;
39
40- wake_q_add(wake_q, tsk);
41+ get_task_struct(tsk);
42 list_del(&waiter->list);
43 /*
44- * Ensure that the last operation is setting the reader
45+ * Ensure calling get_task_struct() before setting the reader
46 * waiter to nil such that rwsem_down_read_failed() cannot
47 * race with do_exit() by always holding a reference count
48 * to the task to wakeup.
49 */
50 smp_store_release(&waiter->task, NULL);
51+ /*
52+ * Ensure issuing the wakeup (either by us or someone else)
53+ * after setting the reader waiter to nil.
54+ */
55+ wake_q_add(wake_q, tsk);
56+ /* wake_q_add() already take the task ref */
57+ put_task_struct(tsk);
58 }
59
60 adjustment = woken * RWSEM_ACTIVE_READ_BIAS - adjustment;
61--
622.19.1
63