cpuset: remove v1-specific code from generate_sched_domains

Following the introduction of cpuset1_generate_sched_domains() for v1
in the previous patch, v1-specific logic can now be removed from the
generic generate_sched_domains(). This patch cleans up the v1-only
code and ensures uf_node is only visible when CONFIG_CPUSETS_V1=y.

Signed-off-by: Chen Ridong <chenridong@huawei.com>
Reviewed-by: Waiman Long <longman@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
Chen Ridong 2025-12-18 09:31:41 +00:00 committed by Tejun Heo
parent 6e1d31ce49
commit 7cc1720589
3 changed files with 28 additions and 129 deletions

View File

@ -175,14 +175,14 @@ struct cpuset {
/* Handle for cpuset.cpus.partition */
struct cgroup_file partition_file;
/* Used to merge intersecting subsets for generate_sched_domains */
struct uf_node node;
#ifdef CONFIG_CPUSETS_V1
struct fmeter fmeter; /* memory_pressure filter */
/* for custom sched domain */
int relax_domain_level;
/* Used to merge intersecting subsets for generate_sched_domains */
struct uf_node node;
#endif
};
@ -314,8 +314,6 @@ void cpuset1_hotplug_update_tasks(struct cpuset *cs,
int cpuset1_validate_change(struct cpuset *cur, struct cpuset *trial);
void cpuset1_init(struct cpuset *cs);
void cpuset1_online_css(struct cgroup_subsys_state *css);
void update_domain_attr_tree(struct sched_domain_attr *dattr,
struct cpuset *root_cs);
int cpuset1_generate_sched_domains(cpumask_var_t **domains,
struct sched_domain_attr **attributes);
@ -330,8 +328,6 @@ static inline int cpuset1_validate_change(struct cpuset *cur,
struct cpuset *trial) { return 0; }
static inline void cpuset1_init(struct cpuset *cs) {}
static inline void cpuset1_online_css(struct cgroup_subsys_state *css) {}
static inline void update_domain_attr_tree(struct sched_domain_attr *dattr,
struct cpuset *root_cs) {}
static inline int cpuset1_generate_sched_domains(cpumask_var_t **domains,
struct sched_domain_attr **attributes) { return 0; };

View File

@ -560,7 +560,7 @@ update_domain_attr(struct sched_domain_attr *dattr, struct cpuset *c)
dattr->relax_domain_level = c->relax_domain_level;
}
void update_domain_attr_tree(struct sched_domain_attr *dattr,
static void update_domain_attr_tree(struct sched_domain_attr *dattr,
struct cpuset *root_cs)
{
struct cpuset *cp;

View File

@ -789,18 +789,13 @@ static int generate_sched_domains(cpumask_var_t **domains,
{
struct cpuset *cp; /* top-down scan of cpusets */
struct cpuset **csa; /* array of all cpuset ptrs */
int csn; /* how many cpuset ptrs in csa so far */
int i, j; /* indices for partition finding loops */
cpumask_var_t *doms; /* resulting partition; i.e. sched domains */
struct sched_domain_attr *dattr; /* attributes for custom domains */
int ndoms = 0; /* number of sched domains in result */
int nslot; /* next empty doms[] struct cpumask slot */
struct cgroup_subsys_state *pos_css;
bool root_load_balance = is_sched_load_balance(&top_cpuset);
bool cgrpv2 = cpuset_v2();
int nslot_update;
if (!cgrpv2)
if (!cpuset_v2())
return cpuset1_generate_sched_domains(domains, attributes);
doms = NULL;
@ -808,70 +803,26 @@ static int generate_sched_domains(cpumask_var_t **domains,
csa = NULL;
/* Special case for the 99% of systems with one, full, sched domain */
if (root_load_balance && cpumask_empty(subpartitions_cpus)) {
single_root_domain:
if (cpumask_empty(subpartitions_cpus)) {
ndoms = 1;
doms = alloc_sched_domains(ndoms);
if (!doms)
goto done;
dattr = kmalloc(sizeof(struct sched_domain_attr), GFP_KERNEL);
if (dattr) {
*dattr = SD_ATTR_INIT;
update_domain_attr_tree(dattr, &top_cpuset);
}
cpumask_and(doms[0], top_cpuset.effective_cpus,
housekeeping_cpumask(HK_TYPE_DOMAIN));
goto done;
/* !csa will be checked and can be correctly handled */
goto generate_doms;
}
csa = kmalloc_array(nr_cpusets(), sizeof(cp), GFP_KERNEL);
if (!csa)
goto done;
csn = 0;
/* Find how many partitions and cache them to csa[] */
rcu_read_lock();
if (root_load_balance)
csa[csn++] = &top_cpuset;
cpuset_for_each_descendant_pre(cp, pos_css, &top_cpuset) {
if (cp == &top_cpuset)
continue;
if (cgrpv2)
goto v2;
/*
* v1:
* Continue traversing beyond @cp iff @cp has some CPUs and
* isn't load balancing. The former is obvious. The
* latter: All child cpusets contain a subset of the
* parent's cpus, so just skip them, and then we call
* update_domain_attr_tree() to calc relax_domain_level of
* the corresponding sched domain.
*/
if (!cpumask_empty(cp->cpus_allowed) &&
!(is_sched_load_balance(cp) &&
cpumask_intersects(cp->cpus_allowed,
housekeeping_cpumask(HK_TYPE_DOMAIN))))
continue;
if (is_sched_load_balance(cp) &&
!cpumask_empty(cp->effective_cpus))
csa[csn++] = cp;
/* skip @cp's subtree */
pos_css = css_rightmost_descendant(pos_css);
continue;
v2:
/*
* Only valid partition roots that are not isolated and with
* non-empty effective_cpus will be saved into csn[].
* non-empty effective_cpus will be saved into csa[].
*/
if ((cp->partition_root_state == PRS_ROOT) &&
!cpumask_empty(cp->effective_cpus))
csa[csn++] = cp;
csa[ndoms++] = cp;
/*
* Skip @cp's subtree if not a partition root and has no
@ -882,40 +833,18 @@ static int generate_sched_domains(cpumask_var_t **domains,
}
rcu_read_unlock();
/*
* If there are only isolated partitions underneath the cgroup root,
* we can optimize out unneeded sched domains scanning.
*/
if (root_load_balance && (csn == 1))
goto single_root_domain;
for (i = 0; i < csn; i++)
uf_node_init(&csa[i]->node);
/* Merge overlapping cpusets */
for (i = 0; i < csn; i++) {
for (j = i + 1; j < csn; j++) {
if (cpusets_overlap(csa[i], csa[j])) {
for (i = 0; i < ndoms; i++) {
for (j = i + 1; j < ndoms; j++) {
if (cpusets_overlap(csa[i], csa[j]))
/*
* Cgroup v2 shouldn't pass down overlapping
* partition root cpusets.
*/
WARN_ON_ONCE(cgrpv2);
uf_union(&csa[i]->node, &csa[j]->node);
}
WARN_ON_ONCE(1);
}
}
/* Count the total number of domains */
for (i = 0; i < csn; i++) {
if (uf_find(&csa[i]->node) == &csa[i]->node)
ndoms++;
}
/*
* Now we know how many domains to create.
* Convert <csn, csa> to <ndoms, doms> and populate cpu masks.
*/
generate_doms:
doms = alloc_sched_domains(ndoms);
if (!doms)
goto done;
@ -932,46 +861,20 @@ static int generate_sched_domains(cpumask_var_t **domains,
* to SD_ATTR_INIT. Also non-isolating partition root CPUs are a
* subset of HK_TYPE_DOMAIN housekeeping CPUs.
*/
if (cgrpv2) {
for (i = 0; i < ndoms; i++) {
/*
* The top cpuset may contain some boot time isolated
* CPUs that need to be excluded from the sched domain.
*/
if (csa[i] == &top_cpuset)
cpumask_and(doms[i], csa[i]->effective_cpus,
housekeeping_cpumask(HK_TYPE_DOMAIN));
else
cpumask_copy(doms[i], csa[i]->effective_cpus);
if (dattr)
dattr[i] = SD_ATTR_INIT;
}
goto done;
for (i = 0; i < ndoms; i++) {
/*
* The top cpuset may contain some boot time isolated
* CPUs that need to be excluded from the sched domain.
*/
if (!csa || csa[i] == &top_cpuset)
cpumask_and(doms[i], top_cpuset.effective_cpus,
housekeeping_cpumask(HK_TYPE_DOMAIN));
else
cpumask_copy(doms[i], csa[i]->effective_cpus);
if (dattr)
dattr[i] = SD_ATTR_INIT;
}
for (nslot = 0, i = 0; i < csn; i++) {
nslot_update = 0;
for (j = i; j < csn; j++) {
if (uf_find(&csa[j]->node) == &csa[i]->node) {
struct cpumask *dp = doms[nslot];
if (i == j) {
nslot_update = 1;
cpumask_clear(dp);
if (dattr)
*(dattr + nslot) = SD_ATTR_INIT;
}
cpumask_or(dp, dp, csa[j]->effective_cpus);
cpumask_and(dp, dp, housekeeping_cpumask(HK_TYPE_DOMAIN));
if (dattr)
update_domain_attr_tree(dattr + nslot, csa[j]);
}
}
if (nslot_update)
nslot++;
}
BUG_ON(nslot != ndoms);
done:
kfree(csa);