@@ -193,6 +193,8 @@ struct cpuset {
*
* 1 - partition root
*
+ * 2 - partition root without load balancing (isolated)
+ *
* -1 - invalid partition root
* None of the cpus in cpus_allowed can be put into the parent's
* subparts_cpus. In this case, the cpuset is not a real partition
@@ -202,6 +204,7 @@ struct cpuset {
*/
#define PRS_DISABLED 0
#define PRS_ENABLED 1
+#define PRS_ISOLATED 2
#define PRS_ERROR -1
/*
@@ -1298,17 +1301,22 @@ static int update_parent_subparts_cpumask(struct cpuset *cpuset, int cmd,
if (cmd == partcmd_update) {
/*
- * Check for possible transition between PRS_ENABLED
- * and PRS_ERROR.
+ * Check for possible transition between PRS_ERROR and
+ * PRS_ENABLED/PRS_ISOLATED.
*/
switch (cpuset->partition_root_state) {
case PRS_ENABLED:
+ case PRS_ISOLATED:
if (part_error)
new_prs = PRS_ERROR;
break;
case PRS_ERROR:
- if (!part_error)
+ if (part_error)
+ break;
+ if (is_sched_load_balance(cpuset))
new_prs = PRS_ENABLED;
+ else
+ new_prs = PRS_ISOLATED;
break;
}
}
@@ -1443,6 +1451,7 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp)
break;
case PRS_ENABLED:
+ case PRS_ISOLATED:
if (update_parent_subparts_cpumask(cp, partcmd_update, NULL, tmp))
update_tasks_cpumask(parent);
/*
@@ -1468,7 +1477,7 @@ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp)
spin_lock_irq(&callback_lock);
- if (cp->nr_subparts_cpus && (new_prs != PRS_ENABLED)) {
+ if (cp->nr_subparts_cpus && (new_prs <= 0)) {
/*
* Put all active subparts_cpus back to effective_cpus.
*/
@@ -2007,6 +2016,7 @@ static int update_prstate(struct cpuset *cs, int new_prs)
int err, old_prs = cs->partition_root_state;
struct cpuset *parent = parent_cs(cs);
struct tmpmasks tmpmask;
+ bool sched_domain_rebuilt = false;
if (old_prs == new_prs)
return 0;
@@ -2041,6 +2051,22 @@ static int update_prstate(struct cpuset *cs, int new_prs)
update_flag(CS_CPU_EXCLUSIVE, cs, 0);
goto out;
}
+
+ if (new_prs == PRS_ISOLATED) {
+ /*
+ * Disable the load balance flag should not return an
+ * error unless the system is running out of memory.
+ */
+ update_flag(CS_SCHED_LOAD_BALANCE, cs, 0);
+ sched_domain_rebuilt = true;
+ }
+ } else if (old_prs && new_prs) {
+ /*
+ * A change in load balance state only, no change in cpumasks.
+ */
+ update_flag(CS_SCHED_LOAD_BALANCE, cs, (new_prs != PRS_ISOLATED));
+ err = 0;
+ goto out; /* Sched domain is rebuilt in update_flag() */
} else {
/*
* Switch back to member is always allowed even if it
@@ -2073,6 +2099,12 @@ static int update_prstate(struct cpuset *cs, int new_prs)
/* Turning off CS_CPU_EXCLUSIVE will not return error */
update_flag(CS_CPU_EXCLUSIVE, cs, 0);
+
+ if (!is_sched_load_balance(cs)) {
+ /* Make sure load balance is on */
+ update_flag(CS_SCHED_LOAD_BALANCE, cs, 1);
+ sched_domain_rebuilt = true;
+ }
}
/*
@@ -2085,7 +2117,8 @@ static int update_prstate(struct cpuset *cs, int new_prs)
if (parent->child_ecpus_count)
update_sibling_cpumasks(parent, cs, &tmpmask);
- rebuild_sched_domains_locked();
+ if (!sched_domain_rebuilt)
+ rebuild_sched_domains_locked();
out:
if (!err) {
spin_lock_irq(&callback_lock);
@@ -2588,6 +2621,9 @@ static int sched_partition_show(struct seq_file *seq, void *v)
case PRS_ENABLED:
seq_puts(seq, "root\n");
break;
+ case PRS_ISOLATED:
+ seq_puts(seq, "isolated\n");
+ break;
case PRS_DISABLED:
seq_puts(seq, "member\n");
break;
@@ -2618,6 +2654,8 @@ static ssize_t sched_partition_write(struct kernfs_open_file *of, char *buf,
val = PRS_ENABLED;
else if (!strcmp(buf, "member"))
val = PRS_DISABLED;
+ else if (!strcmp(buf, "isolated"))
+ val = PRS_ISOLATED;
else
return -EINVAL;