]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 4.19
authorSasha Levin <sashal@kernel.org>
Mon, 24 May 2021 00:40:13 +0000 (20:40 -0400)
committerSasha Levin <sashal@kernel.org>
Mon, 24 May 2021 00:40:13 +0000 (20:40 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.19/locking-mutex-clear-mutex_flags-if-wait_list-is-empt.patch [new file with mode: 0644]
queue-4.19/series

diff --git a/queue-4.19/locking-mutex-clear-mutex_flags-if-wait_list-is-empt.patch b/queue-4.19/locking-mutex-clear-mutex_flags-if-wait_list-is-empt.patch
new file mode 100644 (file)
index 0000000..617ed36
--- /dev/null
@@ -0,0 +1,136 @@
+From 8ec34f007b392032744ea14e9f6f68579c3601bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 May 2021 11:40:05 +0800
+Subject: locking/mutex: clear MUTEX_FLAGS if wait_list is empty due to signal
+
+From: Zqiang <qiang.zhang@windriver.com>
+
+[ Upstream commit 3a010c493271f04578b133de977e0e5dd2848cea ]
+
+When a interruptible mutex locker is interrupted by a signal
+without acquiring this lock and removed from the wait queue.
+if the mutex isn't contended enough to have a waiter
+put into the wait queue again, the setting of the WAITER
+bit will force mutex locker to go into the slowpath to
+acquire the lock every time, so if the wait queue is empty,
+the WAITER bit need to be clear.
+
+Fixes: 040a0a371005 ("mutex: Add support for wound/wait style locks")
+Suggested-by: Peter Zijlstra <peterz@infradead.org>
+Signed-off-by: Zqiang <qiang.zhang@windriver.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lkml.kernel.org/r/20210517034005.30828-1-qiang.zhang@windriver.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/locking/mutex-debug.c |  4 ++--
+ kernel/locking/mutex-debug.h |  2 +-
+ kernel/locking/mutex.c       | 18 +++++++++++++-----
+ kernel/locking/mutex.h       |  4 +---
+ 4 files changed, 17 insertions(+), 11 deletions(-)
+
+diff --git a/kernel/locking/mutex-debug.c b/kernel/locking/mutex-debug.c
+index 9aa713629387..839df4383799 100644
+--- a/kernel/locking/mutex-debug.c
++++ b/kernel/locking/mutex-debug.c
+@@ -57,7 +57,7 @@ void debug_mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter,
+       task->blocked_on = waiter;
+ }
+-void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
++void debug_mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
+                        struct task_struct *task)
+ {
+       DEBUG_LOCKS_WARN_ON(list_empty(&waiter->list));
+@@ -65,7 +65,7 @@ void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
+       DEBUG_LOCKS_WARN_ON(task->blocked_on != waiter);
+       task->blocked_on = NULL;
+-      list_del_init(&waiter->list);
++      INIT_LIST_HEAD(&waiter->list);
+       waiter->task = NULL;
+ }
+diff --git a/kernel/locking/mutex-debug.h b/kernel/locking/mutex-debug.h
+index 1edd3f45a4ec..53e631e1d76d 100644
+--- a/kernel/locking/mutex-debug.h
++++ b/kernel/locking/mutex-debug.h
+@@ -22,7 +22,7 @@ extern void debug_mutex_free_waiter(struct mutex_waiter *waiter);
+ extern void debug_mutex_add_waiter(struct mutex *lock,
+                                  struct mutex_waiter *waiter,
+                                  struct task_struct *task);
+-extern void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
++extern void debug_mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
+                               struct task_struct *task);
+ extern void debug_mutex_unlock(struct mutex *lock);
+ extern void debug_mutex_init(struct mutex *lock, const char *name,
+diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
+index b3da782cdfbd..354151fef06a 100644
+--- a/kernel/locking/mutex.c
++++ b/kernel/locking/mutex.c
+@@ -177,7 +177,7 @@ static inline bool __mutex_waiter_is_first(struct mutex *lock, struct mutex_wait
+  * Add @waiter to a given location in the lock wait_list and set the
+  * FLAG_WAITERS flag if it's the first waiter.
+  */
+-static void __sched
++static void
+ __mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter,
+                  struct list_head *list)
+ {
+@@ -188,6 +188,16 @@ __mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter,
+               __mutex_set_flag(lock, MUTEX_FLAG_WAITERS);
+ }
++static void
++__mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter)
++{
++      list_del(&waiter->list);
++      if (likely(list_empty(&lock->wait_list)))
++              __mutex_clear_flag(lock, MUTEX_FLAGS);
++
++      debug_mutex_remove_waiter(lock, waiter, current);
++}
++
+ /*
+  * Give up ownership to a specific task, when @task = NULL, this is equivalent
+  * to a regular unlock. Sets PICKUP on a handoff, clears HANDOF, preserves
+@@ -1040,9 +1050,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
+                       __ww_mutex_check_waiters(lock, ww_ctx);
+       }
+-      mutex_remove_waiter(lock, &waiter, current);
+-      if (likely(list_empty(&lock->wait_list)))
+-              __mutex_clear_flag(lock, MUTEX_FLAGS);
++      __mutex_remove_waiter(lock, &waiter);
+       debug_mutex_free_waiter(&waiter);
+@@ -1059,7 +1067,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
+ err:
+       __set_current_state(TASK_RUNNING);
+-      mutex_remove_waiter(lock, &waiter, current);
++      __mutex_remove_waiter(lock, &waiter);
+ err_early_kill:
+       spin_unlock(&lock->wait_lock);
+       debug_mutex_free_waiter(&waiter);
+diff --git a/kernel/locking/mutex.h b/kernel/locking/mutex.h
+index 1c2287d3fa71..f0c710b1d192 100644
+--- a/kernel/locking/mutex.h
++++ b/kernel/locking/mutex.h
+@@ -10,12 +10,10 @@
+  * !CONFIG_DEBUG_MUTEXES case. Most of them are NOPs:
+  */
+-#define mutex_remove_waiter(lock, waiter, task) \
+-              __list_del((waiter)->list.prev, (waiter)->list.next)
+-
+ #define debug_mutex_wake_waiter(lock, waiter)         do { } while (0)
+ #define debug_mutex_free_waiter(waiter)                       do { } while (0)
+ #define debug_mutex_add_waiter(lock, waiter, ti)      do { } while (0)
++#define debug_mutex_remove_waiter(lock, waiter, ti)     do { } while (0)
+ #define debug_mutex_unlock(lock)                      do { } while (0)
+ #define debug_mutex_init(lock, name, key)             do { } while (0)
+-- 
+2.30.2
+
index 3e778042c568fbe91fadd7faa7788f78fe4bae15..31edcd352a92d4ea10669f413cbe1d7c2c044e2e 100644 (file)
@@ -6,3 +6,4 @@ rdma-mlx5-recover-from-fatal-event-in-dual-port-mode.patch
 platform-x86-dell-smbios-wmi-fix-oops-on-rmmod-dell_.patch
 ptrace-make-ptrace-fail-if-the-tracee-changed-its-pi.patch
 nvmet-seset-ns-file-when-open-fails.patch
+locking-mutex-clear-mutex_flags-if-wait_list-is-empt.patch