From 584d38f189e1f88db447c5baa6f5473294124701 Mon Sep 17 00:00:00 2001 From: Olav Haugan Date: Wed, 7 Dec 2016 16:34:49 -0800 Subject: sched/core: Prevent (user) space tasks from affining to isolated cpus We don't want user space tasks to run on isolated cpus. If the affinity mask that the user space task is trying to set only includes online cpus that are isolated return error. Also ensure that tasks do not get stuck on isolated cores. We are not properly updating the mask that we check against the current CPU so we might end up thinking we can run on the current CPU. Fix this. Change-Id: I078d01e63860d1fc60fc96eb0c739c0f680ae983 Signed-off-by: Olav Haugan --- kernel/sched/core.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index d7846edd7a79..d59cae164431 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1248,15 +1248,16 @@ static int __set_cpus_allowed_ptr(struct task_struct *p, goto out; cpumask_andnot(&allowed_mask, new_mask, cpu_isolated_mask); + cpumask_and(&allowed_mask, &allowed_mask, cpu_active_mask); - dest_cpu = cpumask_any_and(cpu_active_mask, &allowed_mask); + dest_cpu = cpumask_any(&allowed_mask); if (dest_cpu >= nr_cpu_ids) { - dest_cpu = cpumask_any_and(cpu_active_mask, new_mask); + cpumask_and(&allowed_mask, cpu_active_mask, new_mask); + dest_cpu = cpumask_any(&allowed_mask); if (dest_cpu >= nr_cpu_ids) { ret = -EINVAL; goto out; } - cpumask_copy(&allowed_mask, new_mask); } do_set_cpus_allowed(p, new_mask); @@ -4635,6 +4636,8 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask) cpumask_var_t cpus_allowed, new_mask; struct task_struct *p; int retval; + int dest_cpu; + cpumask_t allowed_mask; rcu_read_lock(); @@ -4696,20 +4699,26 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask) } #endif again: - retval = __set_cpus_allowed_ptr(p, new_mask, true); - - if (!retval) { - cpuset_cpus_allowed(p, cpus_allowed); - if (!cpumask_subset(new_mask, cpus_allowed)) { - /* - * We must have raced with a concurrent cpuset - * update. Just reset the cpus_allowed to the - * cpuset's cpus_allowed - */ - cpumask_copy(new_mask, cpus_allowed); - goto again; + cpumask_andnot(&allowed_mask, new_mask, cpu_isolated_mask); + dest_cpu = cpumask_any_and(cpu_active_mask, &allowed_mask); + if (dest_cpu < nr_cpu_ids) { + retval = __set_cpus_allowed_ptr(p, new_mask, true); + if (!retval) { + cpuset_cpus_allowed(p, cpus_allowed); + if (!cpumask_subset(new_mask, cpus_allowed)) { + /* + * We must have raced with a concurrent cpuset + * update. Just reset the cpus_allowed to the + * cpuset's cpus_allowed + */ + cpumask_copy(new_mask, cpus_allowed); + goto again; + } } + } else { + retval = -EINVAL; } + out_free_new_mask: free_cpumask_var(new_mask); out_free_cpus_allowed: -- cgit v1.2.3 From 8cf404403a00039b63859397e269b7fe26bd2bef Mon Sep 17 00:00:00 2001 From: Olav Haugan Date: Wed, 7 Dec 2016 16:36:14 -0800 Subject: sched/core: Fix race condition in clearing hmp request There is a race condition between clearing an HMP request for active migration and the actual active migration. Active migration can he half-way through doing the migration when the HMP request can be cleared by another core. Move clearing of HMP request to the stopper thread to avoid this. Change-Id: I6d73b8f246ae3754ab60984af198333fd284ae16 Signed-off-by: Olav Haugan --- kernel/sched/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index d59cae164431..13990fa6f9cf 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5609,6 +5609,7 @@ int do_isolation_work_cpu_stop(void *data) */ nohz_balance_clear_nohz_mask(cpu); + clear_hmp_request(cpu); local_irq_enable(); return 0; } @@ -5733,7 +5734,6 @@ int sched_isolate_cpu(int cpu) migrate_sync_cpu(cpu, cpumask_first(&avail_cpus)); stop_cpus(cpumask_of(cpu), do_isolation_work_cpu_stop, 0); - clear_hmp_request(cpu); calc_load_migrate(rq); update_max_interval(); -- cgit v1.2.3