*
* 0 - member (not a partition root)
* 1 - partition root
+ * 2 - partition root without load balancing (isolated)
* -1 - invalid partition root
+ * -2 - invalid isolated partition root
*/
#define PRS_MEMBER 0
#define PRS_ROOT 1
+#define PRS_ISOLATED 2
#define PRS_INVALID_ROOT -1
+#define PRS_INVALID_ISOLATED -2
static inline bool is_prs_invalid(int prs_state)
{
*/
static inline void make_partition_invalid(struct cpuset *cs)
{
- cs->partition_root_state = PRS_INVALID_ROOT;
+ if (is_partition_valid(cs))
+ cs->partition_root_state = -cs->partition_root_state;
}
/*
if (cmd == partcmd_update) {
/*
- * Check for possible transition between PRS_ROOT
- * and PRS_INVALID_ROOT.
+ * Check for possible transition between valid and invalid
+ * partition root.
*/
switch (cs->partition_root_state) {
case PRS_ROOT:
+ case PRS_ISOLATED:
if (part_error)
- new_prs = PRS_INVALID_ROOT;
+ new_prs = -old_prs;
break;
case PRS_INVALID_ROOT:
+ case PRS_INVALID_ISOLATED:
if (!part_error)
- new_prs = PRS_ROOT;
+ new_prs = -old_prs;
break;
}
}
/*
* Transitioning between invalid to valid or vice versa may require
- * changing CS_CPU_EXCLUSIVE.
+ * changing CS_CPU_EXCLUSIVE and CS_SCHED_LOAD_BALANCE.
*/
if (old_prs != new_prs) {
if (is_prs_invalid(old_prs) && !is_cpu_exclusive(cs) &&
if (adding || deleting)
update_tasks_cpumask(parent);
+ /*
+ * Set or clear CS_SCHED_LOAD_BALANCE when partcmd_update, if necessary.
+ * rebuild_sched_domains_locked() may be called.
+ */
+ if (old_prs != new_prs) {
+ if (old_prs == PRS_ISOLATED)
+ update_flag(CS_SCHED_LOAD_BALANCE, cs, 1);
+ else if (new_prs == PRS_ISOLATED)
+ update_flag(CS_SCHED_LOAD_BALANCE, cs, 0);
+ }
notify_partition_change(cs, old_prs);
-
return 0;
}
if ((cp != cs) && old_prs) {
switch (parent->partition_root_state) {
case PRS_ROOT:
+ case PRS_ISOLATED:
update_parent = true;
break;
* invalid, child partition roots become
* invalid too.
*/
- new_prs = PRS_INVALID_ROOT;
+ if (is_partition_valid(cp))
+ new_prs = -cp->partition_root_state;
break;
}
}
static int update_prstate(struct cpuset *cs, int new_prs)
{
int err = 0, old_prs = cs->partition_root_state;
+ bool sched_domain_rebuilt = false;
struct cpuset *parent = parent_cs(cs);
struct tmpmasks tmpmask;
* For a previously invalid partition root, leave it at being
* invalid if new_prs is not "member".
*/
- if (new_prs && is_prs_invalid(old_prs))
+ if (new_prs && is_prs_invalid(old_prs)) {
+ cs->partition_root_state = -new_prs;
return 0;
+ }
if (alloc_cpumasks(NULL, &tmpmask))
return -ENOMEM;
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));
+ sched_domain_rebuilt = true;
+ goto out; /* Sched domain is rebuilt in update_flag() */
} else {
/*
* Switching back to member is always allowed even if it
/* 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;
+ }
}
update_tasks_cpumask(parent);
if (parent->child_ecpus_count)
update_sibling_cpumasks(parent, cs, &tmpmask);
- rebuild_sched_domains_locked();
+ if (!sched_domain_rebuilt)
+ rebuild_sched_domains_locked();
out:
/*
* Make partition invalid if an error happen
*/
if (err)
- new_prs = PRS_INVALID_ROOT;
+ new_prs = -new_prs;
spin_lock_irq(&callback_lock);
cs->partition_root_state = new_prs;
spin_unlock_irq(&callback_lock);
case PRS_ROOT:
seq_puts(seq, "root\n");
break;
+ case PRS_ISOLATED:
+ seq_puts(seq, "isolated\n");
+ break;
case PRS_MEMBER:
seq_puts(seq, "member\n");
break;
case PRS_INVALID_ROOT:
seq_puts(seq, "root invalid\n");
break;
+ case PRS_INVALID_ISOLATED:
+ seq_puts(seq, "isolated invalid\n");
+ break;
}
return 0;
}
val = PRS_ROOT;
else if (!strcmp(buf, "member"))
val = PRS_MEMBER;
+ else if (!strcmp(buf, "isolated"))
+ val = PRS_ISOLATED;
else
return -EINVAL;