* Returns: true if CPU exclusivity conflict exists, false otherwise
*
* Conflict detection rules:
* 1. If either cpuset is CPU exclusive, they must be mutually exclusive
* 2. exclusive_cpus masks cannot intersect between cpusets
- * 3. The allowed CPUs of one cpuset cannot be a subset of another's exclusive
CPUs
+ * 3. The allowed CPUs of a sibling cpuset cannot be a subset of the new
exclusive CPUs
*/
-static inline bool cpus_excl_conflict(struct cpuset *cs1, struct cpuset *cs2)
+static inline bool cpus_excl_conflict(struct cpuset *trial, struct cpuset
*sibling,
+ bool new_xcpus)
{
/* If either cpuset is exclusive, check if they are mutually exclusive
*/
- if (is_cpu_exclusive(cs1) || is_cpu_exclusive(cs2))
- return !cpusets_are_exclusive(cs1, cs2);
+ if (is_cpu_exclusive(trial) || is_cpu_exclusive(sibling))
+ return !cpusets_are_exclusive(trial, sibling);
/* Exclusive_cpus cannot intersect */
- if (cpumask_intersects(cs1->exclusive_cpus, cs2->exclusive_cpus))
+ if (cpumask_intersects(trial->exclusive_cpus, sibling->exclusive_cpus))
return true;
- /* The cpus_allowed of one cpuset cannot be a subset of another cpuset's exclusive_cpus */
- if (!cpumask_empty(cs1->cpus_allowed) &&
- cpumask_subset(cs1->cpus_allowed, cs2->exclusive_cpus))
- return true;
-
- if (!cpumask_empty(cs2->cpus_allowed) &&
- cpumask_subset(cs2->cpus_allowed, cs1->exclusive_cpus))
+ /* The cpus_allowed of a sibling cpuset cannot be a subset of the new
exclusive_cpus */
+ if (new_xcpus && !cpumask_empty(sibling->cpus_allowed) &&
+ cpumask_subset(sibling->cpus_allowed, trial->exclusive_cpus))
return true;
return false;
@@ -672,6 +670,7 @@ static int validate_change(struct cpuset *cur, struct
cpuset *trial)
{
struct cgroup_subsys_state *css;
struct cpuset *c, *par;
+ bool new_xcpus;
int ret = 0;
rcu_read_lock();
@@ -728,10 +727,11 @@ static int validate_change(struct cpuset *cur, struct
cpuset *trial)
* overlap. exclusive_cpus cannot overlap with each other if set.
*/
ret = -EINVAL;
+ new_xcpus = !cpumask_equal(cur->exclusive_cpus, trial->exclusive_cpus);
cpuset_for_each_child(c, css, par) {
if (c == cur)
continue;
- if (cpus_excl_conflict(trial, c))
+ if (cpus_excl_conflict(trial, c, new_xcpus))
goto out;
if (mems_excl_conflict(trial, c))
goto out;