diff -Naurp linux-2.6.12-rc2.orig/kernel/cpuset.c linux-2.6.12-rc2/kernel/cpuset.c --- linux-2.6.12-rc2.orig/kernel/cpuset.c 2005-04-28 18:24:11.000000000 +0530 +++ linux-2.6.12-rc2/kernel/cpuset.c 2005-05-01 22:15:06.000000000 +0530 @@ -602,12 +602,48 @@ static int validate_change(const struct return 0; } +static void update_cpu_domains(struct cpuset *cur) +{ + struct cpuset *c, *par = cur->parent; + cpumask_t span1, span2; + + if (par == NULL || cpus_empty(cur->cpus_allowed)) + return; + + /* Get all non-exclusive cpus from parent domain */ + span1 = par->cpus_allowed; + list_for_each_entry(c, &par->children, sibling) { + if (is_cpu_exclusive(c)) + cpus_andnot(span1, span1, c->cpus_allowed); + } + if (is_removed(cur) || !is_cpu_exclusive(cur)) { + cpus_or(span1, span1, cur->cpus_allowed); + if (cpus_equal(span1, cur->cpus_allowed)) + return; + span2 = CPU_MASK_NONE; + } + else { + if (cpus_empty(span1)) + return; + span2 = cur->cpus_allowed; + /* If current cpuset has exclusive children, exclude from domain */ + list_for_each_entry(c, &cur->children, sibling) { + if (is_cpu_exclusive(c)) + cpus_andnot(span2, span2, c->cpus_allowed); + } + } + + lock_cpu_hotplug(); + rebuild_sched_domains(span1, span2); + unlock_cpu_hotplug(); +} + static int update_cpumask(struct cpuset *cs, char *buf) { - struct cpuset trialcs; + struct cpuset trialcs, oldcs; int retval; - trialcs = *cs; + trialcs = oldcs = *cs; retval = cpulist_parse(buf, trialcs.cpus_allowed); if (retval < 0) return retval; @@ -615,9 +651,13 @@ static int update_cpumask(struct cpuset if (cpus_empty(trialcs.cpus_allowed)) return -ENOSPC; retval = validate_change(cs, &trialcs); - if (retval == 0) - cs->cpus_allowed = trialcs.cpus_allowed; - return retval; + if (retval < 0) + return retval; + cs->cpus_allowed = trialcs.cpus_allowed; + if (is_cpu_exclusive(cs) && + (!cpus_equal(cs->cpus_allowed, oldcs.cpus_allowed))) + update_cpu_domains(cs); + return 0; } static int update_nodemask(struct cpuset *cs, char *buf) @@ -652,25 +692,28 @@ static int update_nodemask(struct cpuset static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf) { int turning_on; - struct cpuset trialcs; + struct cpuset trialcs, oldcs; int err; turning_on = (simple_strtoul(buf, NULL, 10) != 0); - trialcs = *cs; + trialcs = oldcs = *cs; if (turning_on) set_bit(bit, &trialcs.flags); else clear_bit(bit, &trialcs.flags); err = validate_change(cs, &trialcs); - if (err == 0) { - if (turning_on) - set_bit(bit, &cs->flags); - else - clear_bit(bit, &cs->flags); - } - return err; + if (err < 0) + return err; + if (turning_on) + set_bit(bit, &cs->flags); + else + clear_bit(bit, &cs->flags); + + if (is_cpu_exclusive(cs) != is_cpu_exclusive(&oldcs)) + update_cpu_domains(cs); + return 0; } static int attach_task(struct cpuset *cs, char *buf) @@ -1319,6 +1362,8 @@ static int cpuset_rmdir(struct inode *un spin_lock(&cs->dentry->d_lock); parent = cs->parent; set_bit(CS_REMOVED, &cs->flags); + if (is_cpu_exclusive(cs)) + update_cpu_domains(cs); list_del(&cs->sibling); /* delete my sibling from parent->children */ if (list_empty(&parent->children)) check_for_release(parent);