Skip to content

Commit 4a74e41

Browse files
Waiman-Longhtejun
authored andcommitted
cgroup/cpuset: Check partition conflict with housekeeping setup
A user can pre-configure certain CPUs in an isolated state at boot time with the "isolcpus" kernel boot command line option. Those CPUs will not be in the housekeeping_cpumask(HK_TYPE_DOMAIN) and so will not be in any sched domains. This may conflict with the partition setup at runtime. Those boot time isolated CPUs should only be used in an isolated partition. This patch adds the necessary check and disallows partition setup if the check fails. Signed-off-by: Waiman Long <longman@redhat.com> Signed-off-by: Tejun Heo <tj@kernel.org>
1 parent 181c8e0 commit 4a74e41

File tree

1 file changed

+31
-0
lines changed

1 file changed

+31
-0
lines changed

kernel/cgroup/cpuset.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ enum prs_errcode {
7575
PERR_NOCPUS,
7676
PERR_HOTPLUG,
7777
PERR_CPUSEMPTY,
78+
PERR_HKEEPING,
7879
};
7980

8081
static const char * const perr_strings[] = {
@@ -85,6 +86,7 @@ static const char * const perr_strings[] = {
8586
[PERR_NOCPUS] = "Parent unable to distribute cpu downstream",
8687
[PERR_HOTPLUG] = "No cpu available due to hotplug",
8788
[PERR_CPUSEMPTY] = "cpuset.cpus is empty",
89+
[PERR_HKEEPING] = "partition config conflicts with housekeeping setup",
8890
};
8991

9092
struct cpuset {
@@ -1646,6 +1648,26 @@ static void remote_partition_check(struct cpuset *cs, struct cpumask *newmask,
16461648
rebuild_sched_domains_locked();
16471649
}
16481650

1651+
/*
1652+
* prstate_housekeeping_conflict - check for partition & housekeeping conflicts
1653+
* @prstate: partition root state to be checked
1654+
* @new_cpus: cpu mask
1655+
* Return: true if there is conflict, false otherwise
1656+
*
1657+
* CPUs outside of housekeeping_cpumask(HK_TYPE_DOMAIN) can only be used in
1658+
* an isolated partition.
1659+
*/
1660+
static bool prstate_housekeeping_conflict(int prstate, struct cpumask *new_cpus)
1661+
{
1662+
const struct cpumask *hk_domain = housekeeping_cpumask(HK_TYPE_DOMAIN);
1663+
bool all_in_hk = cpumask_subset(new_cpus, hk_domain);
1664+
1665+
if (!all_in_hk && (prstate != PRS_ISOLATED))
1666+
return true;
1667+
1668+
return false;
1669+
}
1670+
16491671
/**
16501672
* update_parent_effective_cpumask - update effective_cpus mask of parent cpuset
16511673
* @cs: The cpuset that requests change in partition root state
@@ -1748,6 +1770,9 @@ static int update_parent_effective_cpumask(struct cpuset *cs, int cmd,
17481770
!cpumask_intersects(xcpus, parent->effective_xcpus))
17491771
return PERR_INVCPUS;
17501772

1773+
if (prstate_housekeeping_conflict(new_prs, xcpus))
1774+
return PERR_HKEEPING;
1775+
17511776
/*
17521777
* A parent can be left with no CPU as long as there is no
17531778
* task directly associated with the parent partition.
@@ -2335,6 +2360,9 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs,
23352360
if (cpumask_empty(trialcs->effective_xcpus)) {
23362361
invalidate = true;
23372362
cs->prs_err = PERR_INVCPUS;
2363+
} else if (prstate_housekeeping_conflict(old_prs, trialcs->effective_xcpus)) {
2364+
invalidate = true;
2365+
cs->prs_err = PERR_HKEEPING;
23382366
} else if (tasks_nocpu_error(parent, cs, trialcs->effective_xcpus)) {
23392367
invalidate = true;
23402368
cs->prs_err = PERR_NOCPUS;
@@ -2469,6 +2497,9 @@ static int update_exclusive_cpumask(struct cpuset *cs, struct cpuset *trialcs,
24692497
if (cpumask_empty(trialcs->effective_xcpus)) {
24702498
invalidate = true;
24712499
cs->prs_err = PERR_INVCPUS;
2500+
} else if (prstate_housekeeping_conflict(old_prs, trialcs->effective_xcpus)) {
2501+
invalidate = true;
2502+
cs->prs_err = PERR_HKEEPING;
24722503
} else if (tasks_nocpu_error(parent, cs, trialcs->effective_xcpus)) {
24732504
invalidate = true;
24742505
cs->prs_err = PERR_NOCPUS;

0 commit comments

Comments
 (0)