| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Todd Kjos <tkjos@google.com> |
| Date: Fri, 27 Mar 2020 10:04:16 -0700 |
| Subject: Revert "sched/core: Prevent race condition between cpuset and |
| __sched_setscheduler()" |
| |
| This reverts commit 710da3c8ea7dfbd327920afd3831d8c82c42789d. |
| |
| When changing a thread's scheduling priority, binder calls |
| sched_setscheduler_nocheck() while holding the node lock and |
| proc inner lock. This was safe until v5.3 when this change was |
| introduced where cpuset_read_lock() is called in this path |
| which can sleep. |
| |
| This patch was introduced to fix a possible accounting error |
| in sched deadline (potential oversell of CPU bandwidth) due |
| to a race condition between cpusets and __sched_setscheduler(). |
| This is not an issue for Android. |
| |
| This should be fixed in the binder driver, but that may take |
| some time. |
| |
| [CPNOTE: 21/07/21] Lee: Requested status from the author via the bug |
| [CPNOTE: 07/09/21] Lee: Required whilst carrying current Binder PI implementation |
| |
| Bug: 120446518 # OoT |
| Bug: 151861772 |
| Change-Id: Ica1ef71b3cdcdc509b341ea1b57c41f8ee73794a |
| Signed-off-by: Todd Kjos <tkjos@google.com> |
| Signed-off-by: Lee Jones <joneslee@google.com> |
| --- |
| include/linux/cpuset.h | 5 ----- |
| kernel/cgroup/cpuset.c | 11 ----------- |
| kernel/sched/core.c | 20 +++----------------- |
| 3 files changed, 3 insertions(+), 33 deletions(-) |
| |
| diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h |
| --- a/include/linux/cpuset.h |
| +++ b/include/linux/cpuset.h |
| @@ -71,8 +71,6 @@ extern void cpuset_init_smp(void); |
| extern void cpuset_force_rebuild(void); |
| extern void cpuset_update_active_cpus(void); |
| extern void cpuset_wait_for_hotplug(void); |
| -extern void cpuset_read_lock(void); |
| -extern void cpuset_read_unlock(void); |
| extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask); |
| extern bool cpuset_cpus_allowed_fallback(struct task_struct *p); |
| extern nodemask_t cpuset_mems_allowed(struct task_struct *p); |
| @@ -196,9 +194,6 @@ static inline void cpuset_update_active_cpus(void) |
| |
| static inline void cpuset_wait_for_hotplug(void) { } |
| |
| -static inline void cpuset_read_lock(void) { } |
| -static inline void cpuset_read_unlock(void) { } |
| - |
| static inline void cpuset_cpus_allowed(struct task_struct *p, |
| struct cpumask *mask) |
| { |
| diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c |
| --- a/kernel/cgroup/cpuset.c |
| +++ b/kernel/cgroup/cpuset.c |
| @@ -404,17 +404,6 @@ static struct cpuset top_cpuset = { |
| */ |
| |
| DEFINE_STATIC_PERCPU_RWSEM(cpuset_rwsem); |
| - |
| -void cpuset_read_lock(void) |
| -{ |
| - percpu_down_read(&cpuset_rwsem); |
| -} |
| - |
| -void cpuset_read_unlock(void) |
| -{ |
| - percpu_up_read(&cpuset_rwsem); |
| -} |
| - |
| static DEFINE_SPINLOCK(callback_lock); |
| |
| static struct workqueue_struct *cpuset_migrate_mm_wq; |
| diff --git a/kernel/sched/core.c b/kernel/sched/core.c |
| --- a/kernel/sched/core.c |
| +++ b/kernel/sched/core.c |
| @@ -7515,9 +7515,6 @@ static int __sched_setscheduler(struct task_struct *p, |
| return retval; |
| } |
| |
| - if (pi) |
| - cpuset_read_lock(); |
| - |
| /* |
| * Make sure no PI-waiters arrive (or leave) while we are |
| * changing the priority of the task: |
| @@ -7592,8 +7589,6 @@ static int __sched_setscheduler(struct task_struct *p, |
| if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) { |
| policy = oldpolicy = -1; |
| task_rq_unlock(rq, p, &rf); |
| - if (pi) |
| - cpuset_read_unlock(); |
| goto recheck; |
| } |
| |
| @@ -7659,10 +7654,8 @@ static int __sched_setscheduler(struct task_struct *p, |
| head = splice_balance_callbacks(rq); |
| task_rq_unlock(rq, p, &rf); |
| |
| - if (pi) { |
| - cpuset_read_unlock(); |
| + if (pi) |
| rt_mutex_adjust_pi(p); |
| - } |
| |
| /* Run balance callbacks after we've adjusted the PI chain: */ |
| balance_callbacks(rq, head); |
| @@ -7672,8 +7665,6 @@ static int __sched_setscheduler(struct task_struct *p, |
| |
| unlock: |
| task_rq_unlock(rq, p, &rf); |
| - if (pi) |
| - cpuset_read_unlock(); |
| return retval; |
| } |
| |
| @@ -7803,14 +7794,9 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) |
| rcu_read_lock(); |
| retval = -ESRCH; |
| p = find_process_by_pid(pid); |
| - if (likely(p)) |
| - get_task_struct(p); |
| - rcu_read_unlock(); |
| - |
| - if (likely(p)) { |
| + if (p != NULL) |
| retval = sched_setscheduler(p, policy, &lparam); |
| - put_task_struct(p); |
| - } |
| + rcu_read_unlock(); |
| |
| return retval; |
| } |