mirror of
https://github.com/torvalds/linux.git
synced 2024-11-01 04:53:36 +01:00
cgroup: Changes for v6.7
* cpuset now supports remote partitions where CPUs can be reserved for exclusive use down the tree without requiring all the intermediate nodes to be partitions. This makes it easier to use partitions without modifying existing cgroup hierarchy. * cpuset partition configuration behavior improvement. * cgroup_favordynmods= boot param added to allow setting the flag on boot on cgroup1. * Misc code and doc updates. -----BEGIN PGP SIGNATURE----- iIQEABYIACwWIQTfIjM1kS57o3GsC/uxYfJx3gVYGQUCZUBUKA4cdGpAa2VybmVs Lm9yZwAKCRCxYfJx3gVYGWfMAP9WP+Z21qzzL2bY5I5kOxu+rD2fF9ORk7azILrI c3gXSQD/bdxNWcdtrCQMvs+ToNEJvqDFxrmgG5uRUF8Ea+FCtQ8= =gZj2 -----END PGP SIGNATURE----- Merge tag 'cgroup-for-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup Pull cgroup updates from Tejun Heo: - cpuset now supports remote partitions where CPUs can be reserved for exclusive use down the tree without requiring all the intermediate nodes to be partitions. This makes it easier to use partitions without modifying existing cgroup hierarchy. - cpuset partition configuration behavior improvement - cgroup_favordynmods= boot param added to allow setting the flag on boot on cgroup1 - Misc code and doc updates * tag 'cgroup-for-6.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: docs/cgroup: Add the list of threaded controllers to cgroup-v2.rst cgroup: use legacy_name for cgroup v1 disable info cgroup/cpuset: Cleanup signedness issue in cpu_exclusive_check() cgroup/cpuset: Enable invalid to valid local partition transition cgroup: add cgroup_favordynmods= command-line option cgroup/cpuset: Extend test_cpuset_prs.sh to test remote partition cgroup/cpuset: Documentation update for partition cgroup/cpuset: Check partition conflict with housekeeping setup cgroup/cpuset: Introduce remote partition cgroup/cpuset: Add cpuset.cpus.exclusive for v2 cgroup/cpuset: Add cpuset.cpus.exclusive.effective for v2 cgroup/cpuset: Fix load balance state in update_partition_sd_lb() cgroup: Avoid extra dereference in css_populate_dir() cgroup: Check for ret during cgroup1_base_files cft addition
This commit is contained in:
commit
5a6a09e971
5 changed files with 1439 additions and 520 deletions
|
@ -364,6 +364,13 @@ constraint, a threaded controller must be able to handle competition
|
|||
between threads in a non-leaf cgroup and its child cgroups. Each
|
||||
threaded controller defines how such competitions are handled.
|
||||
|
||||
Currently, the following controllers are threaded and can be enabled
|
||||
in a threaded cgroup::
|
||||
|
||||
- cpu
|
||||
- cpuset
|
||||
- perf_event
|
||||
- pids
|
||||
|
||||
[Un]populated Notification
|
||||
--------------------------
|
||||
|
@ -2226,6 +2233,49 @@ Cpuset Interface Files
|
|||
|
||||
Its value will be affected by memory nodes hotplug events.
|
||||
|
||||
cpuset.cpus.exclusive
|
||||
A read-write multiple values file which exists on non-root
|
||||
cpuset-enabled cgroups.
|
||||
|
||||
It lists all the exclusive CPUs that are allowed to be used
|
||||
to create a new cpuset partition. Its value is not used
|
||||
unless the cgroup becomes a valid partition root. See the
|
||||
"cpuset.cpus.partition" section below for a description of what
|
||||
a cpuset partition is.
|
||||
|
||||
When the cgroup becomes a partition root, the actual exclusive
|
||||
CPUs that are allocated to that partition are listed in
|
||||
"cpuset.cpus.exclusive.effective" which may be different
|
||||
from "cpuset.cpus.exclusive". If "cpuset.cpus.exclusive"
|
||||
has previously been set, "cpuset.cpus.exclusive.effective"
|
||||
is always a subset of it.
|
||||
|
||||
Users can manually set it to a value that is different from
|
||||
"cpuset.cpus". The only constraint in setting it is that the
|
||||
list of CPUs must be exclusive with respect to its sibling.
|
||||
|
||||
For a parent cgroup, any one of its exclusive CPUs can only
|
||||
be distributed to at most one of its child cgroups. Having an
|
||||
exclusive CPU appearing in two or more of its child cgroups is
|
||||
not allowed (the exclusivity rule). A value that violates the
|
||||
exclusivity rule will be rejected with a write error.
|
||||
|
||||
The root cgroup is a partition root and all its available CPUs
|
||||
are in its exclusive CPU set.
|
||||
|
||||
cpuset.cpus.exclusive.effective
|
||||
A read-only multiple values file which exists on all non-root
|
||||
cpuset-enabled cgroups.
|
||||
|
||||
This file shows the effective set of exclusive CPUs that
|
||||
can be used to create a partition root. The content of this
|
||||
file will always be a subset of "cpuset.cpus" and its parent's
|
||||
"cpuset.cpus.exclusive.effective" if its parent is not the root
|
||||
cgroup. It will also be a subset of "cpuset.cpus.exclusive"
|
||||
if it is set. If "cpuset.cpus.exclusive" is not set, it is
|
||||
treated to have an implicit value of "cpuset.cpus" in the
|
||||
formation of local partition.
|
||||
|
||||
cpuset.cpus.partition
|
||||
A read-write single value file which exists on non-root
|
||||
cpuset-enabled cgroups. This flag is owned by the parent cgroup
|
||||
|
@ -2239,26 +2289,41 @@ Cpuset Interface Files
|
|||
"isolated" Partition root without load balancing
|
||||
========== =====================================
|
||||
|
||||
The root cgroup is always a partition root and its state
|
||||
cannot be changed. All other non-root cgroups start out as
|
||||
"member".
|
||||
A cpuset partition is a collection of cpuset-enabled cgroups with
|
||||
a partition root at the top of the hierarchy and its descendants
|
||||
except those that are separate partition roots themselves and
|
||||
their descendants. A partition has exclusive access to the
|
||||
set of exclusive CPUs allocated to it. Other cgroups outside
|
||||
of that partition cannot use any CPUs in that set.
|
||||
|
||||
There are two types of partitions - local and remote. A local
|
||||
partition is one whose parent cgroup is also a valid partition
|
||||
root. A remote partition is one whose parent cgroup is not a
|
||||
valid partition root itself. Writing to "cpuset.cpus.exclusive"
|
||||
is optional for the creation of a local partition as its
|
||||
"cpuset.cpus.exclusive" file will assume an implicit value that
|
||||
is the same as "cpuset.cpus" if it is not set. Writing the
|
||||
proper "cpuset.cpus.exclusive" values down the cgroup hierarchy
|
||||
before the target partition root is mandatory for the creation
|
||||
of a remote partition.
|
||||
|
||||
Currently, a remote partition cannot be created under a local
|
||||
partition. All the ancestors of a remote partition root except
|
||||
the root cgroup cannot be a partition root.
|
||||
|
||||
The root cgroup is always a partition root and its state cannot
|
||||
be changed. All other non-root cgroups start out as "member".
|
||||
|
||||
When set to "root", the current cgroup is the root of a new
|
||||
partition or scheduling domain that comprises itself and all
|
||||
its descendants except those that are separate partition roots
|
||||
themselves and their descendants.
|
||||
partition or scheduling domain. The set of exclusive CPUs is
|
||||
determined by the value of its "cpuset.cpus.exclusive.effective".
|
||||
|
||||
When set to "isolated", the CPUs in that partition root will
|
||||
When set to "isolated", the CPUs in that partition will
|
||||
be in an isolated state without any load balancing from the
|
||||
scheduler. Tasks placed in such a partition with multiple
|
||||
CPUs should be carefully distributed and bound to each of the
|
||||
individual CPUs for optimal performance.
|
||||
|
||||
The value shown in "cpuset.cpus.effective" of a partition root
|
||||
is the CPUs that the partition root can dedicate to a potential
|
||||
new child partition root. The new child subtracts available
|
||||
CPUs from its parent "cpuset.cpus.effective".
|
||||
|
||||
A partition root ("root" or "isolated") can be in one of the
|
||||
two possible states - valid or invalid. An invalid partition
|
||||
root is in a degraded state where some state information may
|
||||
|
@ -2281,37 +2346,33 @@ Cpuset Interface Files
|
|||
In the case of an invalid partition root, a descriptive string on
|
||||
why the partition is invalid is included within parentheses.
|
||||
|
||||
For a partition root to become valid, the following conditions
|
||||
For a local partition root to be valid, the following conditions
|
||||
must be met.
|
||||
|
||||
1) The "cpuset.cpus" is exclusive with its siblings , i.e. they
|
||||
are not shared by any of its siblings (exclusivity rule).
|
||||
2) The parent cgroup is a valid partition root.
|
||||
3) The "cpuset.cpus" is not empty and must contain at least
|
||||
one of the CPUs from parent's "cpuset.cpus", i.e. they overlap.
|
||||
4) The "cpuset.cpus.effective" cannot be empty unless there is
|
||||
1) The parent cgroup is a valid partition root.
|
||||
2) The "cpuset.cpus.exclusive.effective" file cannot be empty,
|
||||
though it may contain offline CPUs.
|
||||
3) The "cpuset.cpus.effective" cannot be empty unless there is
|
||||
no task associated with this partition.
|
||||
|
||||
External events like hotplug or changes to "cpuset.cpus" can
|
||||
cause a valid partition root to become invalid and vice versa.
|
||||
Note that a task cannot be moved to a cgroup with empty
|
||||
"cpuset.cpus.effective".
|
||||
For a remote partition root to be valid, all the above conditions
|
||||
except the first one must be met.
|
||||
|
||||
For a valid partition root with the sibling cpu exclusivity
|
||||
rule enabled, changes made to "cpuset.cpus" that violate the
|
||||
exclusivity rule will invalidate the partition as well as its
|
||||
sibling partitions with conflicting cpuset.cpus values. So
|
||||
care must be taking in changing "cpuset.cpus".
|
||||
External events like hotplug or changes to "cpuset.cpus" or
|
||||
"cpuset.cpus.exclusive" can cause a valid partition root to
|
||||
become invalid and vice versa. Note that a task cannot be
|
||||
moved to a cgroup with empty "cpuset.cpus.effective".
|
||||
|
||||
A valid non-root parent partition may distribute out all its CPUs
|
||||
to its child partitions when there is no task associated with it.
|
||||
to its child local partitions when there is no task associated
|
||||
with it.
|
||||
|
||||
Care must be taken to change a valid partition root to
|
||||
"member" as all its child partitions, if present, will become
|
||||
Care must be taken to change a valid partition root to "member"
|
||||
as all its child local partitions, if present, will become
|
||||
invalid causing disruption to tasks running in those child
|
||||
partitions. These inactivated partitions could be recovered if
|
||||
their parent is switched back to a partition root with a proper
|
||||
set of "cpuset.cpus".
|
||||
value in "cpuset.cpus" or "cpuset.cpus.exclusive".
|
||||
|
||||
Poll and inotify events are triggered whenever the state of
|
||||
"cpuset.cpus.partition" changes. That includes changes caused
|
||||
|
@ -2321,6 +2382,11 @@ Cpuset Interface Files
|
|||
to "cpuset.cpus.partition" without the need to do continuous
|
||||
polling.
|
||||
|
||||
A user can pre-configure certain CPUs to an isolated state
|
||||
with load balancing disabled at boot time with the "isolcpus"
|
||||
kernel boot command line option. If those CPUs are to be put
|
||||
into a partition, they have to be used in an isolated partition.
|
||||
|
||||
|
||||
Device controller
|
||||
-----------------
|
||||
|
|
|
@ -580,6 +580,10 @@
|
|||
named mounts. Specifying both "all" and "named" disables
|
||||
all v1 hierarchies.
|
||||
|
||||
cgroup_favordynmods= [KNL] Enable or Disable favordynmods.
|
||||
Format: { "true" | "false" }
|
||||
Defaults to the value of CONFIG_CGROUP_FAVOR_DYNMODS.
|
||||
|
||||
cgroup.memory= [KNL] Pass options to the cgroup memory controller.
|
||||
Format: <string>
|
||||
nosocket -- Disable socket memory accounting.
|
||||
|
|
|
@ -207,6 +207,8 @@ static u16 have_exit_callback __read_mostly;
|
|||
static u16 have_release_callback __read_mostly;
|
||||
static u16 have_canfork_callback __read_mostly;
|
||||
|
||||
static bool have_favordynmods __ro_after_init = IS_ENABLED(CONFIG_CGROUP_FAVOR_DYNMODS);
|
||||
|
||||
/* cgroup namespace for init task */
|
||||
struct cgroup_namespace init_cgroup_ns = {
|
||||
.ns.count = REFCOUNT_INIT(2),
|
||||
|
@ -1350,7 +1352,9 @@ static void cgroup_destroy_root(struct cgroup_root *root)
|
|||
cgroup_root_count--;
|
||||
}
|
||||
|
||||
cgroup_favor_dynmods(root, false);
|
||||
if (!have_favordynmods)
|
||||
cgroup_favor_dynmods(root, false);
|
||||
|
||||
cgroup_exit_root_id(root);
|
||||
|
||||
cgroup_unlock();
|
||||
|
@ -1719,20 +1723,22 @@ static int css_populate_dir(struct cgroup_subsys_state *css)
|
|||
|
||||
if (!css->ss) {
|
||||
if (cgroup_on_dfl(cgrp)) {
|
||||
ret = cgroup_addrm_files(&cgrp->self, cgrp,
|
||||
ret = cgroup_addrm_files(css, cgrp,
|
||||
cgroup_base_files, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (cgroup_psi_enabled()) {
|
||||
ret = cgroup_addrm_files(&cgrp->self, cgrp,
|
||||
ret = cgroup_addrm_files(css, cgrp,
|
||||
cgroup_psi_files, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
cgroup_addrm_files(css, cgrp,
|
||||
cgroup1_base_files, true);
|
||||
ret = cgroup_addrm_files(css, cgrp,
|
||||
cgroup1_base_files, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
list_for_each_entry(cfts, &css->ss->cfts, node) {
|
||||
|
@ -2243,9 +2249,9 @@ static int cgroup_init_fs_context(struct fs_context *fc)
|
|||
fc->user_ns = get_user_ns(ctx->ns->user_ns);
|
||||
fc->global = true;
|
||||
|
||||
#ifdef CONFIG_CGROUP_FAVOR_DYNMODS
|
||||
ctx->flags |= CGRP_ROOT_FAVOR_DYNMODS;
|
||||
#endif
|
||||
if (have_favordynmods)
|
||||
ctx->flags |= CGRP_ROOT_FAVOR_DYNMODS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -6121,7 +6127,7 @@ int __init cgroup_init(void)
|
|||
|
||||
if (cgroup1_ssid_disabled(ssid))
|
||||
pr_info("Disabling %s control group subsystem in v1 mounts\n",
|
||||
ss->name);
|
||||
ss->legacy_name);
|
||||
|
||||
cgrp_dfl_root.subsys_mask |= 1 << ss->id;
|
||||
|
||||
|
@ -6764,6 +6770,12 @@ static int __init enable_cgroup_debug(char *str)
|
|||
}
|
||||
__setup("cgroup_debug", enable_cgroup_debug);
|
||||
|
||||
static int __init cgroup_favordynmods_setup(char *str)
|
||||
{
|
||||
return (kstrtobool(str, &have_favordynmods) == 0);
|
||||
}
|
||||
__setup("cgroup_favordynmods=", cgroup_favordynmods_setup);
|
||||
|
||||
/**
|
||||
* css_tryget_online_from_dir - get corresponding css from a cgroup dentry
|
||||
* @dentry: directory dentry of interest
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3,7 +3,7 @@
|
|||
#
|
||||
# Test for cpuset v2 partition root state (PRS)
|
||||
#
|
||||
# The sched verbose flag is set, if available, so that the console log
|
||||
# The sched verbose flag can be optionally set so that the console log
|
||||
# can be examined for the correct setting of scheduling domain.
|
||||
#
|
||||
|
||||
|
@ -22,27 +22,27 @@ WAIT_INOTIFY=$(cd $(dirname $0); pwd)/wait_inotify
|
|||
# Find cgroup v2 mount point
|
||||
CGROUP2=$(mount -t cgroup2 | head -1 | awk -e '{print $3}')
|
||||
[[ -n "$CGROUP2" ]] || skip_test "Cgroup v2 mount point not found!"
|
||||
SUBPARTS_CPUS=$CGROUP2/.__DEBUG__.cpuset.cpus.subpartitions
|
||||
CPULIST=$(cat $CGROUP2/cpuset.cpus.effective)
|
||||
|
||||
CPUS=$(lscpu | grep "^CPU(s):" | sed -e "s/.*:[[:space:]]*//")
|
||||
[[ $CPUS -lt 8 ]] && skip_test "Test needs at least 8 cpus available!"
|
||||
NR_CPUS=$(lscpu | grep "^CPU(s):" | sed -e "s/.*:[[:space:]]*//")
|
||||
[[ $NR_CPUS -lt 8 ]] && skip_test "Test needs at least 8 cpus available!"
|
||||
|
||||
# Set verbose flag and delay factor
|
||||
PROG=$1
|
||||
VERBOSE=
|
||||
VERBOSE=0
|
||||
DELAY_FACTOR=1
|
||||
SCHED_DEBUG=
|
||||
while [[ "$1" = -* ]]
|
||||
do
|
||||
case "$1" in
|
||||
-v) VERBOSE=1
|
||||
-v) ((VERBOSE++))
|
||||
# Enable sched/verbose can slow thing down
|
||||
[[ $DELAY_FACTOR -eq 1 ]] &&
|
||||
DELAY_FACTOR=2
|
||||
break
|
||||
;;
|
||||
-d) DELAY_FACTOR=$2
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*) echo "Usage: $PROG [-v] [-d <delay-factor>"
|
||||
exit
|
||||
|
@ -52,7 +52,7 @@ do
|
|||
done
|
||||
|
||||
# Set sched verbose flag if available when "-v" option is specified
|
||||
if [[ -n "$VERBOSE" && -d /sys/kernel/debug/sched ]]
|
||||
if [[ $VERBOSE -gt 0 && -d /sys/kernel/debug/sched ]]
|
||||
then
|
||||
# Used to restore the original setting during cleanup
|
||||
SCHED_DEBUG=$(cat /sys/kernel/debug/sched/verbose)
|
||||
|
@ -61,14 +61,26 @@ fi
|
|||
|
||||
cd $CGROUP2
|
||||
echo +cpuset > cgroup.subtree_control
|
||||
|
||||
#
|
||||
# If cpuset has been set up and used in child cgroups, we may not be able to
|
||||
# create partition under root cgroup because of the CPU exclusivity rule.
|
||||
# So we are going to skip the test if this is the case.
|
||||
#
|
||||
[[ -d test ]] || mkdir test
|
||||
cd test
|
||||
echo 0-6 > test/cpuset.cpus
|
||||
echo root > test/cpuset.cpus.partition
|
||||
cat test/cpuset.cpus.partition | grep -q invalid
|
||||
RESULT=$?
|
||||
echo member > test/cpuset.cpus.partition
|
||||
echo "" > test/cpuset.cpus
|
||||
[[ $RESULT -eq 0 ]] && skip_test "Child cgroups are using cpuset!"
|
||||
|
||||
cleanup()
|
||||
{
|
||||
online_cpus
|
||||
cd $CGROUP2
|
||||
rmdir A1/A2/A3 A1/A2 A1 B1 > /dev/null 2>&1
|
||||
cd ..
|
||||
rmdir test > /dev/null 2>&1
|
||||
[[ -n "$SCHED_DEBUG" ]] &&
|
||||
echo "$SCHED_DEBUG" > /sys/kernel/debug/sched/verbose
|
||||
|
@ -103,7 +115,7 @@ test_partition()
|
|||
[[ $? -eq 0 ]] || exit 1
|
||||
ACTUAL_VAL=$(cat cpuset.cpus.partition)
|
||||
[[ $ACTUAL_VAL != $EXPECTED_VAL ]] && {
|
||||
echo "cpuset.cpus.partition: expect $EXPECTED_VAL, found $EXPECTED_VAL"
|
||||
echo "cpuset.cpus.partition: expect $EXPECTED_VAL, found $ACTUAL_VAL"
|
||||
echo "Test FAILED"
|
||||
exit 1
|
||||
}
|
||||
|
@ -114,7 +126,7 @@ test_effective_cpus()
|
|||
EXPECTED_VAL=$1
|
||||
ACTUAL_VAL=$(cat cpuset.cpus.effective)
|
||||
[[ "$ACTUAL_VAL" != "$EXPECTED_VAL" ]] && {
|
||||
echo "cpuset.cpus.effective: expect '$EXPECTED_VAL', found '$EXPECTED_VAL'"
|
||||
echo "cpuset.cpus.effective: expect '$EXPECTED_VAL', found '$ACTUAL_VAL'"
|
||||
echo "Test FAILED"
|
||||
exit 1
|
||||
}
|
||||
|
@ -139,6 +151,7 @@ test_add_proc()
|
|||
#
|
||||
test_isolated()
|
||||
{
|
||||
cd $CGROUP2/test
|
||||
echo 2-3 > cpuset.cpus
|
||||
TYPE=$(cat cpuset.cpus.partition)
|
||||
[[ $TYPE = member ]] || echo member > cpuset.cpus.partition
|
||||
|
@ -203,125 +216,220 @@ test_isolated()
|
|||
#
|
||||
# Cgroup test hierarchy
|
||||
#
|
||||
# test -- A1 -- A2 -- A3
|
||||
# \- B1
|
||||
# root -- A1 -- A2 -- A3
|
||||
# +- B1
|
||||
#
|
||||
# P<v> = set cpus.partition (0:member, 1:root, 2:isolated, -1:root invalid)
|
||||
# C<l> = add cpu-list
|
||||
# P<v> = set cpus.partition (0:member, 1:root, 2:isolated)
|
||||
# C<l> = add cpu-list to cpuset.cpus
|
||||
# X<l> = add cpu-list to cpuset.cpus.exclusive
|
||||
# S<p> = use prefix in subtree_control
|
||||
# T = put a task into cgroup
|
||||
# O<c>-<v> = Write <v> to CPU online file of <c>
|
||||
# O<c>=<v> = Write <v> to CPU online file of <c>
|
||||
#
|
||||
SETUP_A123_PARTITIONS="C1-3:P1:S+ C2-3:P1:S+ C3:P1"
|
||||
TEST_MATRIX=(
|
||||
# test old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate
|
||||
# ---- ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------
|
||||
" S+ C0-1 . . C2-3 S+ C4-5 . . 0 A2:0-1"
|
||||
" S+ C0-1 . . C2-3 P1 . . . 0 "
|
||||
" S+ C0-1 . . C2-3 P1:S+ C0-1:P1 . . 0 "
|
||||
" S+ C0-1 . . C2-3 P1:S+ C1:P1 . . 0 "
|
||||
" S+ C0-1:S+ . . C2-3 . . . P1 0 "
|
||||
" S+ C0-1:P1 . . C2-3 S+ C1 . . 0 "
|
||||
" S+ C0-1:P1 . . C2-3 S+ C1:P1 . . 0 "
|
||||
" S+ C0-1:P1 . . C2-3 S+ C1:P1 . P1 0 "
|
||||
" S+ C0-1:P1 . . C2-3 C4-5 . . . 0 A1:4-5"
|
||||
" S+ C0-1:P1 . . C2-3 S+:C4-5 . . . 0 A1:4-5"
|
||||
" S+ C0-1 . . C2-3:P1 . . . C2 0 "
|
||||
" S+ C0-1 . . C2-3:P1 . . . C4-5 0 B1:4-5"
|
||||
" S+ C0-3:P1:S+ C2-3:P1 . . . . . . 0 A1:0-1,A2:2-3"
|
||||
" S+ C0-3:P1:S+ C2-3:P1 . . C1-3 . . . 0 A1:1,A2:2-3"
|
||||
" S+ C2-3:P1:S+ C3:P1 . . C3 . . . 0 A1:,A2:3 A1:P1,A2:P1"
|
||||
" S+ C2-3:P1:S+ C3:P1 . . C3 P0 . . 0 A1:3,A2:3 A1:P1,A2:P0"
|
||||
" S+ C2-3:P1:S+ C2:P1 . . C2-4 . . . 0 A1:3-4,A2:2"
|
||||
" S+ C2-3:P1:S+ C3:P1 . . C3 . . C0-2 0 A1:,B1:0-2 A1:P1,A2:P1"
|
||||
" S+ $SETUP_A123_PARTITIONS . C2-3 . . . 0 A1:,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
|
||||
# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
|
||||
# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
|
||||
" C0-1 . . C2-3 S+ C4-5 . . 0 A2:0-1"
|
||||
" C0-1 . . C2-3 P1 . . . 0 "
|
||||
" C0-1 . . C2-3 P1:S+ C0-1:P1 . . 0 "
|
||||
" C0-1 . . C2-3 P1:S+ C1:P1 . . 0 "
|
||||
" C0-1:S+ . . C2-3 . . . P1 0 "
|
||||
" C0-1:P1 . . C2-3 S+ C1 . . 0 "
|
||||
" C0-1:P1 . . C2-3 S+ C1:P1 . . 0 "
|
||||
" C0-1:P1 . . C2-3 S+ C1:P1 . P1 0 "
|
||||
" C0-1:P1 . . C2-3 C4-5 . . . 0 A1:4-5"
|
||||
" C0-1:P1 . . C2-3 S+:C4-5 . . . 0 A1:4-5"
|
||||
" C0-1 . . C2-3:P1 . . . C2 0 "
|
||||
" C0-1 . . C2-3:P1 . . . C4-5 0 B1:4-5"
|
||||
"C0-3:P1:S+ C2-3:P1 . . . . . . 0 A1:0-1,A2:2-3"
|
||||
"C0-3:P1:S+ C2-3:P1 . . C1-3 . . . 0 A1:1,A2:2-3"
|
||||
"C2-3:P1:S+ C3:P1 . . C3 . . . 0 A1:,A2:3 A1:P1,A2:P1"
|
||||
"C2-3:P1:S+ C3:P1 . . C3 P0 . . 0 A1:3,A2:3 A1:P1,A2:P0"
|
||||
"C2-3:P1:S+ C2:P1 . . C2-4 . . . 0 A1:3-4,A2:2"
|
||||
"C2-3:P1:S+ C3:P1 . . C3 . . C0-2 0 A1:,B1:0-2 A1:P1,A2:P1"
|
||||
"$SETUP_A123_PARTITIONS . C2-3 . . . 0 A1:,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
|
||||
|
||||
# CPU offlining cases:
|
||||
" S+ C0-1 . . C2-3 S+ C4-5 . O2-0 0 A1:0-1,B1:3"
|
||||
" S+ C0-3:P1:S+ C2-3:P1 . . O2-0 . . . 0 A1:0-1,A2:3"
|
||||
" S+ C0-3:P1:S+ C2-3:P1 . . O2-0 O2-1 . . 0 A1:0-1,A2:2-3"
|
||||
" S+ C0-3:P1:S+ C2-3:P1 . . O1-0 . . . 0 A1:0,A2:2-3"
|
||||
" S+ C0-3:P1:S+ C2-3:P1 . . O1-0 O1-1 . . 0 A1:0-1,A2:2-3"
|
||||
" S+ C2-3:P1:S+ C3:P1 . . O3-0 O3-1 . . 0 A1:2,A2:3 A1:P1,A2:P1"
|
||||
" S+ C2-3:P1:S+ C3:P2 . . O3-0 O3-1 . . 0 A1:2,A2:3 A1:P1,A2:P2"
|
||||
" S+ C2-3:P1:S+ C3:P1 . . O2-0 O2-1 . . 0 A1:2,A2:3 A1:P1,A2:P1"
|
||||
" S+ C2-3:P1:S+ C3:P2 . . O2-0 O2-1 . . 0 A1:2,A2:3 A1:P1,A2:P2"
|
||||
" S+ C2-3:P1:S+ C3:P1 . . O2-0 . . . 0 A1:,A2:3 A1:P1,A2:P1"
|
||||
" S+ C2-3:P1:S+ C3:P1 . . O3-0 . . . 0 A1:2,A2: A1:P1,A2:P1"
|
||||
" S+ C2-3:P1:S+ C3:P1 . . T:O2-0 . . . 0 A1:3,A2:3 A1:P1,A2:P-1"
|
||||
" S+ C2-3:P1:S+ C3:P1 . . . T:O3-0 . . 0 A1:2,A2:2 A1:P1,A2:P-1"
|
||||
" S+ $SETUP_A123_PARTITIONS . O1-0 . . . 0 A1:,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
|
||||
" S+ $SETUP_A123_PARTITIONS . O2-0 . . . 0 A1:1,A2:,A3:3 A1:P1,A2:P1,A3:P1"
|
||||
" S+ $SETUP_A123_PARTITIONS . O3-0 . . . 0 A1:1,A2:2,A3: A1:P1,A2:P1,A3:P1"
|
||||
" S+ $SETUP_A123_PARTITIONS . T:O1-0 . . . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P-1,A3:P-1"
|
||||
" S+ $SETUP_A123_PARTITIONS . . T:O2-0 . . 0 A1:1,A2:3,A3:3 A1:P1,A2:P1,A3:P-1"
|
||||
" S+ $SETUP_A123_PARTITIONS . . . T:O3-0 . 0 A1:1,A2:2,A3:2 A1:P1,A2:P1,A3:P-1"
|
||||
" S+ $SETUP_A123_PARTITIONS . T:O1-0 O1-1 . . 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
|
||||
" S+ $SETUP_A123_PARTITIONS . . T:O2-0 O2-1 . 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
|
||||
" S+ $SETUP_A123_PARTITIONS . . . T:O3-0 O3-1 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
|
||||
" S+ $SETUP_A123_PARTITIONS . T:O1-0 O2-0 O1-1 . 0 A1:1,A2:,A3:3 A1:P1,A2:P1,A3:P1"
|
||||
" S+ $SETUP_A123_PARTITIONS . T:O1-0 O2-0 O2-1 . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P-1,A3:P-1"
|
||||
" C0-1 . . C2-3 S+ C4-5 . O2=0 0 A1:0-1,B1:3"
|
||||
"C0-3:P1:S+ C2-3:P1 . . O2=0 . . . 0 A1:0-1,A2:3"
|
||||
"C0-3:P1:S+ C2-3:P1 . . O2=0 O2=1 . . 0 A1:0-1,A2:2-3"
|
||||
"C0-3:P1:S+ C2-3:P1 . . O1=0 . . . 0 A1:0,A2:2-3"
|
||||
"C0-3:P1:S+ C2-3:P1 . . O1=0 O1=1 . . 0 A1:0-1,A2:2-3"
|
||||
"C2-3:P1:S+ C3:P1 . . O3=0 O3=1 . . 0 A1:2,A2:3 A1:P1,A2:P1"
|
||||
"C2-3:P1:S+ C3:P2 . . O3=0 O3=1 . . 0 A1:2,A2:3 A1:P1,A2:P2"
|
||||
"C2-3:P1:S+ C3:P1 . . O2=0 O2=1 . . 0 A1:2,A2:3 A1:P1,A2:P1"
|
||||
"C2-3:P1:S+ C3:P2 . . O2=0 O2=1 . . 0 A1:2,A2:3 A1:P1,A2:P2"
|
||||
"C2-3:P1:S+ C3:P1 . . O2=0 . . . 0 A1:,A2:3 A1:P1,A2:P1"
|
||||
"C2-3:P1:S+ C3:P1 . . O3=0 . . . 0 A1:2,A2: A1:P1,A2:P1"
|
||||
"C2-3:P1:S+ C3:P1 . . T:O2=0 . . . 0 A1:3,A2:3 A1:P1,A2:P-1"
|
||||
"C2-3:P1:S+ C3:P1 . . . T:O3=0 . . 0 A1:2,A2:2 A1:P1,A2:P-1"
|
||||
"$SETUP_A123_PARTITIONS . O1=0 . . . 0 A1:,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
|
||||
"$SETUP_A123_PARTITIONS . O2=0 . . . 0 A1:1,A2:,A3:3 A1:P1,A2:P1,A3:P1"
|
||||
"$SETUP_A123_PARTITIONS . O3=0 . . . 0 A1:1,A2:2,A3: A1:P1,A2:P1,A3:P1"
|
||||
"$SETUP_A123_PARTITIONS . T:O1=0 . . . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P-1,A3:P-1"
|
||||
"$SETUP_A123_PARTITIONS . . T:O2=0 . . 0 A1:1,A2:3,A3:3 A1:P1,A2:P1,A3:P-1"
|
||||
"$SETUP_A123_PARTITIONS . . . T:O3=0 . 0 A1:1,A2:2,A3:2 A1:P1,A2:P1,A3:P-1"
|
||||
"$SETUP_A123_PARTITIONS . T:O1=0 O1=1 . . 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
|
||||
"$SETUP_A123_PARTITIONS . . T:O2=0 O2=1 . 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
|
||||
"$SETUP_A123_PARTITIONS . . . T:O3=0 O3=1 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
|
||||
"$SETUP_A123_PARTITIONS . T:O1=0 O2=0 O1=1 . 0 A1:1,A2:,A3:3 A1:P1,A2:P1,A3:P1"
|
||||
"$SETUP_A123_PARTITIONS . T:O1=0 O2=0 O2=1 . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P-1,A3:P-1"
|
||||
|
||||
# test old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate
|
||||
# ---- ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------
|
||||
# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
|
||||
# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
|
||||
#
|
||||
# Remote partition and cpuset.cpus.exclusive tests
|
||||
#
|
||||
" C0-3:S+ C1-3:S+ C2-3 . X2-3 . . . 0 A1:0-3,A2:1-3,A3:2-3,XA1:2-3"
|
||||
" C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3:P2 . . 0 A1:0-1,A2:2-3,A3:2-3 A1:P0,A2:P2 2-3"
|
||||
" C0-3:S+ C1-3:S+ C2-3 . X2-3 X3:P2 . . 0 A1:0-2,A2:3,A3:3 A1:P0,A2:P2 3"
|
||||
" C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2 . 0 A1:0-1,A2:1,A3:2-3 A1:P0,A3:P2 2-3"
|
||||
" C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:C3 . 0 A1:0-2,A2:1-2,A3:3 A1:P0,A3:P2 3"
|
||||
" C0-3:S+ C1-3:S+ C2-3 C2-3 . . . P2 0 A1:0-3,A2:1-3,A3:2-3,B1:2-3 A1:P0,A3:P0,B1:P-2"
|
||||
" C0-3:S+ C1-3:S+ C2-3 C4-5 . . . P2 0 B1:4-5 B1:P2 4-5"
|
||||
" C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2 P2 0 A3:2-3,B1:4 A3:P2,B1:P2 2-4"
|
||||
" C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2:C1-3 P2 0 A3:2-3,B1:4 A3:P2,B1:P2 2-4"
|
||||
" C0-3:S+ C1-3:S+ C2-3 C4 X1-3 X1-3:P2 P2 . 0 A2:1,A3:2-3 A2:P2,A3:P2 1-3"
|
||||
" C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3 X2-3:P2 P2:C4-5 0 A3:2-3,B1:4-5 A3:P2,B1:P2 2-5"
|
||||
|
||||
# Nested remote/local partition tests
|
||||
" C0-3:S+ C1-3:S+ C2-3 C4-5 X2-3 X2-3:P1 P2 P1 0 A1:0-1,A2:,A3:2-3,B1:4-5 \
|
||||
A1:P0,A2:P1,A3:P2,B1:P1 2-3"
|
||||
" C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3:P1 P2 P1 0 A1:0-1,A2:,A3:2-3,B1:4 \
|
||||
A1:P0,A2:P1,A3:P2,B1:P1 2-4"
|
||||
" C0-3:S+ C1-3:S+ 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"
|
||||
" C0-4:S+ C1-4:S+ 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"
|
||||
" C0-4:X2-4:S+ C1-4:X2-4:S+:P2 C2-4:X4:P1 \
|
||||
. . X5 . . 0 A1:0-4,A2:1-4,A3:2-4 \
|
||||
A1:P0,A2:P-2,A3:P-1 ."
|
||||
" C0-4:X2-4:S+ C1-4:X2-4:S+: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"
|
||||
|
||||
# Remote partition offline tests
|
||||
" C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:O2=0 . 0 A1:0-1,A2:1,A3:3 A1:P0,A3:P2 2-3"
|
||||
" C0-3:S+ C1-3:S+ C2-3 . X2-3 X2-3 X2-3:P2:O2=0 O2=1 0 A1:0-1,A2:1,A3:2-3 A1:P0,A3:P2 2-3"
|
||||
" C0-3:S+ C1-3:S+ C3 . X2-3 X2-3 P2:O3=0 . 0 A1:0-2,A2:1-2,A3: A1:P0,A3:P2 3"
|
||||
" C0-3:S+ C1-3:S+ C3 . X2-3 X2-3 T:P2:O3=0 . 0 A1:0-2,A2:1-2,A3:1-2 A1:P0,A3:P-2 3"
|
||||
|
||||
# An invalidated remote partition cannot self-recover from hotplug
|
||||
" C0-3:S+ C1-3:S+ C2 . X2-3 X2-3 T:P2:O2=0 O2=1 0 A1:0-3,A2:1-3,A3:2 A1:P0,A3:P-2"
|
||||
|
||||
# cpus.exclusive.effective clearing test
|
||||
" C0-3:S+ C1-3:S+ C2 . X2-3:X . . . 0 A1:0-3,A2:1-3,A3:2,XA1:"
|
||||
|
||||
# Invalid to valid remote partition transition test
|
||||
" C0-3:S+ C1-3 . . . X3:P2 . . 0 A1:0-3,A2:1-3,XA2: A2:P-2"
|
||||
" C0-3:S+ C1-3:X3:P2
|
||||
. . X2-3 P2 . . 0 A1:0-2,A2:3,XA2:3 A2:P2 3"
|
||||
|
||||
# Invalid to valid local partition direct transition tests
|
||||
" C1-3:S+:P2 C2-3:X1:P2 . . . . . . 0 A1:1-3,XA1:1-3,A2:2-3:XA2: A1:P2,A2:P-2 1-3"
|
||||
" C1-3:S+:P2 C2-3:X1:P2 . . . X3:P2 . . 0 A1:1-2,XA1:1-3,A2:3:XA2:3 A1:P2,A2:P2 1-3"
|
||||
" C0-3:P2 . . C4-6 C0-4 . . . 0 A1:0-4,B1:4-6 A1:P-2,B1:P0"
|
||||
" C0-3:P2 . . C4-6 C0-4:C0-3 . . . 0 A1:0-3,B1:4-6 A1:P2,B1:P0 0-3"
|
||||
" C0-3:P2 . . C3-5:C4-5 . . . . 0 A1:0-3,B1:4-5 A1:P2,B1:P0 0-3"
|
||||
|
||||
# Local partition invalidation tests
|
||||
" C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \
|
||||
. . . . . 0 A1:1,A2:2,A3:3 A1:P2,A2:P2,A3:P2 1-3"
|
||||
" C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \
|
||||
. . X4 . . 0 A1:1-3,A2:1-3,A3:2-3,XA2:,XA3: A1:P2,A2:P-2,A3:P-2 1-3"
|
||||
" C0-3:X1-3:S+:P2 C1-3:X2-3:S+:P2 C2-3:X3:P2 \
|
||||
. . C4 . . 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:S+:P2 C4-5:S+:P1 . . . C3-5 . . 0 A1:0-2,A2:3-5 A1:P2,A2:P1 0-2"
|
||||
" C0-5:S+:P2 C4-5:S+:P1 . . C1-5 . . . 0 A1:1-3,A2:4-5 A1:P2,A2:P1 1-3"
|
||||
|
||||
# cpus_allowed/exclusive_cpus update tests
|
||||
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \
|
||||
. C4 . P2 . 0 A1:4,A2:4,XA2:,XA3:,A3:4 \
|
||||
A1:P0,A3:P-2 ."
|
||||
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \
|
||||
. X1 . P2 . 0 A1:0-3,A2:1-3,XA1:1,XA2:,XA3:,A3:2-3 \
|
||||
A1:P0,A3:P-2 ."
|
||||
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \
|
||||
. . C3 P2 . 0 A1:0-2,A2:0-2,XA2:3,XA3:3,A3:3 \
|
||||
A1:P0,A3:P2 3"
|
||||
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \
|
||||
. . X3 P2 . 0 A1:0-2,A2:1-2,XA2:3,XA3:3,A3:3 \
|
||||
A1:P0,A3:P2 3"
|
||||
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \
|
||||
. . X3 . . 0 A1:0-3,A2:1-3,XA2:3,XA3:3,A3:2-3 \
|
||||
A1:P0,A3:P-2 ."
|
||||
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \
|
||||
. . C3 . . 0 A1:0-3,A2:3,XA2:3,XA3:3,A3:3 \
|
||||
A1:P0,A3:P-2 ."
|
||||
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \
|
||||
. C4 . . . 0 A1:4,A2:4,A3:4,XA1:,XA2:,XA3 \
|
||||
A1:P0,A3:P-2 ."
|
||||
|
||||
# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
|
||||
# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
|
||||
#
|
||||
# Incorrect change to cpuset.cpus invalidates partition root
|
||||
#
|
||||
# Adding CPUs to partition root that are not in parent's
|
||||
# cpuset.cpus is allowed, but those extra CPUs are ignored.
|
||||
" S+ C2-3:P1:S+ C3:P1 . . . C2-4 . . 0 A1:,A2:2-3 A1:P1,A2:P1"
|
||||
"C2-3:P1:S+ C3:P1 . . . C2-4 . . 0 A1:,A2:2-3 A1:P1,A2:P1"
|
||||
|
||||
# Taking away all CPUs from parent or itself if there are tasks
|
||||
# will make the partition invalid.
|
||||
" S+ C2-3:P1:S+ C3:P1 . . T C2-3 . . 0 A1:2-3,A2:2-3 A1:P1,A2:P-1"
|
||||
" S+ C3:P1:S+ C3 . . T P1 . . 0 A1:3,A2:3 A1:P1,A2:P-1"
|
||||
" S+ $SETUP_A123_PARTITIONS . T:C2-3 . . . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P-1,A3:P-1"
|
||||
" S+ $SETUP_A123_PARTITIONS . T:C2-3:C1-3 . . . 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
|
||||
"C2-3:P1:S+ C3:P1 . . T C2-3 . . 0 A1:2-3,A2:2-3 A1:P1,A2:P-1"
|
||||
" C3:P1:S+ C3 . . T P1 . . 0 A1:3,A2:3 A1:P1,A2:P-1"
|
||||
"$SETUP_A123_PARTITIONS . T:C2-3 . . . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P-1,A3:P-1"
|
||||
"$SETUP_A123_PARTITIONS . T:C2-3:C1-3 . . . 0 A1:1,A2:2,A3:3 A1:P1,A2:P1,A3:P1"
|
||||
|
||||
# Changing a partition root to member makes child partitions invalid
|
||||
" S+ C2-3:P1:S+ C3:P1 . . P0 . . . 0 A1:2-3,A2:3 A1:P0,A2:P-1"
|
||||
" S+ $SETUP_A123_PARTITIONS . C2-3 P0 . . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P0,A3:P-1"
|
||||
"C2-3:P1:S+ C3:P1 . . P0 . . . 0 A1:2-3,A2:3 A1:P0,A2:P-1"
|
||||
"$SETUP_A123_PARTITIONS . C2-3 P0 . . 0 A1:2-3,A2:2-3,A3:3 A1:P1,A2:P0,A3:P-1"
|
||||
|
||||
# cpuset.cpus can contains cpus not in parent's cpuset.cpus as long
|
||||
# as they overlap.
|
||||
" S+ C2-3:P1:S+ . . . . C3-4:P1 . . 0 A1:2,A2:3 A1:P1,A2:P1"
|
||||
"C2-3:P1:S+ . . . . C3-4:P1 . . 0 A1:2,A2:3 A1:P1,A2:P1"
|
||||
|
||||
# Deletion of CPUs distributed to child cgroup is allowed.
|
||||
" S+ C0-1:P1:S+ C1 . C2-3 C4-5 . . . 0 A1:4-5,A2:4-5"
|
||||
"C0-1:P1:S+ C1 . C2-3 C4-5 . . . 0 A1:4-5,A2:4-5"
|
||||
|
||||
# To become a valid partition root, cpuset.cpus must overlap parent's
|
||||
# cpuset.cpus.
|
||||
" S+ C0-1:P1 . . C2-3 S+ C4-5:P1 . . 0 A1:0-1,A2:0-1 A1:P1,A2:P-1"
|
||||
" C0-1:P1 . . C2-3 S+ C4-5:P1 . . 0 A1:0-1,A2:0-1 A1:P1,A2:P-1"
|
||||
|
||||
# Enabling partition with child cpusets is allowed
|
||||
" S+ C0-1:S+ C1 . C2-3 P1 . . . 0 A1:0-1,A2:1 A1:P1"
|
||||
" C0-1:S+ C1 . C2-3 P1 . . . 0 A1:0-1,A2:1 A1:P1"
|
||||
|
||||
# A partition root with non-partition root parent is invalid, but it
|
||||
# can be made valid if its parent becomes a partition root too.
|
||||
" S+ C0-1:S+ C1 . C2-3 . P2 . . 0 A1:0-1,A2:1 A1:P0,A2:P-2"
|
||||
" S+ C0-1:S+ C1:P2 . C2-3 P1 . . . 0 A1:0,A2:1 A1:P1,A2:P2"
|
||||
" C0-1:S+ C1 . C2-3 . P2 . . 0 A1:0-1,A2:1 A1:P0,A2:P-2"
|
||||
" C0-1:S+ C1:P2 . C2-3 P1 . . . 0 A1:0,A2:1 A1:P1,A2:P2"
|
||||
|
||||
# A non-exclusive cpuset.cpus change will invalidate partition and its siblings
|
||||
" S+ C0-1:P1 . . C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P-1,B1:P0"
|
||||
" S+ C0-1:P1 . . P1:C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P-1,B1:P-1"
|
||||
" S+ C0-1 . . P1:C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P0,B1:P-1"
|
||||
" C0-1:P1 . . C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P-1,B1:P0"
|
||||
" C0-1:P1 . . P1:C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P-1,B1:P-1"
|
||||
" C0-1 . . P1:C2-3 C0-2 . . . 0 A1:0-2,B1:2-3 A1:P0,B1:P-1"
|
||||
|
||||
# test old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate
|
||||
# ---- ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------
|
||||
# old-A1 old-A2 old-A3 old-B1 new-A1 new-A2 new-A3 new-B1 fail ECPUs Pstate ISOLCPUS
|
||||
# ------ ------ ------ ------ ------ ------ ------ ------ ---- ----- ------ --------
|
||||
# Failure cases:
|
||||
|
||||
# A task cannot be added to a partition with no cpu
|
||||
" S+ C2-3:P1:S+ C3:P1 . . O2-0:T . . . 1 A1:,A2:3 A1:P1,A2:P1"
|
||||
"C2-3:P1:S+ C3:P1 . . O2=0:T . . . 1 A1:,A2:3 A1:P1,A2:P1"
|
||||
|
||||
# Changes to cpuset.cpus.exclusive that violate exclusivity rule is rejected
|
||||
" C0-3 . . C4-5 X0-3 . . X3-5 1 A1:0-3,B1:4-5"
|
||||
)
|
||||
|
||||
#
|
||||
# Write to the cpu online file
|
||||
# $1 - <c>-<v> where <c> = cpu number, <v> value to be written
|
||||
# $1 - <c>=<v> where <c> = cpu number, <v> value to be written
|
||||
#
|
||||
write_cpu_online()
|
||||
{
|
||||
CPU=${1%-*}
|
||||
VAL=${1#*-}
|
||||
CPU=${1%=*}
|
||||
VAL=${1#*=}
|
||||
CPUFILE=//sys/devices/system/cpu/cpu${CPU}/online
|
||||
if [[ $VAL -eq 0 ]]
|
||||
then
|
||||
|
@ -349,11 +457,12 @@ set_ctrl_state()
|
|||
TMPMSG=/tmp/.msg_$$
|
||||
CGRP=$1
|
||||
STATE=$2
|
||||
SHOWERR=${3}${VERBOSE}
|
||||
SHOWERR=${3}
|
||||
CTRL=${CTRL:=$CONTROLLER}
|
||||
HASERR=0
|
||||
REDIRECT="2> $TMPMSG"
|
||||
[[ -z "$STATE" || "$STATE" = '.' ]] && return 0
|
||||
[[ $VERBOSE -gt 0 ]] && SHOWERR=1
|
||||
|
||||
rm -f $TMPMSG
|
||||
for CMD in $(echo $STATE | sed -e "s/:/ /g")
|
||||
|
@ -362,12 +471,18 @@ set_ctrl_state()
|
|||
SFILE=$CGRP/cgroup.subtree_control
|
||||
PFILE=$CGRP/cpuset.cpus.partition
|
||||
CFILE=$CGRP/cpuset.cpus
|
||||
XFILE=$CGRP/cpuset.cpus.exclusive
|
||||
S=$(expr substr $CMD 1 1)
|
||||
if [[ $S = S ]]
|
||||
then
|
||||
PREFIX=${CMD#?}
|
||||
COMM="echo ${PREFIX}${CTRL} > $SFILE"
|
||||
eval $COMM $REDIRECT
|
||||
elif [[ $S = X ]]
|
||||
then
|
||||
CPUS=${CMD#?}
|
||||
COMM="echo $CPUS > $XFILE"
|
||||
eval $COMM $REDIRECT
|
||||
elif [[ $S = C ]]
|
||||
then
|
||||
CPUS=${CMD#?}
|
||||
|
@ -430,7 +545,7 @@ online_cpus()
|
|||
[[ -n "OFFLINE_CPUS" ]] && {
|
||||
for C in $OFFLINE_CPUS
|
||||
do
|
||||
write_cpu_online ${C}-1
|
||||
write_cpu_online ${C}=1
|
||||
done
|
||||
}
|
||||
}
|
||||
|
@ -443,18 +558,27 @@ reset_cgroup_states()
|
|||
echo 0 > $CGROUP2/cgroup.procs
|
||||
online_cpus
|
||||
rmdir A1/A2/A3 A1/A2 A1 B1 > /dev/null 2>&1
|
||||
set_ctrl_state . S-
|
||||
pause 0.02
|
||||
set_ctrl_state . R-
|
||||
pause 0.01
|
||||
}
|
||||
|
||||
dump_states()
|
||||
{
|
||||
for DIR in A1 A1/A2 A1/A2/A3 B1
|
||||
for DIR in . A1 A1/A2 A1/A2/A3 B1
|
||||
do
|
||||
CPUS=$DIR/cpuset.cpus
|
||||
ECPUS=$DIR/cpuset.cpus.effective
|
||||
XCPUS=$DIR/cpuset.cpus.exclusive
|
||||
XECPUS=$DIR/cpuset.cpus.exclusive.effective
|
||||
PRS=$DIR/cpuset.cpus.partition
|
||||
[[ -e $ECPUS ]] && echo "$ECPUS: $(cat $ECPUS)"
|
||||
[[ -e $PRS ]] && echo "$PRS: $(cat $PRS)"
|
||||
PCPUS=$DIR/.__DEBUG__.cpuset.cpus.subpartitions
|
||||
[[ -e $CPUS ]] && echo "$CPUS: $(cat $CPUS)"
|
||||
[[ -e $XCPUS ]] && echo "$XCPUS: $(cat $XCPUS)"
|
||||
[[ -e $ECPUS ]] && echo "$ECPUS: $(cat $ECPUS)"
|
||||
[[ -e $XECPUS ]] && echo "$XECPUS: $(cat $XECPUS)"
|
||||
[[ -e $PRS ]] && echo "$PRS: $(cat $PRS)"
|
||||
[[ -e $PCPUS ]] && echo "$PCPUS: $(cat $PCPUS)"
|
||||
done
|
||||
}
|
||||
|
||||
|
@ -470,11 +594,17 @@ check_effective_cpus()
|
|||
set -- $(echo $CHK | sed -e "s/:/ /g")
|
||||
CGRP=$1
|
||||
CPUS=$2
|
||||
if [[ $CGRP = X* ]]
|
||||
then
|
||||
CGRP=${CGRP#X}
|
||||
FILE=cpuset.cpus.exclusive.effective
|
||||
else
|
||||
FILE=cpuset.cpus.effective
|
||||
fi
|
||||
[[ $CGRP = A2 ]] && CGRP=A1/A2
|
||||
[[ $CGRP = A3 ]] && CGRP=A1/A2/A3
|
||||
FILE=$CGRP/cpuset.cpus.effective
|
||||
[[ -e $FILE ]] || return 1
|
||||
[[ $CPUS = $(cat $FILE) ]] || return 1
|
||||
[[ -e $CGRP/$FILE ]] || return 1
|
||||
[[ $CPUS = $(cat $CGRP/$FILE) ]] || return 1
|
||||
done
|
||||
}
|
||||
|
||||
|
@ -524,6 +654,65 @@ check_cgroup_states()
|
|||
return 0
|
||||
}
|
||||
|
||||
#
|
||||
# Get isolated (including offline) CPUs by looking at
|
||||
# /sys/kernel/debug/sched/domains and compare that with the expected value.
|
||||
#
|
||||
# Note that a sched domain of just 1 CPU will be considered isolated.
|
||||
#
|
||||
# $1 - expected isolated cpu list
|
||||
#
|
||||
check_isolcpus()
|
||||
{
|
||||
EXPECT_VAL=$1
|
||||
ISOLCPUS=
|
||||
LASTISOLCPU=
|
||||
SCHED_DOMAINS=/sys/kernel/debug/sched/domains
|
||||
[[ -d $SCHED_DOMAINS ]] || return 0
|
||||
[[ $EXPECT_VAL = . ]] && EXPECT_VAL=
|
||||
|
||||
for ((CPU=0; CPU < $NR_CPUS; CPU++))
|
||||
do
|
||||
[[ -n "$(ls ${SCHED_DOMAINS}/cpu$CPU)" ]] && continue
|
||||
|
||||
if [[ -z "$LASTISOLCPU" ]]
|
||||
then
|
||||
ISOLCPUS=$CPU
|
||||
LASTISOLCPU=$CPU
|
||||
elif [[ "$LASTISOLCPU" -eq $((CPU - 1)) ]]
|
||||
then
|
||||
echo $ISOLCPUS | grep -q "\<$LASTISOLCPU\$"
|
||||
if [[ $? -eq 0 ]]
|
||||
then
|
||||
ISOLCPUS=${ISOLCPUS}-
|
||||
fi
|
||||
LASTISOLCPU=$CPU
|
||||
else
|
||||
if [[ $ISOLCPUS = *- ]]
|
||||
then
|
||||
ISOLCPUS=${ISOLCPUS}$LASTISOLCPU
|
||||
fi
|
||||
ISOLCPUS=${ISOLCPUS},$CPU
|
||||
LASTISOLCPU=$CPU
|
||||
fi
|
||||
done
|
||||
[[ "$ISOLCPUS" = *- ]] && ISOLCPUS=${ISOLCPUS}$LASTISOLCPU
|
||||
[[ "$EXPECT_VAL" = "$ISOLCPUS" ]]
|
||||
}
|
||||
|
||||
test_fail()
|
||||
{
|
||||
TESTNUM=$1
|
||||
TESTTYPE=$2
|
||||
ADDINFO=$3
|
||||
echo "Test $TEST[$TESTNUM] failed $TESTTYPE check!"
|
||||
[[ -n "$ADDINFO" ]] && echo "*** $ADDINFO ***"
|
||||
eval echo \${$TEST[$I]}
|
||||
echo
|
||||
dump_states
|
||||
exit 1
|
||||
}
|
||||
|
||||
#
|
||||
# Run cpuset state transition test
|
||||
# $1 - test matrix name
|
||||
|
@ -536,88 +725,83 @@ run_state_test()
|
|||
{
|
||||
TEST=$1
|
||||
CONTROLLER=cpuset
|
||||
CPULIST=0-6
|
||||
I=0
|
||||
eval CNT="\${#$TEST[@]}"
|
||||
|
||||
reset_cgroup_states
|
||||
echo $CPULIST > cpuset.cpus
|
||||
echo root > cpuset.cpus.partition
|
||||
console_msg "Running state transition test ..."
|
||||
|
||||
while [[ $I -lt $CNT ]]
|
||||
do
|
||||
echo "Running test $I ..." > /dev/console
|
||||
[[ $VERBOSE -gt 1 ]] && {
|
||||
echo ""
|
||||
eval echo \${$TEST[$I]}
|
||||
}
|
||||
eval set -- "\${$TEST[$I]}"
|
||||
ROOT=$1
|
||||
OLD_A1=$2
|
||||
OLD_A2=$3
|
||||
OLD_A3=$4
|
||||
OLD_B1=$5
|
||||
NEW_A1=$6
|
||||
NEW_A2=$7
|
||||
NEW_A3=$8
|
||||
NEW_B1=$9
|
||||
RESULT=${10}
|
||||
ECPUS=${11}
|
||||
STATES=${12}
|
||||
OLD_A1=$1
|
||||
OLD_A2=$2
|
||||
OLD_A3=$3
|
||||
OLD_B1=$4
|
||||
NEW_A1=$5
|
||||
NEW_A2=$6
|
||||
NEW_A3=$7
|
||||
NEW_B1=$8
|
||||
RESULT=$9
|
||||
ECPUS=${10}
|
||||
STATES=${11}
|
||||
ICPUS=${12}
|
||||
|
||||
set_ctrl_state_noerr . $ROOT
|
||||
set_ctrl_state_noerr B1 $OLD_B1
|
||||
set_ctrl_state_noerr A1 $OLD_A1
|
||||
set_ctrl_state_noerr A1/A2 $OLD_A2
|
||||
set_ctrl_state_noerr A1/A2/A3 $OLD_A3
|
||||
set_ctrl_state_noerr B1 $OLD_B1
|
||||
RETVAL=0
|
||||
set_ctrl_state A1 $NEW_A1; ((RETVAL += $?))
|
||||
set_ctrl_state A1/A2 $NEW_A2; ((RETVAL += $?))
|
||||
set_ctrl_state A1/A2/A3 $NEW_A3; ((RETVAL += $?))
|
||||
set_ctrl_state B1 $NEW_B1; ((RETVAL += $?))
|
||||
|
||||
[[ $RETVAL -ne $RESULT ]] && {
|
||||
echo "Test $TEST[$I] failed result check!"
|
||||
eval echo \"\${$TEST[$I]}\"
|
||||
dump_states
|
||||
exit 1
|
||||
}
|
||||
[[ $RETVAL -ne $RESULT ]] && test_fail $I result
|
||||
|
||||
[[ -n "$ECPUS" && "$ECPUS" != . ]] && {
|
||||
check_effective_cpus $ECPUS
|
||||
[[ $? -ne 0 ]] && {
|
||||
echo "Test $TEST[$I] failed effective CPU check!"
|
||||
eval echo \"\${$TEST[$I]}\"
|
||||
echo
|
||||
dump_states
|
||||
exit 1
|
||||
}
|
||||
[[ $? -ne 0 ]] && test_fail $I "effective CPU"
|
||||
}
|
||||
|
||||
[[ -n "$STATES" ]] && {
|
||||
[[ -n "$STATES" && "$STATES" != . ]] && {
|
||||
check_cgroup_states $STATES
|
||||
[[ $? -ne 0 ]] && {
|
||||
echo "FAILED: Test $TEST[$I] failed states check!"
|
||||
eval echo \"\${$TEST[$I]}\"
|
||||
echo
|
||||
dump_states
|
||||
exit 1
|
||||
}
|
||||
[[ $? -ne 0 ]] && test_fail $I states
|
||||
}
|
||||
|
||||
# Compare the expected isolated CPUs with the actual ones,
|
||||
# if available
|
||||
[[ -n "$ICPUS" ]] && {
|
||||
check_isolcpus $ICPUS
|
||||
[[ $? -ne 0 ]] && test_fail $I "isolated CPU" \
|
||||
"Expect $ICPUS, get $ISOLCPUS instead"
|
||||
}
|
||||
reset_cgroup_states
|
||||
#
|
||||
# Check to see if effective cpu list changes
|
||||
#
|
||||
pause 0.05
|
||||
NEWLIST=$(cat cpuset.cpus.effective)
|
||||
RETRY=0
|
||||
while [[ $NEWLIST != $CPULIST && $RETRY -lt 5 ]]
|
||||
do
|
||||
# Wait a bit longer & recheck a few times
|
||||
pause 0.01
|
||||
((RETRY++))
|
||||
NEWLIST=$(cat cpuset.cpus.effective)
|
||||
done
|
||||
[[ $NEWLIST != $CPULIST ]] && {
|
||||
echo "Effective cpus changed to $NEWLIST after test $I!"
|
||||
exit 1
|
||||
}
|
||||
[[ -n "$VERBOSE" ]] && echo "Test $I done."
|
||||
[[ $VERBOSE -gt 0 ]] && echo "Test $I done."
|
||||
((I++))
|
||||
done
|
||||
echo "All $I tests of $TEST PASSED."
|
||||
|
||||
echo member > cpuset.cpus.partition
|
||||
}
|
||||
|
||||
#
|
||||
|
@ -642,6 +826,7 @@ test_inotify()
|
|||
{
|
||||
ERR=0
|
||||
PRS=/tmp/.prs_$$
|
||||
cd $CGROUP2/test
|
||||
[[ -f $WAIT_INOTIFY ]] || {
|
||||
echo "wait_inotify not found, inotify test SKIPPED."
|
||||
return
|
||||
|
@ -655,7 +840,7 @@ test_inotify()
|
|||
rm -f $PRS
|
||||
wait_inotify $PWD/cpuset.cpus.partition $PRS &
|
||||
pause 0.01
|
||||
set_ctrl_state . "O1-0"
|
||||
set_ctrl_state . "O1=0"
|
||||
pause 0.01
|
||||
check_cgroup_states ".:P-1"
|
||||
if [[ $? -ne 0 ]]
|
||||
|
@ -689,5 +874,3 @@ run_state_test TEST_MATRIX
|
|||
test_isolated
|
||||
test_inotify
|
||||
echo "All tests PASSED."
|
||||
cd ..
|
||||
rmdir test
|
||||
|
|
Loading…
Reference in a new issue