Skip to content

Commit d7c8142

Browse files
Waiman-Longhtejun
authored andcommitted
cgroup/cpuset: Make partition invalid if cpumask change violates exclusivity rule
Currently, changes in "cpust.cpus" of a partition root is not allowed if it violates the sibling cpu exclusivity rule when the check is done in the validate_change() function. That is inconsistent with the other cpuset changes that are always allowed but may make a partition invalid. Update the cpuset code to allow cpumask change even if it violates the sibling cpu exclusivity rule, but invalidate the partition instead just like the other changes. However, other sibling partitions with conflicting cpumask will also be invalidated in order to not violating the exclusivity rule. This behavior is specific to this partition rule violation. Note that a previous commit has made sibling cpu exclusivity rule check the last check of validate_change(). So if -EINVAL is returned, we can be sure that sibling cpu exclusivity rule violation is the only rule that is broken. Signed-off-by: Waiman Long <[email protected]> Signed-off-by: Tejun Heo <[email protected]>
1 parent 74027a6 commit d7c8142

File tree

1 file changed

+60
-9
lines changed

1 file changed

+60
-9
lines changed

kernel/cgroup/cpuset.c

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,7 @@ enum subparts_cmd {
12561256
partcmd_enable, /* Enable partition root */
12571257
partcmd_disable, /* Disable partition root */
12581258
partcmd_update, /* Update parent's subparts_cpus */
1259+
partcmd_invalidate, /* Make partition invalid */
12591260
};
12601261

12611262
static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
@@ -1286,13 +1287,17 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
12861287
* or vice versa. An error code will only be returned if transitioning from
12871288
* invalid to valid violates the exclusivity rule.
12881289
*
1290+
* For partcmd_invalidate, the current partition will be made invalid.
1291+
*
12891292
* The partcmd_enable and partcmd_disable commands are used by
12901293
* update_prstate(). An error code may be returned and the caller will check
12911294
* for error.
12921295
*
12931296
* The partcmd_update command is used by update_cpumasks_hier() with newmask
1294-
* NULL and update_cpumask() with newmask set. The callers won't check for
1295-
* error and so partition_root_state and prs_error will be updated directly.
1297+
* NULL and update_cpumask() with newmask set. The partcmd_invalidate is used
1298+
* by update_cpumask() with NULL newmask. In both cases, the callers won't
1299+
* check for error and so partition_root_state and prs_error will be updated
1300+
* directly.
12961301
*/
12971302
static int update_parent_subparts_cpumask(struct cpuset *cs, int cmd,
12981303
struct cpumask *newmask,
@@ -1320,7 +1325,8 @@ static int update_parent_subparts_cpumask(struct cpuset *cs, int cmd,
13201325
return PERR_CPUSEMPTY;
13211326

13221327
/*
1323-
* new_prs will only be changed for the partcmd_update command.
1328+
* new_prs will only be changed for the partcmd_update and
1329+
* partcmd_invalidate commands.
13241330
*/
13251331
adding = deleting = false;
13261332
old_prs = new_prs = cs->partition_root_state;
@@ -1350,6 +1356,20 @@ static int update_parent_subparts_cpumask(struct cpuset *cs, int cmd,
13501356
deleting = !is_prs_invalid(old_prs) &&
13511357
cpumask_and(tmp->delmask, cs->cpus_allowed,
13521358
parent->subparts_cpus);
1359+
} else if (cmd == partcmd_invalidate) {
1360+
if (is_prs_invalid(old_prs))
1361+
return 0;
1362+
1363+
/*
1364+
* Make the current partition invalid. It is assumed that
1365+
* invalidation is caused by violating cpu exclusivity rule.
1366+
*/
1367+
deleting = cpumask_and(tmp->delmask, cs->cpus_allowed,
1368+
parent->subparts_cpus);
1369+
if (old_prs > 0) {
1370+
new_prs = -old_prs;
1371+
part_error = PERR_NOTEXCL;
1372+
}
13531373
} else if (newmask) {
13541374
/*
13551375
* partcmd_update with newmask:
@@ -1403,6 +1423,7 @@ static int update_parent_subparts_cpumask(struct cpuset *cs, int cmd,
14031423
parent->cpus_allowed);
14041424
adding = cpumask_andnot(tmp->addmask, tmp->addmask,
14051425
parent->subparts_cpus);
1426+
14061427
if ((is_partition_valid(cs) && !parent->nr_subparts_cpus) ||
14071428
(adding &&
14081429
cpumask_subset(parent->effective_cpus, tmp->addmask) &&
@@ -1709,6 +1730,7 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
17091730
{
17101731
int retval;
17111732
struct tmpmasks tmp;
1733+
bool invalidate = false;
17121734

17131735
/* top_cpuset.cpus_allowed tracks cpu_online_mask; it's read-only */
17141736
if (cs == &top_cpuset)
@@ -1736,10 +1758,6 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
17361758
if (cpumask_equal(cs->cpus_allowed, trialcs->cpus_allowed))
17371759
return 0;
17381760

1739-
retval = validate_change(cs, trialcs);
1740-
if (retval < 0)
1741-
return retval;
1742-
17431761
#ifdef CONFIG_CPUMASK_OFFSTACK
17441762
/*
17451763
* Use the cpumasks in trialcs for tmpmasks when they are pointers
@@ -1750,9 +1768,42 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
17501768
tmp.new_cpus = trialcs->cpus_allowed;
17511769
#endif
17521770

1771+
retval = validate_change(cs, trialcs);
1772+
1773+
if ((retval == -EINVAL) && cgroup_subsys_on_dfl(cpuset_cgrp_subsys)) {
1774+
struct cpuset *cp, *parent;
1775+
struct cgroup_subsys_state *css;
1776+
1777+
/*
1778+
* The -EINVAL error code indicates that partition sibling
1779+
* CPU exclusivity rule has been violated. We still allow
1780+
* the cpumask change to proceed while invalidating the
1781+
* partition. However, any conflicting sibling partitions
1782+
* have to be marked as invalid too.
1783+
*/
1784+
invalidate = true;
1785+
rcu_read_lock();
1786+
parent = parent_cs(cs);
1787+
cpuset_for_each_child(cp, css, parent)
1788+
if (is_partition_valid(cp) &&
1789+
cpumask_intersects(trialcs->cpus_allowed, cp->cpus_allowed)) {
1790+
rcu_read_unlock();
1791+
update_parent_subparts_cpumask(cp, partcmd_invalidate, NULL, &tmp);
1792+
rcu_read_lock();
1793+
}
1794+
rcu_read_unlock();
1795+
retval = 0;
1796+
}
1797+
if (retval < 0)
1798+
return retval;
1799+
17531800
if (cs->partition_root_state) {
1754-
update_parent_subparts_cpumask(cs, partcmd_update,
1755-
trialcs->cpus_allowed, &tmp);
1801+
if (invalidate)
1802+
update_parent_subparts_cpumask(cs, partcmd_invalidate,
1803+
NULL, &tmp);
1804+
else
1805+
update_parent_subparts_cpumask(cs, partcmd_update,
1806+
trialcs->cpus_allowed, &tmp);
17561807
}
17571808

17581809
compute_effective_cpumask(trialcs->effective_cpus, trialcs,

0 commit comments

Comments
 (0)