mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
cgroup/cpuset: Don't allow a child root partition under an isolated parent
Although it is not typical for real users to create a complicated nested partition hierarchy, it is currently allowed to create nested root and isolated partitions. In addition, disabling or invalidating a partition should always be allowed especially when the cpuset is being deleted. With a nested root and isolated partition hierarchy, it is possible that all active housekeeping CPUs can be exhausted when disabling or invalidating a root partition and returning its CPUs to the isolated parent. One way to avoid this problem is to disallow the creation of a root partition under an isolated parent. It is indeed a new limitation imposed on the existing cpuset partition functionality. However an isolated partition is usually a left node where scheduling and some other kernel noises are disabled. It doesn't make much sense to create a child root partition under an isolated parent and remove some CPUs from the set of isolated CPUs again. Creation of a child isolated partition under a root or isolated parent is still allowed. If a partition with child root partitions is converted to isolated, the child root partitions will be invalidated. The cgroup-v2 documentation is also updated to reflect this new limitation. New test cases are added to test_cpuset_prs.sh to verify this new behavior. Some existing test cases are also updated accordingly. Signed-off-by: Waiman Long <longman@redhat.com> Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
parent
db27a748a3
commit
c0189e75d3
|
|
@ -2767,7 +2767,9 @@ Cpuset Interface Files
|
|||
be retained, but behaves more like a "member".
|
||||
|
||||
All possible state transitions among "member", "root" and
|
||||
"isolated" are allowed.
|
||||
"isolated" are allowed with the exception that a local child
|
||||
"root" partition is not allowed to be created under an "isolated"
|
||||
parent partition.
|
||||
|
||||
On read, the "cpuset.cpus.partition" file can show the following
|
||||
values.
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ enum prs_errcode {
|
|||
PERR_HKEEPING,
|
||||
PERR_ACCESS,
|
||||
PERR_REMOTE,
|
||||
PERR_ISOPARENT,
|
||||
};
|
||||
|
||||
/* bits in struct cpuset flags field */
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ static const char * const perr_strings[] = {
|
|||
[PERR_HKEEPING] = "partition config conflicts with housekeeping setup",
|
||||
[PERR_ACCESS] = "Enable partition not permitted",
|
||||
[PERR_REMOTE] = "Have remote partition underneath",
|
||||
[PERR_ISOPARENT] = "Root partition is not allowed with isolated parent",
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -1899,6 +1900,10 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
|
|||
part_error = PERR_CPUSEMPTY;
|
||||
goto write_error;
|
||||
}
|
||||
if ((parent_prs == PRS_ISOLATED) && (old_prs == -PRS_ROOT)) {
|
||||
part_error = PERR_ISOPARENT;
|
||||
goto write_error;
|
||||
}
|
||||
|
||||
/* Check newmask again, whether cpus are available for parent/cs */
|
||||
nocpu |= tasks_nocpu_error(parent, cs, newmask);
|
||||
|
|
@ -1974,6 +1979,13 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
|
|||
adding = cpumask_and(tmp->addmask,
|
||||
cs->effective_xcpus,
|
||||
parent->effective_xcpus);
|
||||
} else if ((parent_prs == PRS_ISOLATED) &&
|
||||
((old_prs == PRS_ROOT) || (old_prs == -PRS_ROOT))) {
|
||||
part_error = PERR_ISOPARENT;
|
||||
if (old_prs == PRS_ROOT) {
|
||||
cpumask_copy(tmp->addmask, cs->effective_xcpus);
|
||||
adding = true;
|
||||
}
|
||||
} else if (is_partition_invalid(cs) && !cpumask_empty(xcpus) &&
|
||||
cpumask_subset(xcpus, parent->effective_xcpus)) {
|
||||
struct cgroup_subsys_state *css;
|
||||
|
|
@ -2927,6 +2939,7 @@ static int update_prstate(struct cpuset *cs, int new_prs)
|
|||
int err = PERR_NONE, old_prs = cs->partition_root_state;
|
||||
struct cpuset *parent = parent_cs(cs);
|
||||
struct tmpmasks tmpmask;
|
||||
int parent_prs = parent->partition_root_state;
|
||||
bool isolcpus_updated = false;
|
||||
bool disable_partition = false;
|
||||
|
||||
|
|
@ -2972,6 +2985,14 @@ static int update_prstate(struct cpuset *cs, int new_prs)
|
|||
enum partition_cmd cmd = (new_prs == PRS_ROOT)
|
||||
? partcmd_enable : partcmd_enablei;
|
||||
|
||||
/*
|
||||
* It is not allowed to create a root partition under
|
||||
* an isolated parent partition.
|
||||
*/
|
||||
if ((new_prs == PRS_ROOT) && (parent_prs == PRS_ISOLATED)) {
|
||||
err = PERR_ISOPARENT;
|
||||
goto out;
|
||||
}
|
||||
err = update_parent_effective_cpumask(cs, cmd, NULL, &tmpmask);
|
||||
} else {
|
||||
err = remote_partition_enable(cs, new_prs, &tmpmask);
|
||||
|
|
@ -2985,12 +3006,15 @@ static int update_prstate(struct cpuset *cs, int new_prs)
|
|||
* Need to update isolated_cpus.
|
||||
*/
|
||||
if (prstate_housekeeping_conflict(new_prs, parent_prs,
|
||||
cs->effective_xcpus, NULL)) {
|
||||
disable_partition = true;
|
||||
cs->effective_xcpus, NULL))
|
||||
err = PERR_HKEEPING;
|
||||
} else {
|
||||
else if (parent_prs == PRS_ISOLATED)
|
||||
err = PERR_ISOPARENT;
|
||||
|
||||
if (!err)
|
||||
isolcpus_updated = true;
|
||||
}
|
||||
else
|
||||
disable_partition = true;
|
||||
} else {
|
||||
/*
|
||||
* Switching back to member is always allowed even if it
|
||||
|
|
|
|||
|
|
@ -288,16 +288,14 @@ TEST_MATRIX=(
|
|||
A1:P0|A2:P1|A3:P0|B1:P1"
|
||||
" C0-3 C1-3 C3 C4 X2-3 X2-3:P1 P2 P1 0 A1:0-1|A2:2|A3:3|B1:4 \
|
||||
A1:P0|A2:P1|A3:P2|B1:P1 2-4|3"
|
||||
" C0-4 C1-4 C2-4 . X2-4 X2-4:P2 X4:P1 . 0 A1:0-1|A2:2-3|A3:4 \
|
||||
A1:P0|A2:P2|A3:P1 2-4|2-3"
|
||||
" C0-4 C1-4 C2-4 . X2-4 X2-4:P2 X3-4:P1 . 0 A1:0-1|A2:2|A3:3-4 \
|
||||
A1:P0|A2:P2|A3:P1 2"
|
||||
" C1-6:P1 C3-6:P1 C5-6:P1 . . P2 . . 0 A1:1-2|A2:3-6|A3:5-6 \
|
||||
A1:P1|A2:P2|A3:P-1 3-6"
|
||||
" C1-4:X2-4 C2-4:X3-4:P1 C3-4:X4:P2 \
|
||||
. . X5 . . 0 A1:1-4|A2:2-4|A3:3-4 \
|
||||
A1:P0|A2:P-1|A3:P-2 ."
|
||||
" C0-4:X2-4 C1-4:X2-4:P2 C2-4:X4:P1 \
|
||||
. . . X1 . 0 A1:0-1|A2:2-4|A3:2-4 \
|
||||
A1:P0|A2:P2|A3:P-1 2-4"
|
||||
" C1-4:X2-4 C1-4:X3-4:P1 C3-4:X4:P2 \
|
||||
. . . X1 . 0 A1:1-2|A2:3-4|A3:3-4 \
|
||||
A1:P0|A2:P1|A3:P-2 ."
|
||||
" CX1-3:P1 CX1-3 CX1-3 . . . P1 . 0 A1:1-3|A2:1-3|A3:1-3 \
|
||||
A1:P1|A2:P0|A3:P-1"
|
||||
|
||||
|
|
@ -331,8 +329,8 @@ TEST_MATRIX=(
|
|||
" C0-3:X1-3:P2 C1-3:X2-3:P2 C2-3:X3:P2 \
|
||||
. . C4:X . . 0 A1:1-3|A2:1-3|A3:2-3|XA2:|XA3: A1:P2|A2:P-2|A3:P-2 1-3"
|
||||
# Local partition CPU change tests
|
||||
" C0-5:P2 C4-5:P1 . . . C3-5 . . 0 A1:0-2|A2:3-5 A1:P2|A2:P1 0-2"
|
||||
" C0-5:P2 C4-5:P1 . . C1-5 . . . 0 A1:1-3|A2:4-5 A1:P2|A2:P1 1-3"
|
||||
" C0-5:P1 C4-5:P2 . . . C3-5 . . 0 A1:0-2|A2:3-5 A1:P1|A2:P2 3-5"
|
||||
" C0-5:P1 C4-5:P2 . . C1-5 . . . 0 A1:1-3|A2:4-5 A1:P1|A2:P2 4-5"
|
||||
|
||||
# cpus_allowed/exclusive_cpus update tests
|
||||
" C0-3:X2-3 C1-3:X2-3 C2-3:X2-3 \
|
||||
|
|
@ -430,6 +428,13 @@ TEST_MATRIX=(
|
|||
# cpuset.cpus can become empty with task in it as it inherits parent's effective CPUs
|
||||
" C1-3 C2 . . . T:C . . 0 A1:1-3|A2:1-3"
|
||||
|
||||
# Creation of root partition under an isolated partition is not allowed
|
||||
" C1-3:P2 C2 . . . P1 . . 0 A1:1-3|A2:2 A1:P2|A2:P-1 1-3"
|
||||
" C1-3:P2 C2 . . . P2 . . 0 A1:1,3|A2:2 A1:P2|A2:P2 1-3"
|
||||
" C1-3:P2 C2:P2 . . . P1 . . 0 A1:1-3|A2:2 A1:P2|A2:P-1 1-3"
|
||||
" C1-3:P2 C2:P1 . . . C2-3 . . 0 A1:1-3|A2:2-3 A1:P2|A2:P-1 1-3"
|
||||
|
||||
#
|
||||
# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
|
||||
# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
|
||||
# Failure cases:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user