Commit 41d701dd authored by Guopeng Zhang's avatar Guopeng Zhang Committed by Tejun Heo
Browse files

cgroup/cpuset: record DL BW alloc CPU for attach rollback



cpuset_can_attach() allocates DL bandwidth only when migrating
deadline tasks to a disjoint CPU mask, but cpuset_cancel_attach()
rolls back based only on nr_migrate_dl_tasks. This makes the DL
bandwidth alloc/free paths asymmetric: rollback can call dl_bw_free()
even when no dl_bw_alloc() was done.

Rollback also needs to undo the reservation against the same CPU/root
domain that was charged. Record the CPU used by dl_bw_alloc() and use
that state in cpuset_cancel_attach(). If no allocation happened,
dl_bw_cpu stays at -1 and rollback skips dl_bw_free(). If allocation
did happen, bandwidth is returned to the same CPU/root domain.

Successful attach paths are unchanged. This only fixes failed attach
rollback accounting.

Fixes: 2ef269ef ("cgroup/cpuset: Free DL BW in case can_attach() fails")
Signed-off-by: default avatarGuopeng Zhang <zhangguopeng@kylinos.cn>
Reviewed-by: default avatarWaiman Long <longman@redhat.com>
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
parent c802f460
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -168,6 +168,11 @@ struct cpuset {
	int nr_deadline_tasks;
	int nr_migrate_dl_tasks;
	u64 sum_migrate_dl_bw;
	/*
	 * CPU used for temporary DL bandwidth allocation during attach;
	 * -1 if no DL bandwidth was allocated in the current attach.
	 */
	int dl_bw_cpu;

	/* Invalid partition error code, not lock protected */
	enum prs_errcode prs_err;
+9 −4
Original line number Diff line number Diff line
@@ -288,6 +288,7 @@ struct cpuset top_cpuset = {
	.flags = BIT(CS_CPU_EXCLUSIVE) |
		 BIT(CS_MEM_EXCLUSIVE) | BIT(CS_SCHED_LOAD_BALANCE),
	.partition_root_state = PRS_ROOT,
	.dl_bw_cpu = -1,
};

/**
@@ -579,6 +580,8 @@ static struct cpuset *dup_or_alloc_cpuset(struct cpuset *cs)
	if (!trial)
		return NULL;

	trial->dl_bw_cpu = -1;

	/* Setup cpumask pointer array */
	cpumask_var_t *pmask[4] = {
		&trial->cpus_allowed,
@@ -2980,6 +2983,7 @@ static void reset_migrate_dl_data(struct cpuset *cs)
{
	cs->nr_migrate_dl_tasks = 0;
	cs->sum_migrate_dl_bw = 0;
	cs->dl_bw_cpu = -1;
}

/* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
@@ -3056,6 +3060,8 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
			reset_migrate_dl_data(cs);
			goto out_unlock;
		}

		cs->dl_bw_cpu = cpu;
	}

out_success:
@@ -3080,12 +3086,11 @@ static void cpuset_cancel_attach(struct cgroup_taskset *tset)
	mutex_lock(&cpuset_mutex);
	dec_attach_in_progress_locked(cs);

	if (cs->nr_migrate_dl_tasks) {
		int cpu = cpumask_any(cs->effective_cpus);
	if (cs->dl_bw_cpu >= 0)
		dl_bw_free(cs->dl_bw_cpu, cs->sum_migrate_dl_bw);

		dl_bw_free(cpu, cs->sum_migrate_dl_bw);
	if (cs->nr_migrate_dl_tasks)
		reset_migrate_dl_data(cs);
	}

	mutex_unlock(&cpuset_mutex);
}