Skip to content

Commit f82f804

Browse files
Juri LelliIngo Molnar
authored andcommitted
sched/deadline: Ensure that updates to exclusive cpusets don't break AC
How we deal with updates to exclusive cpusets is currently broken. As an example, suppose we have an exclusive cpuset composed of two cpus: A[cpu0,cpu1]. We can assign SCHED_DEADLINE task to it up to the allowed bandwidth. If we want now to modify cpusetA's cpumask, we have to check that removing a cpu's amount of bandwidth doesn't break AC guarantees. This thing isn't checked in the current code. This patch fixes the problem above, denying an update if the new cpumask won't have enough bandwidth for SCHED_DEADLINE tasks that are currently active. Signed-off-by: Juri Lelli <juri.lelli@arm.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Li Zefan <lizefan@huawei.com> Cc: cgroups@vger.kernel.org Link: http://lkml.kernel.org/r/5433E6AF.5080105@arm.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 7f51412 commit f82f804

File tree

3 files changed

+31
-0
lines changed

3 files changed

+31
-0
lines changed

include/linux/sched.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,6 +2052,8 @@ static inline void tsk_restore_flags(struct task_struct *task,
20522052
task->flags |= orig_flags & flags;
20532053
}
20542054

2055+
extern int cpuset_cpumask_can_shrink(const struct cpumask *cur,
2056+
const struct cpumask *trial);
20552057
extern int task_can_attach(struct task_struct *p,
20562058
const struct cpumask *cs_cpus_allowed);
20572059
#ifdef CONFIG_SMP

kernel/cpuset.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,16 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
506506
goto out;
507507
}
508508

509+
/*
510+
* We can't shrink if we won't have enough room for SCHED_DEADLINE
511+
* tasks.
512+
*/
513+
ret = -EBUSY;
514+
if (is_cpu_exclusive(cur) &&
515+
!cpuset_cpumask_can_shrink(cur->cpus_allowed,
516+
trial->cpus_allowed))
517+
goto out;
518+
509519
ret = 0;
510520
out:
511521
rcu_read_unlock();

kernel/sched/core.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4650,6 +4650,25 @@ void init_idle(struct task_struct *idle, int cpu)
46504650
#endif
46514651
}
46524652

4653+
int cpuset_cpumask_can_shrink(const struct cpumask *cur,
4654+
const struct cpumask *trial)
4655+
{
4656+
int ret = 1, trial_cpus;
4657+
struct dl_bw *cur_dl_b;
4658+
unsigned long flags;
4659+
4660+
cur_dl_b = dl_bw_of(cpumask_any(cur));
4661+
trial_cpus = cpumask_weight(trial);
4662+
4663+
raw_spin_lock_irqsave(&cur_dl_b->lock, flags);
4664+
if (cur_dl_b->bw != -1 &&
4665+
cur_dl_b->bw * trial_cpus < cur_dl_b->total_bw)
4666+
ret = 0;
4667+
raw_spin_unlock_irqrestore(&cur_dl_b->lock, flags);
4668+
4669+
return ret;
4670+
}
4671+
46534672
int task_can_attach(struct task_struct *p,
46544673
const struct cpumask *cs_cpus_allowed)
46554674
{

0 commit comments

Comments
 (0)