Commit 7cc17205 authored by Chen Ridong's avatar Chen Ridong Committed by Tejun Heo
Browse files

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: default avatarChen Ridong <chenridong@huawei.com>
Reviewed-by: default avatarWaiman Long <longman@redhat.com>
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
parent 6e1d31ce
Loading
Loading
Loading
Loading
+3 −7
Original line number Diff line number Diff line
@@ -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; };

+1 −1
Original line number Diff line number Diff line
@@ -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;
+24 −121
Original line number Diff line number Diff line
@@ -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,45 +861,19 @@ 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,
		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;
	}
		goto done;
	}

	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);