mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
Merge tag 'cgroup-for-7.0-rc2-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
Pull cgroup fixes from Tejun Heo: - Fix circular locking dependency in cpuset partition code by deferring housekeeping_update() calls to a workqueue instead of calling them directly under cpus_read_lock - Fix null-ptr-deref in rebuild_sched_domains_cpuslocked() when generate_sched_domains() returns NULL due to kmalloc failure - Fix incorrect cpuset behavior for effective_xcpus in partition_xcpus_del() and cpuset_update_tasks_cpumask() in update_cpumasks_hier() - Fix race between task migration and cgroup iteration * tag 'cgroup-for-7.0-rc2-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: cgroup/cpuset: fix null-ptr-deref in rebuild_sched_domains_cpuslocked cgroup/cpuset: Call housekeeping_update() without holding cpus_read_lock cgroup/cpuset: Defer housekeeping_update() calls from CPU hotplug to workqueue cgroup/cpuset: Move housekeeping_update()/rebuild_sched_domains() together kselftest/cgroup: Simplify test_cpuset_prs.sh by removing "S+" command cgroup/cpuset: Set isolated_cpus_updating only if isolated_cpus is changed cgroup/cpuset: Clarify exclusion rules for cpuset internal variables cgroup/cpuset: Fix incorrect use of cpuset_update_tasks_cpumask() in update_cpumasks_hier() cgroup/cpuset: Fix incorrect change to effective_xcpus in partition_xcpus_del() cgroup: fix race between task migration and iteration
This commit is contained in:
@@ -2608,6 +2608,7 @@ static void cgroup_migrate_add_task(struct task_struct *task,
|
||||
|
||||
mgctx->tset.nr_tasks++;
|
||||
|
||||
css_set_skip_task_iters(cset, task);
|
||||
list_move_tail(&task->cg_list, &cset->mg_tasks);
|
||||
if (list_empty(&cset->mg_node))
|
||||
list_add_tail(&cset->mg_node,
|
||||
|
||||
@@ -61,6 +61,75 @@ static const char * const perr_strings[] = {
|
||||
[PERR_REMOTE] = "Have remote partition underneath",
|
||||
};
|
||||
|
||||
/*
|
||||
* CPUSET Locking Convention
|
||||
* -------------------------
|
||||
*
|
||||
* Below are the four global/local locks guarding cpuset structures in lock
|
||||
* acquisition order:
|
||||
* - cpuset_top_mutex
|
||||
* - cpu_hotplug_lock (cpus_read_lock/cpus_write_lock)
|
||||
* - cpuset_mutex
|
||||
* - callback_lock (raw spinlock)
|
||||
*
|
||||
* As cpuset will now indirectly flush a number of different workqueues in
|
||||
* housekeeping_update() to update housekeeping cpumasks when the set of
|
||||
* isolated CPUs is going to be changed, it may be vulnerable to deadlock
|
||||
* if we hold cpus_read_lock while calling into housekeeping_update().
|
||||
*
|
||||
* The first cpuset_top_mutex will be held except when calling into
|
||||
* cpuset_handle_hotplug() from the CPU hotplug code where cpus_write_lock
|
||||
* and cpuset_mutex will be held instead. The main purpose of this mutex
|
||||
* is to prevent regular cpuset control file write actions from interfering
|
||||
* with the call to housekeeping_update(), though CPU hotplug operation can
|
||||
* still happen in parallel. This mutex also provides protection for some
|
||||
* internal variables.
|
||||
*
|
||||
* A task must hold all the remaining three locks to modify externally visible
|
||||
* or used fields of cpusets, though some of the internally used cpuset fields
|
||||
* and internal variables can be modified without holding callback_lock. If only
|
||||
* reliable read access of the externally used fields are needed, a task can
|
||||
* hold either cpuset_mutex or callback_lock which are exposed to other
|
||||
* external subsystems.
|
||||
*
|
||||
* If a task holds cpu_hotplug_lock and cpuset_mutex, it blocks others,
|
||||
* ensuring that it is the only task able to also acquire callback_lock and
|
||||
* be able to modify cpusets. It can perform various checks on the cpuset
|
||||
* structure first, knowing nothing will change. It can also allocate memory
|
||||
* without holding callback_lock. While it is performing these checks, various
|
||||
* callback routines can briefly acquire callback_lock to query cpusets. Once
|
||||
* it is ready to make the changes, it takes callback_lock, blocking everyone
|
||||
* else.
|
||||
*
|
||||
* Calls to the kernel memory allocator cannot be made while holding
|
||||
* callback_lock which is a spinlock, as the memory allocator may sleep or
|
||||
* call back into cpuset code and acquire callback_lock.
|
||||
*
|
||||
* Now, the task_struct fields mems_allowed and mempolicy may be changed
|
||||
* by other task, we use alloc_lock in the task_struct fields to protect
|
||||
* them.
|
||||
*
|
||||
* The cpuset_common_seq_show() handlers only hold callback_lock across
|
||||
* small pieces of code, such as when reading out possibly multi-word
|
||||
* cpumasks and nodemasks.
|
||||
*/
|
||||
|
||||
static DEFINE_MUTEX(cpuset_top_mutex);
|
||||
static DEFINE_MUTEX(cpuset_mutex);
|
||||
|
||||
/*
|
||||
* File level internal variables below follow one of the following exclusion
|
||||
* rules.
|
||||
*
|
||||
* RWCS: Read/write-able by holding either cpus_write_lock (and optionally
|
||||
* cpuset_mutex) or both cpus_read_lock and cpuset_mutex.
|
||||
*
|
||||
* CSCB: Readable by holding either cpuset_mutex or callback_lock. Writable
|
||||
* by holding both cpuset_mutex and callback_lock.
|
||||
*
|
||||
* T: Read/write-able by holding the cpuset_top_mutex.
|
||||
*/
|
||||
|
||||
/*
|
||||
* For local partitions, update to subpartitions_cpus & isolated_cpus is done
|
||||
* in update_parent_effective_cpumask(). For remote partitions, it is done in
|
||||
@@ -70,19 +139,22 @@ static const char * const perr_strings[] = {
|
||||
* Exclusive CPUs distributed out to local or remote sub-partitions of
|
||||
* top_cpuset
|
||||
*/
|
||||
static cpumask_var_t subpartitions_cpus;
|
||||
static cpumask_var_t subpartitions_cpus; /* RWCS */
|
||||
|
||||
/*
|
||||
* Exclusive CPUs in isolated partitions
|
||||
* Exclusive CPUs in isolated partitions (shown in cpuset.cpus.isolated)
|
||||
*/
|
||||
static cpumask_var_t isolated_cpus;
|
||||
static cpumask_var_t isolated_cpus; /* CSCB */
|
||||
|
||||
/*
|
||||
* isolated_cpus updating flag (protected by cpuset_mutex)
|
||||
* Set if isolated_cpus is going to be updated in the current
|
||||
* cpuset_mutex crtical section.
|
||||
* Set if housekeeping cpumasks are to be updated.
|
||||
*/
|
||||
static bool isolated_cpus_updating;
|
||||
static bool update_housekeeping; /* RWCS */
|
||||
|
||||
/*
|
||||
* Copy of isolated_cpus to be passed to housekeeping_update()
|
||||
*/
|
||||
static cpumask_var_t isolated_hk_cpus; /* T */
|
||||
|
||||
/*
|
||||
* A flag to force sched domain rebuild at the end of an operation.
|
||||
@@ -98,7 +170,7 @@ static bool isolated_cpus_updating;
|
||||
* Note that update_relax_domain_level() in cpuset-v1.c can still call
|
||||
* rebuild_sched_domains_locked() directly without using this flag.
|
||||
*/
|
||||
static bool force_sd_rebuild;
|
||||
static bool force_sd_rebuild; /* RWCS */
|
||||
|
||||
/*
|
||||
* Partition root states:
|
||||
@@ -218,42 +290,6 @@ struct cpuset top_cpuset = {
|
||||
.partition_root_state = PRS_ROOT,
|
||||
};
|
||||
|
||||
/*
|
||||
* There are two global locks guarding cpuset structures - cpuset_mutex and
|
||||
* callback_lock. The cpuset code uses only cpuset_mutex. Other kernel
|
||||
* subsystems can use cpuset_lock()/cpuset_unlock() to prevent change to cpuset
|
||||
* structures. Note that cpuset_mutex needs to be a mutex as it is used in
|
||||
* paths that rely on priority inheritance (e.g. scheduler - on RT) for
|
||||
* correctness.
|
||||
*
|
||||
* A task must hold both locks to modify cpusets. If a task holds
|
||||
* cpuset_mutex, it blocks others, ensuring that it is the only task able to
|
||||
* also acquire callback_lock and be able to modify cpusets. It can perform
|
||||
* various checks on the cpuset structure first, knowing nothing will change.
|
||||
* It can also allocate memory while just holding cpuset_mutex. While it is
|
||||
* performing these checks, various callback routines can briefly acquire
|
||||
* callback_lock to query cpusets. Once it is ready to make the changes, it
|
||||
* takes callback_lock, blocking everyone else.
|
||||
*
|
||||
* Calls to the kernel memory allocator can not be made while holding
|
||||
* callback_lock, as that would risk double tripping on callback_lock
|
||||
* from one of the callbacks into the cpuset code from within
|
||||
* __alloc_pages().
|
||||
*
|
||||
* If a task is only holding callback_lock, then it has read-only
|
||||
* access to cpusets.
|
||||
*
|
||||
* Now, the task_struct fields mems_allowed and mempolicy may be changed
|
||||
* by other task, we use alloc_lock in the task_struct fields to protect
|
||||
* them.
|
||||
*
|
||||
* The cpuset_common_seq_show() handlers only hold callback_lock across
|
||||
* small pieces of code, such as when reading out possibly multi-word
|
||||
* cpumasks and nodemasks.
|
||||
*/
|
||||
|
||||
static DEFINE_MUTEX(cpuset_mutex);
|
||||
|
||||
/**
|
||||
* cpuset_lock - Acquire the global cpuset mutex
|
||||
*
|
||||
@@ -283,6 +319,7 @@ void lockdep_assert_cpuset_lock_held(void)
|
||||
*/
|
||||
void cpuset_full_lock(void)
|
||||
{
|
||||
mutex_lock(&cpuset_top_mutex);
|
||||
cpus_read_lock();
|
||||
mutex_lock(&cpuset_mutex);
|
||||
}
|
||||
@@ -291,12 +328,14 @@ void cpuset_full_unlock(void)
|
||||
{
|
||||
mutex_unlock(&cpuset_mutex);
|
||||
cpus_read_unlock();
|
||||
mutex_unlock(&cpuset_top_mutex);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
bool lockdep_is_cpuset_held(void)
|
||||
{
|
||||
return lockdep_is_held(&cpuset_mutex);
|
||||
return lockdep_is_held(&cpuset_mutex) ||
|
||||
lockdep_is_held(&cpuset_top_mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -961,7 +1000,7 @@ void rebuild_sched_domains_locked(void)
|
||||
* offline CPUs, a warning is emitted and we return directly to
|
||||
* prevent the panic.
|
||||
*/
|
||||
for (i = 0; i < ndoms; ++i) {
|
||||
for (i = 0; doms && i < ndoms; i++) {
|
||||
if (WARN_ON_ONCE(!cpumask_subset(doms[i], cpu_active_mask)))
|
||||
return;
|
||||
}
|
||||
@@ -1161,12 +1200,18 @@ static void reset_partition_data(struct cpuset *cs)
|
||||
static void isolated_cpus_update(int old_prs, int new_prs, struct cpumask *xcpus)
|
||||
{
|
||||
WARN_ON_ONCE(old_prs == new_prs);
|
||||
if (new_prs == PRS_ISOLATED)
|
||||
lockdep_assert_held(&callback_lock);
|
||||
lockdep_assert_held(&cpuset_mutex);
|
||||
if (new_prs == PRS_ISOLATED) {
|
||||
if (cpumask_subset(xcpus, isolated_cpus))
|
||||
return;
|
||||
cpumask_or(isolated_cpus, isolated_cpus, xcpus);
|
||||
else
|
||||
} else {
|
||||
if (!cpumask_intersects(xcpus, isolated_cpus))
|
||||
return;
|
||||
cpumask_andnot(isolated_cpus, isolated_cpus, xcpus);
|
||||
|
||||
isolated_cpus_updating = true;
|
||||
}
|
||||
update_housekeeping = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1219,8 +1264,8 @@ static void partition_xcpus_del(int old_prs, struct cpuset *parent,
|
||||
isolated_cpus_update(old_prs, parent->partition_root_state,
|
||||
xcpus);
|
||||
|
||||
cpumask_and(xcpus, xcpus, cpu_active_mask);
|
||||
cpumask_or(parent->effective_cpus, parent->effective_cpus, xcpus);
|
||||
cpumask_and(parent->effective_cpus, parent->effective_cpus, cpu_active_mask);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1284,22 +1329,43 @@ static bool prstate_housekeeping_conflict(int prstate, struct cpumask *new_cpus)
|
||||
}
|
||||
|
||||
/*
|
||||
* update_isolation_cpumasks - Update external isolation related CPU masks
|
||||
* update_hk_sched_domains - Update HK cpumasks & rebuild sched domains
|
||||
*
|
||||
* The following external CPU masks will be updated if necessary:
|
||||
* - workqueue unbound cpumask
|
||||
* Update housekeeping cpumasks and rebuild sched domains if necessary.
|
||||
* This should be called at the end of cpuset or hotplug actions.
|
||||
*/
|
||||
static void update_isolation_cpumasks(void)
|
||||
static void update_hk_sched_domains(void)
|
||||
{
|
||||
int ret;
|
||||
if (update_housekeeping) {
|
||||
/* Updating HK cpumasks implies rebuild sched domains */
|
||||
update_housekeeping = false;
|
||||
force_sd_rebuild = true;
|
||||
cpumask_copy(isolated_hk_cpus, isolated_cpus);
|
||||
|
||||
if (!isolated_cpus_updating)
|
||||
return;
|
||||
/*
|
||||
* housekeeping_update() is now called without holding
|
||||
* cpus_read_lock and cpuset_mutex. Only cpuset_top_mutex
|
||||
* is still being held for mutual exclusion.
|
||||
*/
|
||||
mutex_unlock(&cpuset_mutex);
|
||||
cpus_read_unlock();
|
||||
WARN_ON_ONCE(housekeeping_update(isolated_hk_cpus));
|
||||
cpus_read_lock();
|
||||
mutex_lock(&cpuset_mutex);
|
||||
}
|
||||
/* force_sd_rebuild will be cleared in rebuild_sched_domains_locked() */
|
||||
if (force_sd_rebuild)
|
||||
rebuild_sched_domains_locked();
|
||||
}
|
||||
|
||||
ret = housekeeping_update(isolated_cpus);
|
||||
WARN_ON_ONCE(ret < 0);
|
||||
|
||||
isolated_cpus_updating = false;
|
||||
/*
|
||||
* Work function to invoke update_hk_sched_domains()
|
||||
*/
|
||||
static void hk_sd_workfn(struct work_struct *work)
|
||||
{
|
||||
cpuset_full_lock();
|
||||
update_hk_sched_domains();
|
||||
cpuset_full_unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1450,7 +1516,6 @@ static int remote_partition_enable(struct cpuset *cs, int new_prs,
|
||||
cs->remote_partition = true;
|
||||
cpumask_copy(cs->effective_xcpus, tmp->new_cpus);
|
||||
spin_unlock_irq(&callback_lock);
|
||||
update_isolation_cpumasks();
|
||||
cpuset_force_rebuild();
|
||||
cs->prs_err = 0;
|
||||
|
||||
@@ -1495,7 +1560,6 @@ static void remote_partition_disable(struct cpuset *cs, struct tmpmasks *tmp)
|
||||
compute_excpus(cs, cs->effective_xcpus);
|
||||
reset_partition_data(cs);
|
||||
spin_unlock_irq(&callback_lock);
|
||||
update_isolation_cpumasks();
|
||||
cpuset_force_rebuild();
|
||||
|
||||
/*
|
||||
@@ -1566,7 +1630,6 @@ static void remote_cpus_update(struct cpuset *cs, struct cpumask *xcpus,
|
||||
if (xcpus)
|
||||
cpumask_copy(cs->exclusive_cpus, xcpus);
|
||||
spin_unlock_irq(&callback_lock);
|
||||
update_isolation_cpumasks();
|
||||
if (adding || deleting)
|
||||
cpuset_force_rebuild();
|
||||
|
||||
@@ -1910,7 +1973,6 @@ write_error:
|
||||
partition_xcpus_add(new_prs, parent, tmp->delmask);
|
||||
|
||||
spin_unlock_irq(&callback_lock);
|
||||
update_isolation_cpumasks();
|
||||
|
||||
if ((old_prs != new_prs) && (cmd == partcmd_update))
|
||||
update_partition_exclusive_flag(cs, new_prs);
|
||||
@@ -2155,7 +2217,7 @@ get_css:
|
||||
WARN_ON(!is_in_v2_mode() &&
|
||||
!cpumask_equal(cp->cpus_allowed, cp->effective_cpus));
|
||||
|
||||
cpuset_update_tasks_cpumask(cp, cp->effective_cpus);
|
||||
cpuset_update_tasks_cpumask(cp, tmp->new_cpus);
|
||||
|
||||
/*
|
||||
* On default hierarchy, inherit the CS_SCHED_LOAD_BALANCE
|
||||
@@ -2878,7 +2940,6 @@ out:
|
||||
else if (isolcpus_updated)
|
||||
isolated_cpus_update(old_prs, new_prs, cs->effective_xcpus);
|
||||
spin_unlock_irq(&callback_lock);
|
||||
update_isolation_cpumasks();
|
||||
|
||||
/* Force update if switching back to member & update effective_xcpus */
|
||||
update_cpumasks_hier(cs, &tmpmask, !new_prs);
|
||||
@@ -3168,9 +3229,8 @@ ssize_t cpuset_write_resmask(struct kernfs_open_file *of,
|
||||
}
|
||||
|
||||
free_cpuset(trialcs);
|
||||
if (force_sd_rebuild)
|
||||
rebuild_sched_domains_locked();
|
||||
out_unlock:
|
||||
update_hk_sched_domains();
|
||||
cpuset_full_unlock();
|
||||
if (of_cft(of)->private == FILE_MEMLIST)
|
||||
schedule_flush_migrate_mm();
|
||||
@@ -3278,6 +3338,7 @@ static ssize_t cpuset_partition_write(struct kernfs_open_file *of, char *buf,
|
||||
cpuset_full_lock();
|
||||
if (is_cpuset_online(cs))
|
||||
retval = update_prstate(cs, val);
|
||||
update_hk_sched_domains();
|
||||
cpuset_full_unlock();
|
||||
return retval ?: nbytes;
|
||||
}
|
||||
@@ -3452,6 +3513,7 @@ static void cpuset_css_killed(struct cgroup_subsys_state *css)
|
||||
/* Reset valid partition back to member */
|
||||
if (is_partition_valid(cs))
|
||||
update_prstate(cs, PRS_MEMBER);
|
||||
update_hk_sched_domains();
|
||||
cpuset_full_unlock();
|
||||
}
|
||||
|
||||
@@ -3607,6 +3669,7 @@ int __init cpuset_init(void)
|
||||
BUG_ON(!alloc_cpumask_var(&top_cpuset.exclusive_cpus, GFP_KERNEL));
|
||||
BUG_ON(!zalloc_cpumask_var(&subpartitions_cpus, GFP_KERNEL));
|
||||
BUG_ON(!zalloc_cpumask_var(&isolated_cpus, GFP_KERNEL));
|
||||
BUG_ON(!zalloc_cpumask_var(&isolated_hk_cpus, GFP_KERNEL));
|
||||
|
||||
cpumask_setall(top_cpuset.cpus_allowed);
|
||||
nodes_setall(top_cpuset.mems_allowed);
|
||||
@@ -3778,6 +3841,7 @@ unlock:
|
||||
*/
|
||||
static void cpuset_handle_hotplug(void)
|
||||
{
|
||||
static DECLARE_WORK(hk_sd_work, hk_sd_workfn);
|
||||
static cpumask_t new_cpus;
|
||||
static nodemask_t new_mems;
|
||||
bool cpus_updated, mems_updated;
|
||||
@@ -3859,9 +3923,21 @@ static void cpuset_handle_hotplug(void)
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/* rebuild sched domains if necessary */
|
||||
if (force_sd_rebuild)
|
||||
rebuild_sched_domains_cpuslocked();
|
||||
|
||||
/*
|
||||
* Queue a work to call housekeeping_update() & rebuild_sched_domains()
|
||||
* There will be a slight delay before the HK_TYPE_DOMAIN housekeeping
|
||||
* cpumask can correctly reflect what is in isolated_cpus.
|
||||
*
|
||||
* We rely on WORK_STRUCT_PENDING_BIT to not requeue a work item that
|
||||
* is still pending. Before the pending bit is cleared, the work data
|
||||
* is copied out and work item dequeued. So it is possible to queue
|
||||
* the work again before the hk_sd_workfn() is invoked to process the
|
||||
* previously queued work. Since hk_sd_workfn() doesn't use the work
|
||||
* item at all, this is not a problem.
|
||||
*/
|
||||
if (update_housekeeping || force_sd_rebuild)
|
||||
queue_work(system_unbound_wq, &hk_sd_work);
|
||||
|
||||
free_tmpmasks(ptmp);
|
||||
}
|
||||
|
||||
@@ -123,8 +123,6 @@ int housekeeping_update(struct cpumask *isol_mask)
|
||||
struct cpumask *trial, *old = NULL;
|
||||
int err;
|
||||
|
||||
lockdep_assert_cpus_held();
|
||||
|
||||
trial = kmalloc(cpumask_size(), GFP_KERNEL);
|
||||
if (!trial)
|
||||
return -ENOMEM;
|
||||
@@ -136,7 +134,7 @@ int housekeeping_update(struct cpumask *isol_mask)
|
||||
}
|
||||
|
||||
if (!housekeeping.flags)
|
||||
static_branch_enable_cpuslocked(&housekeeping_overridden);
|
||||
static_branch_enable(&housekeeping_overridden);
|
||||
|
||||
if (housekeeping.flags & HK_FLAG_DOMAIN)
|
||||
old = housekeeping_cpumask_dereference(HK_TYPE_DOMAIN);
|
||||
|
||||
@@ -1559,8 +1559,6 @@ int tmigr_isolated_exclude_cpumask(struct cpumask *exclude_cpumask)
|
||||
cpumask_var_t cpumask __free(free_cpumask_var) = CPUMASK_VAR_NULL;
|
||||
int cpu;
|
||||
|
||||
lockdep_assert_cpus_held();
|
||||
|
||||
if (!works)
|
||||
return -ENOMEM;
|
||||
if (!alloc_cpumask_var(&cpumask, GFP_KERNEL))
|
||||
@@ -1570,6 +1568,7 @@ int tmigr_isolated_exclude_cpumask(struct cpumask *exclude_cpumask)
|
||||
* First set previously isolated CPUs as available (unisolate).
|
||||
* This cpumask contains only CPUs that switched to available now.
|
||||
*/
|
||||
guard(cpus_read_lock)();
|
||||
cpumask_andnot(cpumask, cpu_online_mask, exclude_cpumask);
|
||||
cpumask_andnot(cpumask, cpumask, tmigr_available_cpumask);
|
||||
|
||||
@@ -1626,7 +1625,6 @@ static int __init tmigr_init_isolation(void)
|
||||
cpumask_andnot(cpumask, cpu_possible_mask, housekeeping_cpumask(HK_TYPE_DOMAIN));
|
||||
|
||||
/* Protect against RCU torture hotplug testing */
|
||||
guard(cpus_read_lock)();
|
||||
return tmigr_isolated_exclude_cpumask(cpumask);
|
||||
}
|
||||
late_initcall(tmigr_init_isolation);
|
||||
|
||||
@@ -196,7 +196,6 @@ test_add_proc()
|
||||
# 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
|
||||
# CX<l> = add cpu-list to both cpuset.cpus and cpuset.cpus.exclusive
|
||||
# O<c>=<v> = Write <v> to CPU online file of <c>
|
||||
@@ -209,44 +208,46 @@ test_add_proc()
|
||||
# sched-debug matching which includes offline CPUs and single-CPU partitions
|
||||
# while the second one is for matching cpuset.cpus.isolated.
|
||||
#
|
||||
SETUP_A123_PARTITIONS="C1-3:P1:S+ C2-3:P1:S+ C3:P1"
|
||||
SETUP_A123_PARTITIONS="C1-3:P1 C2-3:P1 C3:P1"
|
||||
TEST_MATRIX=(
|
||||
# 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 . 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 . . C2-3 P1 C0-1:P1 . . 0 "
|
||||
" C0-1 . . C2-3 P1 C1:P1 . . 0 "
|
||||
" C0-1 . . C2-3 . . . P1 0 "
|
||||
" C0-1:P1 . . C2-3 . C1 . . 0 "
|
||||
" C0-1:P1 . . C2-3 . C1:P1 . . 0 "
|
||||
" C0-1:P1 . . C2-3 . 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|XA2:2-3"
|
||||
"C0-3:P1:S+ C2-3:P1 . . C1-3 . . . 0 A1:1|A2:2-3|XA2:2-3"
|
||||
"C2-3:P1:S+ C3:P1 . . C3 . . . 0 A1:|A2:3|XA2: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"
|
||||
" C0-3:P1 C2-3:P1 . . . . . . 0 A1:0-1|A2:2-3|XA2:2-3"
|
||||
" C0-3:P1 C2-3:P1 . . C1-3 . . . 0 A1:1|A2:2-3|XA2:2-3"
|
||||
" C2-3:P1 C3:P1 . . C3 . . . 0 A1:|A2:3|XA2:3 A1:P1|A2:P1"
|
||||
" C2-3:P1 C3:P1 . . C3 P0 . . 0 A1:3|A2:3 A1:P1|A2:P0"
|
||||
" C2-3:P1 C2:P1 . . C2-4 . . . 0 A1:3-4|A2:2"
|
||||
" C2-3:P1 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:
|
||||
" 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"
|
||||
" C0-1 . . C2-3 . C4-5 . O2=0 0 A1:0-1|B1:3"
|
||||
" C0-3:P1 C2-3:P1 . . O2=0 . . . 0 A1:0-1|A2:3"
|
||||
" C0-3:P1 C2-3:P1 . . O2=0 O2=1 . . 0 A1:0-1|A2:2-3"
|
||||
" C0-3:P1 C2-3:P1 . . O1=0 . . . 0 A1:0|A2:2-3"
|
||||
" C0-3:P1 C2-3:P1 . . O1=0 O1=1 . . 0 A1:0-1|A2:2-3"
|
||||
" C2-3:P1 C3:P1 . . O3=0 O3=1 . . 0 A1:2|A2:3 A1:P1|A2:P1"
|
||||
" C2-3:P1 C3:P2 . . O3=0 O3=1 . . 0 A1:2|A2:3 A1:P1|A2:P2"
|
||||
" C2-3:P1 C3:P1 . . O2=0 O2=1 . . 0 A1:2|A2:3 A1:P1|A2:P1"
|
||||
" C2-3:P1 C3:P2 . . O2=0 O2=1 . . 0 A1:2|A2:3 A1:P1|A2:P2"
|
||||
" C2-3:P1 C3:P1 . . O2=0 . . . 0 A1:|A2:3 A1:P1|A2:P1"
|
||||
" C2-3:P1 C3:P1 . . O3=0 . . . 0 A1:2|A2: A1:P1|A2:P1"
|
||||
" C2-3:P1 C3:P1 . . T:O2=0 . . . 0 A1:3|A2:3 A1:P1|A2:P-1"
|
||||
" C2-3:P1 C3:P1 . . . T:O3=0 . . 0 A1:2|A2:2 A1:P1|A2:P-1"
|
||||
" C2-3:P1 C3:P2 . . T:O2=0 . . . 0 A1:3|A2:3 A1:P1|A2:P-2"
|
||||
" C1-3:P1 C3:P2 . . . T:O3=0 . . 0 A1:1-2|A2:1-2 A1:P1|A2:P-2 3|"
|
||||
" C1-3:P1 C3:P2 . . . T:O3=0 O3=1 . 0 A1:1-2|A2:3 A1:P1|A2:P2 3"
|
||||
"$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"
|
||||
@@ -264,88 +265,87 @@ TEST_MATRIX=(
|
||||
#
|
||||
# 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-1|A2:1|A3:2-3 A1:P0|A3:P2 2-3"
|
||||
" C0-3:S+ C1-3:S+ C2-3 C2-3 . . . P2 0 A1:0-1|A2:1|A3:1|B1:2-3 A1:P0|A3:P0|B1:P2"
|
||||
" 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"
|
||||
" C4:X0-3:S+ X1-3:S+ X2-3 . . P2 . . 0 A1:4|A2:1-3|A3:1-3 A2:P2 1-3"
|
||||
" C4:X0-3:S+ X1-3:S+ X2-3 . . . P2 . 0 A1:4|A2:4|A3:2-3 A3:P2 2-3"
|
||||
" C0-3 C1-3 C2-3 . X2-3 . . . 0 A1:0-3|A2:1-3|A3:2-3|XA1:2-3"
|
||||
" C0-3 C1-3 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 C1-3 C2-3 . X2-3 X3:P2 . . 0 A1:0-2|A2:3|A3:3 A1:P0|A2:P2 3"
|
||||
" C0-3 C1-3 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 C1-3 C2-3 . X2-3 X2-3 X2-3:P2:C3 . 0 A1:0-1|A2:1|A3:2-3 A1:P0|A3:P2 2-3"
|
||||
" C0-3 C1-3 C2-3 C2-3 . . . P2 0 A1:0-1|A2:1|A3:1|B1:2-3 A1:P0|A3:P0|B1:P2"
|
||||
" C0-3 C1-3 C2-3 C4-5 . . . P2 0 B1:4-5 B1:P2 4-5"
|
||||
" C0-3 C1-3 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 C1-3 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 C1-3 C2-3 C4 X1-3 X1-3:P2 P2 . 0 A2:1|A3:2-3 A2:P2|A3:P2 1-3"
|
||||
" C0-3 C1-3 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"
|
||||
" C4:X0-3 X1-3 X2-3 . . P2 . . 0 A1:4|A2:1-3|A3:1-3 A2:P2 1-3"
|
||||
" C4:X0-3 X1-3 X2-3 . . . P2 . 0 A1:4|A2:4|A3:2-3 A3:P2 2-3"
|
||||
|
||||
# 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 \
|
||||
" C0-3 C1-3 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 \
|
||||
" C0-3 C1-3 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|2-3"
|
||||
" C0-3:S+ C1-3:S+ C2-3 C4 X2-3 X2-3:P1 . P1 0 A1:0-1|A2:2-3|A3:2-3|B1:4 \
|
||||
" C0-3 C1-3 C2-3 C4 X2-3 X2-3:P1 . P1 0 A1:0-1|A2:2-3|A3:2-3|B1:4 \
|
||||
A1:P0|A2:P1|A3:P0|B1:P1"
|
||||
" 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 \
|
||||
" 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:S+ C1-4:S+ C2-4 . X2-4 X2-4:P2 X4:P1 . 0 A1:0-1|A2:2-3|A3:4 \
|
||||
" 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:S+ C1-4:S+ C2-4 . X2-4 X2-4:P2 X3-4:P1 . 0 A1:0-1|A2:2|A3:3-4 \
|
||||
" 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"
|
||||
" C0-4:X2-4:S+ C1-4:X2-4:S+:P2 C2-4:X4:P1 \
|
||||
" C0-4:X2-4 C1-4:X2-4: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 \
|
||||
" 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"
|
||||
|
||||
# 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|"
|
||||
" C0-3 C1-3 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 C1-3 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 C1-3 C3 . X2-3 X2-3 P2:O3=0 . 0 A1:0-2|A2:1-2|A3: A1:P0|A3:P2 3"
|
||||
" C0-3 C1-3 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 ."
|
||||
" C0-3 C1-3 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:"
|
||||
" C0-3 C1-3 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"
|
||||
" C0-3 C1-3 . . . X3:P2 . . 0 A1:0-3|A2:1-3|XA2: A2:P-2 ."
|
||||
" C0-3 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 X4:P2 . . . . . . 0 A1:1-3|XA1:1-3|A2:1-3:XA2: A1:P2|A2:P-2 1-3"
|
||||
" C1-3:S+:P2 X4:P2 . . . X3:P2 . . 0 A1:1-2|XA1:1-3|A2:3:XA2:3 A1:P2|A2:P2 1-3"
|
||||
" C1-3:P2 X4:P2 . . . . . . 0 A1:1-3|XA1:1-3|A2:1-3:XA2: A1:P2|A2:P-2 1-3"
|
||||
" C1-3:P2 X4: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:5-6 A1:P2|B1:P0"
|
||||
" C0-3:P2 . . C4-6 C0-4:C0-3 . . . 0 A1:0-3|B1:4-6 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 \
|
||||
" C0-3:X1-3:P2 C1-3:X2-3: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 \
|
||||
" C0-3:X1-3:P2 C1-3:X2-3: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 \
|
||||
" 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: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"
|
||||
" 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"
|
||||
|
||||
# cpus_allowed/exclusive_cpus update tests
|
||||
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3 \
|
||||
" C0-3:X2-3 C1-3:X2-3 C2-3:X2-3 \
|
||||
. X: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 \
|
||||
" C0-3:X2-3 C1-3:X2-3 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 \
|
||||
" C0-3:X2-3 C1-3:X2-3 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 \
|
||||
" C0-3:X2-3 C1-3:X2-3 C2-3:X2-3:P2 \
|
||||
. . X3 . . 0 A1:0-2|A2:1-2|XA2:3|XA3:3|A3:3|XA3:3 \
|
||||
A1:P0|A3:P2 3"
|
||||
" C0-3:X2-3:S+ C1-3:X2-3:S+ C2-3:X2-3:P2 \
|
||||
" C0-3:X2-3 C1-3:X2-3 C2-3:X2-3:P2 \
|
||||
. X4 . . . 0 A1:0-3|A2:1-3|A3:2-3|XA1:4|XA2:|XA3 \
|
||||
A1:P0|A3:P-2"
|
||||
|
||||
@@ -356,37 +356,37 @@ TEST_MATRIX=(
|
||||
#
|
||||
# Adding CPUs to partition root that are not in parent's
|
||||
# cpuset.cpus is allowed, but those extra CPUs are ignored.
|
||||
"C2-3:P1:S+ C3:P1 . . . C2-4 . . 0 A1:|A2:2-3 A1:P1|A2:P1"
|
||||
" C2-3:P1 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.
|
||||
"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"
|
||||
" C2-3:P1 C3:P1 . . T C2-3 . . 0 A1:2-3|A2:2-3 A1:P1|A2:P-1"
|
||||
" C3:P1 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
|
||||
"C2-3:P1:S+ C3:P1 . . P0 . . . 0 A1:2-3|A2:3 A1:P0|A2:P-1"
|
||||
" C2-3:P1 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.
|
||||
"C2-3:P1:S+ . . . . C3-4:P1 . . 0 A1:2|A2:3 A1:P1|A2:P1"
|
||||
" C2-3:P1 . . . . C3-4:P1 . . 0 A1:2|A2:3 A1:P1|A2:P1"
|
||||
|
||||
# Deletion of CPUs distributed to child cgroup is allowed.
|
||||
"C0-1:P1:S+ C1 . C2-3 C4-5 . . . 0 A1:4-5|A2:4-5"
|
||||
" C0-1:P1 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.
|
||||
" 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 . C4-5:P1 . . 0 A1:0-1|A2:0-1 A1:P1|A2:P-1"
|
||||
|
||||
# Enabling partition with child cpusets is allowed
|
||||
" C0-1:S+ C1 . C2-3 P1 . . . 0 A1:0-1|A2:1 A1:P1"
|
||||
" C0-1 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.
|
||||
" 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 0-1|1"
|
||||
" C0-1 C1 . C2-3 . P2 . . 0 A1:0-1|A2:1 A1:P0|A2:P-2"
|
||||
" C0-1 C1:P2 . C2-3 P1 . . . 0 A1:0|A2:1 A1:P1|A2:P2 0-1|1"
|
||||
|
||||
# A non-exclusive cpuset.cpus change will not invalidate its siblings partition.
|
||||
" C0-1:P1 . . C2-3 C0-2 . . . 0 A1:0-2|B1:3 A1:P1|B1:P0"
|
||||
@@ -398,23 +398,23 @@ TEST_MATRIX=(
|
||||
|
||||
# Child partition root that try to take all CPUs from parent partition
|
||||
# with tasks will remain invalid.
|
||||
" C1-4:P1:S+ P1 . . . . . . 0 A1:1-4|A2:1-4 A1:P1|A2:P-1"
|
||||
" C1-4:P1:S+ P1 . . . C1-4 . . 0 A1|A2:1-4 A1:P1|A2:P1"
|
||||
" C1-4:P1:S+ P1 . . T C1-4 . . 0 A1:1-4|A2:1-4 A1:P1|A2:P-1"
|
||||
" C1-4:P1 P1 . . . . . . 0 A1:1-4|A2:1-4 A1:P1|A2:P-1"
|
||||
" C1-4:P1 P1 . . . C1-4 . . 0 A1|A2:1-4 A1:P1|A2:P1"
|
||||
" C1-4:P1 P1 . . T C1-4 . . 0 A1:1-4|A2:1-4 A1:P1|A2:P-1"
|
||||
|
||||
# Clearing of cpuset.cpus with a preset cpuset.cpus.exclusive shouldn't
|
||||
# affect cpuset.cpus.exclusive.effective.
|
||||
" C1-4:X3:S+ C1:X3 . . . C . . 0 A2:1-4|XA2:3"
|
||||
" C1-4:X3 C1:X3 . . . C . . 0 A2:1-4|XA2:3"
|
||||
|
||||
# cpuset.cpus can contain CPUs that overlap a sibling cpuset with cpus.exclusive
|
||||
# but creating a local partition out of it is not allowed. Similarly and change
|
||||
# in cpuset.cpus of a local partition that overlaps sibling exclusive CPUs will
|
||||
# invalidate it.
|
||||
" CX1-4:S+ CX2-4:P2 . C5-6 . . . P1 0 A1:1|A2:2-4|B1:5-6|XB1:5-6 \
|
||||
" CX1-4 CX2-4:P2 . C5-6 . . . P1 0 A1:1|A2:2-4|B1:5-6|XB1:5-6 \
|
||||
A1:P0|A2:P2:B1:P1 2-4"
|
||||
" CX1-4:S+ CX2-4:P2 . C3-6 . . . P1 0 A1:1|A2:2-4|B1:5-6 \
|
||||
" CX1-4 CX2-4:P2 . C3-6 . . . P1 0 A1:1|A2:2-4|B1:5-6 \
|
||||
A1:P0|A2:P2:B1:P-1 2-4"
|
||||
" CX1-4:S+ CX2-4:P2 . C5-6 . . . P1:C3-6 0 A1:1|A2:2-4|B1:5-6 \
|
||||
" CX1-4 CX2-4:P2 . C5-6 . . . P1:C3-6 0 A1:1|A2:2-4|B1:5-6 \
|
||||
A1:P0|A2:P2:B1:P-1 2-4"
|
||||
|
||||
# When multiple partitions with conflicting cpuset.cpus are created, the
|
||||
@@ -426,14 +426,14 @@ TEST_MATRIX=(
|
||||
" C1-3:X1-3 . . C4-5 . . . C1-2 0 A1:1-3|B1:1-2"
|
||||
|
||||
# cpuset.cpus can become empty with task in it as it inherits parent's effective CPUs
|
||||
" C1-3:S+ C2 . . . T:C . . 0 A1:1-3|A2:1-3"
|
||||
" C1-3 C2 . . . T:C . . 0 A1:1-3|A2:1-3"
|
||||
|
||||
# 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
|
||||
"C2-3:P1:S+ C3:P1 . . O2=0:T . . . 1 A1:|A2:3 A1:P1|A2:P1"
|
||||
" C2-3:P1 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"
|
||||
@@ -465,31 +465,31 @@ REMOTE_TEST_MATRIX=(
|
||||
# old-p1 old-p2 old-c11 old-c12 old-c21 old-c22
|
||||
# new-p1 new-p2 new-c11 new-c12 new-c21 new-c22 ECPUs Pstate ISOLCPUS
|
||||
# ------ ------ ------- ------- ------- ------- ----- ------ --------
|
||||
" X1-3:S+ X4-6:S+ X1-2 X3 X4-5 X6 \
|
||||
" X1-3 X4-6 X1-2 X3 X4-5 X6 \
|
||||
. . P2 P2 P2 P2 c11:1-2|c12:3|c21:4-5|c22:6 \
|
||||
c11:P2|c12:P2|c21:P2|c22:P2 1-6"
|
||||
" CX1-4:S+ . X1-2:P2 C3 . . \
|
||||
" CX1-4 . X1-2:P2 C3 . . \
|
||||
. . . C3-4 . . p1:3-4|c11:1-2|c12:3-4 \
|
||||
p1:P0|c11:P2|c12:P0 1-2"
|
||||
" CX1-4:S+ . X1-2:P2 . . . \
|
||||
" CX1-4 . X1-2:P2 . . . \
|
||||
X2-4 . . . . . p1:1,3-4|c11:2 \
|
||||
p1:P0|c11:P2 2"
|
||||
" CX1-5:S+ . X1-2:P2 X3-5:P1 . . \
|
||||
" CX1-5 . X1-2:P2 X3-5:P1 . . \
|
||||
X2-4 . . . . . p1:1,5|c11:2|c12:3-4 \
|
||||
p1:P0|c11:P2|c12:P1 2"
|
||||
" CX1-4:S+ . X1-2:P2 X3-4:P1 . . \
|
||||
" CX1-4 . X1-2:P2 X3-4:P1 . . \
|
||||
. . X2 . . . p1:1|c11:2|c12:3-4 \
|
||||
p1:P0|c11:P2|c12:P1 2"
|
||||
# p1 as member, will get its effective CPUs from its parent rtest
|
||||
" CX1-4:S+ . X1-2:P2 X3-4:P1 . . \
|
||||
" CX1-4 . X1-2:P2 X3-4:P1 . . \
|
||||
. . X1 CX2-4 . . p1:5-7|c11:1|c12:2-4 \
|
||||
p1:P0|c11:P2|c12:P1 1"
|
||||
" CX1-4:S+ X5-6:P1:S+ . . . . \
|
||||
" CX1-4 X5-6:P1 . . . . \
|
||||
. . X1-2:P2 X4-5:P1 . X1-7:P2 p1:3|c11:1-2|c12:4:c22:5-6 \
|
||||
p1:P0|p2:P1|c11:P2|c12:P1|c22:P2 \
|
||||
1-2,4-6|1-2,5-6"
|
||||
# c12 whose cpuset.cpus CPUs are all granted to c11 will become invalid partition
|
||||
" C1-5:P1:S+ . C1-4:P1 C2-3 . . \
|
||||
" C1-5:P1 . C1-4:P1 C2-3 . . \
|
||||
. . . P1 . . p1:5|c11:1-4|c12:5 \
|
||||
p1:P1|c11:P1|c12:P-1"
|
||||
)
|
||||
@@ -530,7 +530,6 @@ set_ctrl_state()
|
||||
CGRP=$1
|
||||
STATE=$2
|
||||
SHOWERR=${3}
|
||||
CTRL=${CTRL:=$CONTROLLER}
|
||||
HASERR=0
|
||||
REDIRECT="2> $TMPMSG"
|
||||
[[ -z "$STATE" || "$STATE" = '.' ]] && return 0
|
||||
@@ -540,15 +539,16 @@ set_ctrl_state()
|
||||
for CMD in $(echo $STATE | sed -e "s/:/ /g")
|
||||
do
|
||||
TFILE=$CGRP/cgroup.procs
|
||||
SFILE=$CGRP/cgroup.subtree_control
|
||||
PFILE=$CGRP/cpuset.cpus.partition
|
||||
CFILE=$CGRP/cpuset.cpus
|
||||
XFILE=$CGRP/cpuset.cpus.exclusive
|
||||
case $CMD in
|
||||
S*) PREFIX=${CMD#?}
|
||||
COMM="echo ${PREFIX}${CTRL} > $SFILE"
|
||||
|
||||
# Enable cpuset controller if not enabled yet
|
||||
[[ -f $CFILE ]] || {
|
||||
COMM="echo +cpuset > $CGRP/../cgroup.subtree_control"
|
||||
eval $COMM $REDIRECT
|
||||
;;
|
||||
}
|
||||
case $CMD in
|
||||
X*)
|
||||
CPUS=${CMD#?}
|
||||
COMM="echo $CPUS > $XFILE"
|
||||
@@ -764,7 +764,7 @@ check_cgroup_states()
|
||||
# only CPUs in isolated partitions as well as those that are isolated at
|
||||
# boot time.
|
||||
#
|
||||
# $1 - expected isolated cpu list(s) <isolcpus1>{,<isolcpus2>}
|
||||
# $1 - expected isolated cpu list(s) <isolcpus1>{|<isolcpus2>}
|
||||
# <isolcpus1> - expected sched/domains value
|
||||
# <isolcpus2> - cpuset.cpus.isolated value = <isolcpus1> if not defined
|
||||
#
|
||||
@@ -773,6 +773,7 @@ check_isolcpus()
|
||||
EXPECTED_ISOLCPUS=$1
|
||||
ISCPUS=${CGROUP2}/cpuset.cpus.isolated
|
||||
ISOLCPUS=$(cat $ISCPUS)
|
||||
HKICPUS=$(cat /sys/devices/system/cpu/isolated)
|
||||
LASTISOLCPU=
|
||||
SCHED_DOMAINS=/sys/kernel/debug/sched/domains
|
||||
if [[ $EXPECTED_ISOLCPUS = . ]]
|
||||
@@ -810,6 +811,11 @@ check_isolcpus()
|
||||
ISOLCPUS=
|
||||
EXPECTED_ISOLCPUS=$EXPECTED_SDOMAIN
|
||||
|
||||
#
|
||||
# The inverse of HK_TYPE_DOMAIN cpumask in $HKICPUS should match $ISOLCPUS
|
||||
#
|
||||
[[ "$ISOLCPUS" != "$HKICPUS" ]] && return 1
|
||||
|
||||
#
|
||||
# Use the sched domain in debugfs to check isolated CPUs, if available
|
||||
#
|
||||
@@ -947,7 +953,6 @@ check_test_results()
|
||||
run_state_test()
|
||||
{
|
||||
TEST=$1
|
||||
CONTROLLER=cpuset
|
||||
CGROUP_LIST=". A1 A1/A2 A1/A2/A3 B1"
|
||||
RESET_LIST="A1/A2/A3 A1/A2 A1 B1"
|
||||
I=0
|
||||
@@ -1003,7 +1008,6 @@ run_state_test()
|
||||
run_remote_state_test()
|
||||
{
|
||||
TEST=$1
|
||||
CONTROLLER=cpuset
|
||||
[[ -d rtest ]] || mkdir rtest
|
||||
cd rtest
|
||||
echo +cpuset > cgroup.subtree_control
|
||||
|
||||
Reference in New Issue
Block a user