Home Home > GIT Browse > SLE12-SP3-AZURE
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavidlohr Bueso <dbueso@suse.de>2019-02-18 12:48:17 -0800
committerDavidlohr Bueso <dbueso@suse.de>2019-02-18 12:48:30 -0800
commit4a3eab0d6593383bd47983120f17a6096c751c35 (patch)
treef00004a0fc7b694a88ba578dd76245c8a495c695
parente2cf447bf0fc59b3651615ee120cd28c5172ca17 (diff)
sched/wake_q: Reduce reference counting for special users
(bsc#1050549).
-rw-r--r--patches.fixes/0003-sched-wake_q-Reduce-reference-counting-for-special-u.patch181
-rw-r--r--series.conf1
2 files changed, 182 insertions, 0 deletions
diff --git a/patches.fixes/0003-sched-wake_q-Reduce-reference-counting-for-special-u.patch b/patches.fixes/0003-sched-wake_q-Reduce-reference-counting-for-special-u.patch
new file mode 100644
index 0000000000..344af4055f
--- /dev/null
+++ b/patches.fixes/0003-sched-wake_q-Reduce-reference-counting-for-special-u.patch
@@ -0,0 +1,181 @@
+From 38c5ba7f66c90b3c0b8e68f6a070a8cb9e659855 Mon Sep 17 00:00:00 2001
+From: Davidlohr Bueso <dave@stgolabs.net>
+Date: Mon, 18 Feb 2019 10:03:21 -0800
+Subject: [PATCH 3/3] sched/wake_q: Reduce reference counting for special users
+Patch-mainline: Not yet, queued via tip for v5.1.
+References: bsc#1050549
+
+Some users, specifically futexes and rwsems, required fixes
+that allowed the callers to be safe when wakeups occur before
+they are expected by wake_up_q(). Such scenarios also play
+games and rely on reference counting, and until now were
+pivoting on wake_q doing it. With the wake_q_add() call being
+moved down, this can no longer be the case. As such we end up
+with a a double task refcounting overhead; and these callers
+care enough about this (being rather core-ish).
+
+This patch introduces a wake_q_add_safe() call that serves
+for callers that have already done refcounting and therefore the
+task is 'safe' from wake_q point of view (int that it requires
+reference throughout the entire queue/>wakeup cycle). In the one
+case it has internal reference counting, in the other case it
+consumes the reference counting.
+
+Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Waiman Long <longman@redhat.com>
+Cc: Will Deacon <will.deacon@arm.com>
+Cc: Xie Yongji <xieyongji@baidu.com>
+Cc: Yongji Xie <elohimes@gmail.com>
+Cc: andrea.parri@amarulasolutions.com
+Cc: lilin24@baidu.com
+Cc: liuqi16@baidu.com
+Cc: nixun@baidu.com
+Cc: yuanlinsi01@baidu.com
+Cc: zhangyu31@baidu.com
+Link: https://lkml.kernel.org/r/20181218195352.7orq3upiwfdbrdne@linux-r8p5
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+
+---
+ include/linux/sched.h | 4 +--
+ kernel/futex.c | 3 +--
+ kernel/locking/rwsem-xadd.c | 4 +--
+ kernel/sched/core.c | 60 +++++++++++++++++++++++++++++++++------------
+ 4 files changed, 48 insertions(+), 23 deletions(-)
+
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index ebe1aa236fba..3e17daba39e4 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -1004,8 +1004,8 @@ struct wake_q_head {
+ #define WAKE_Q(name) \
+ struct wake_q_head name = { WAKE_Q_TAIL, &name.first }
+
+-extern void wake_q_add(struct wake_q_head *head,
+- struct task_struct *task);
++extern void wake_q_add(struct wake_q_head *head, struct task_struct *task);
++extern void wake_q_add_safe(struct wake_q_head *head, struct task_struct *task);
+ extern void wake_up_q(struct wake_q_head *head);
+
+ /*
+diff --git a/kernel/futex.c b/kernel/futex.c
+index c3a7a434004e..4323f8061654 100644
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -1290,8 +1290,7 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)
+ * Queue the task for later wakeup for after we've released
+ * the hb->lock. wake_q_add() grabs reference to p.
+ */
+- wake_q_add(wake_q, p);
+- put_task_struct(p);
++ wake_q_add_safe(wake_q, p);
+ }
+
+ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this,
+diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c
+index 1dad74958b1c..32f66c0b53e7 100644
+--- a/kernel/locking/rwsem-xadd.c
++++ b/kernel/locking/rwsem-xadd.c
+@@ -219,9 +219,7 @@ __rwsem_mark_wake(struct rw_semaphore *sem,
+ * Ensure issuing the wakeup (either by us or someone else)
+ * after setting the reader waiter to nil.
+ */
+- wake_q_add(wake_q, tsk);
+- /* wake_q_add() already take the task ref */
+- put_task_struct(tsk);
++ wake_q_add_safe(wake_q, tsk);
+ } while (--loop);
+
+ sem->wait_list.next = next;
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index b5f7fd0b5938..61f80137dee6 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -588,19 +588,7 @@ static bool set_nr_if_polling(struct task_struct *p)
+ #endif
+ #endif
+
+-/**
+- * wake_q_add() - queue a wakeup for 'later' waking.
+- * @head: the wake_q_head to add @task to
+- * @task: the task to queue for 'later' wakeup
+- *
+- * Queue a task for later wakeup, most likely by the wake_up_q() call in the
+- * same context, _HOWEVER_ this is not guaranteed, the wakeup can come
+- * instantly.
+- *
+- * This function must be used as-if it were wake_up_process(); IOW the task
+- * must be ready to be woken at this location.
+- */
+-void wake_q_add(struct wake_q_head *head, struct task_struct *task)
++static bool __wake_q_add(struct wake_q_head *head, struct task_struct *task)
+ {
+ struct wake_q_node *node = &task->wake_q;
+
+@@ -614,15 +602,55 @@ void wake_q_add(struct wake_q_head *head, struct task_struct *task)
+ */
+ smp_mb__before_atomic();
+ if (cmpxchg_relaxed(&node->next, NULL, WAKE_Q_TAIL))
+- return;
+-
+- get_task_struct(task);
++ return false;
+
+ /*
+ * The head is context local, there can be no concurrency.
+ */
+ *head->lastp = node;
+ head->lastp = &node->next;
++ return true;
++}
++
++/**
++ * wake_q_add() - queue a wakeup for 'later' waking.
++ * @head: the wake_q_head to add @task to
++ * @task: the task to queue for 'later' wakeup
++ *
++ * Queue a task for later wakeup, most likely by the wake_up_q() call in the
++ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come
++ * instantly.
++ *
++ * This function must be used as-if it were wake_up_process(); IOW the task
++ * must be ready to be woken at this location.
++ */
++void wake_q_add(struct wake_q_head *head, struct task_struct *task)
++{
++ if (__wake_q_add(head, task))
++ get_task_struct(task);
++}
++
++/**
++ * wake_q_add_safe() - safely queue a wakeup for 'later' waking.
++ * @head: the wake_q_head to add @task to
++ * @task: the task to queue for 'later' wakeup
++ *
++ * Queue a task for later wakeup, most likely by the wake_up_q() call in the
++ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come
++ * instantly.
++ *
++ * This function must be used as-if it were wake_up_process(); IOW the task
++ * must be ready to be woken at this location.
++ *
++ * This function is essentially a task-safe equivalent to wake_q_add(). Callers
++ * that already hold reference to @task can call the 'safe' version and trust
++ * wake_q to do the right thing depending whether or not the @task is already
++ * queued for wakeup.
++ */
++void wake_q_add_safe(struct wake_q_head *head, struct task_struct *task)
++{
++ if (!__wake_q_add(head, task))
++ put_task_struct(task);
+ }
+
+ void wake_up_q(struct wake_q_head *head)
+--
+2.16.4
+
diff --git a/series.conf b/series.conf
index 25ed369f82..ebff91fce7 100644
--- a/series.conf
+++ b/series.conf
@@ -24303,6 +24303,7 @@
patches.suse/0013-net-mpls-prevent-speculative-execution.patch
patches.suse/0014-udf-prevent-speculative-execution.patch
patches.fixes/sched-fair-Avoid-divide-by-zero-when-rebalancing-dom.patch
+ patches.fixes/0003-sched-wake_q-Reduce-reference-counting-for-special-u.patch
########################################################
# interrupts/core