diff -Naurp linux-2.6.12-rc2.orig/include/linux/init.h linux-2.6.12-rc2/include/linux/init.h --- linux-2.6.12-rc2.orig/include/linux/init.h 2005-04-04 22:07:52.000000000 +0530 +++ linux-2.6.12-rc2/include/linux/init.h 2005-05-01 22:07:56.000000000 +0530 @@ -217,7 +217,7 @@ void __init parse_early_param(void); #define __initdata_or_module __initdata #endif /*CONFIG_MODULES*/ -#ifdef CONFIG_HOTPLUG +#if defined(CONFIG_HOTPLUG) || defined(CONFIG_CPUSETS) #define __devinit #define __devinitdata #define __devexit diff -Naurp linux-2.6.12-rc2.orig/include/linux/sched.h linux-2.6.12-rc2/include/linux/sched.h --- linux-2.6.12-rc2.orig/include/linux/sched.h 2005-04-28 18:24:11.000000000 +0530 +++ linux-2.6.12-rc2/include/linux/sched.h 2005-05-01 22:07:35.000000000 +0530 @@ -155,6 +155,7 @@ typedef struct task_struct task_t; extern void sched_init(void); extern void sched_init_smp(void); extern void init_idle(task_t *idle, int cpu); +extern void rebuild_sched_domains(cpumask_t span1, cpumask_t span2); extern cpumask_t nohz_cpu_mask; diff -Naurp linux-2.6.12-rc2.orig/kernel/sched.c linux-2.6.12-rc2/kernel/sched.c --- linux-2.6.12-rc2.orig/kernel/sched.c 2005-04-28 18:24:11.000000000 +0530 +++ linux-2.6.12-rc2/kernel/sched.c 2005-05-01 22:06:55.000000000 +0530 @@ -4526,7 +4526,7 @@ int __init migration_init(void) #endif #ifdef CONFIG_SMP -#define SCHED_DOMAIN_DEBUG +#undef SCHED_DOMAIN_DEBUG #ifdef SCHED_DOMAIN_DEBUG static void sched_domain_debug(struct sched_domain *sd, int cpu) { @@ -4934,40 +4934,50 @@ static void check_sibling_maps(void) } #endif -/* - * Set up scheduler domains and groups. Callers must hold the hotplug lock. - */ -static void __devinit arch_init_sched_domains(void) +static inline void detach_domains(cpumask_t cpu_map) { int i; - cpumask_t cpu_default_map; -#if defined(CONFIG_SCHED_SMT) && defined(CONFIG_NUMA) - check_sibling_maps(); + for_each_cpu_mask(i, cpu_map) + cpu_attach_domain(NULL, i); + synchronize_kernel(); +} + +static inline void attach_domains(cpumask_t cpu_map) +{ + int i; + + /* Attach the domains */ + for_each_cpu_mask(i, cpu_map) { + struct sched_domain *sd; +#ifdef CONFIG_SCHED_SMT + sd = &per_cpu(cpu_domains, i); +#else + sd = &per_cpu(phys_domains, i); #endif - /* - * Setup mask for cpus without special case scheduling requirements. - * For now this just excludes isolated cpus, but could be used to - * exclude other special cases in the future. - */ - cpus_complement(cpu_default_map, cpu_isolated_map); - cpus_and(cpu_default_map, cpu_default_map, cpu_online_map); + cpu_attach_domain(sd, i); + } +} + +static void build_sched_domains(cpumask_t cpu_map) +{ + int i; /* - * Set up domains. Isolated domains just stay on the NULL domain. + * Set up domains as specified by the cpu_map. */ - for_each_cpu_mask(i, cpu_default_map) { + for_each_cpu_mask(i, cpu_map) { int group; struct sched_domain *sd = NULL, *p; cpumask_t nodemask = node_to_cpumask(cpu_to_node(i)); - cpus_and(nodemask, nodemask, cpu_default_map); + cpus_and(nodemask, nodemask, cpu_map); #ifdef CONFIG_NUMA sd = &per_cpu(node_domains, i); group = cpu_to_node_group(i); *sd = SD_NODE_INIT; - sd->span = cpu_default_map; + sd->span = cpu_map; sd->groups = &sched_group_nodes[group]; #endif @@ -4985,7 +4995,7 @@ static void __devinit arch_init_sched_do group = cpu_to_cpu_group(i); *sd = SD_SIBLING_INIT; sd->span = cpu_sibling_map[i]; - cpus_and(sd->span, sd->span, cpu_default_map); + cpus_and(sd->span, sd->span, cpu_map); sd->parent = p; sd->groups = &sched_group_cpus[group]; #endif @@ -4995,7 +5005,7 @@ static void __devinit arch_init_sched_do /* Set up CPU (sibling) groups */ for_each_online_cpu(i) { cpumask_t this_sibling_map = cpu_sibling_map[i]; - cpus_and(this_sibling_map, this_sibling_map, cpu_default_map); + cpus_and(this_sibling_map, this_sibling_map, cpu_map); if (i != first_cpu(this_sibling_map)) continue; @@ -5008,7 +5018,7 @@ static void __devinit arch_init_sched_do for (i = 0; i < MAX_NUMNODES; i++) { cpumask_t nodemask = node_to_cpumask(i); - cpus_and(nodemask, nodemask, cpu_default_map); + cpus_and(nodemask, nodemask, cpu_map); if (cpus_empty(nodemask)) continue; @@ -5018,12 +5028,12 @@ static void __devinit arch_init_sched_do #ifdef CONFIG_NUMA /* Set up node groups */ - init_sched_build_groups(sched_group_nodes, cpu_default_map, + init_sched_build_groups(sched_group_nodes, cpu_map, &cpu_to_node_group); #endif /* Calculate CPU power for physical packages and nodes */ - for_each_cpu_mask(i, cpu_default_map) { + for_each_cpu_mask(i, cpu_map) { int power; struct sched_domain *sd; #ifdef CONFIG_SCHED_SMT @@ -5045,17 +5055,46 @@ static void __devinit arch_init_sched_do } #endif } +} - /* Attach the domains */ - for_each_online_cpu(i) { - struct sched_domain *sd; -#ifdef CONFIG_SCHED_SMT - sd = &per_cpu(cpu_domains, i); -#else - sd = &per_cpu(phys_domains, i); +void rebuild_sched_domains(cpumask_t span1, cpumask_t span2) +{ + cpumask_t change_map; + + cpus_or(change_map, span1, span2); + + preempt_disable(); + detach_domains(change_map); + + if (!cpus_empty(span1)) + build_sched_domains(span1); + if (!cpus_empty(span2)) + build_sched_domains(span2); + + attach_domains(change_map); + preempt_enable(); +} + +/* + * Set up scheduler domains and groups. Callers must hold the hotplug lock. + */ +static void __devinit arch_init_sched_domains(void) +{ + cpumask_t cpu_default_map; + +#if defined(CONFIG_SCHED_SMT) && defined(CONFIG_NUMA) + check_sibling_maps(); #endif - cpu_attach_domain(sd, i); - } + /* + * Setup mask for cpus without special case scheduling requirements. + * For now this just excludes isolated cpus, but could be used to + * exclude other special cases in the future. + */ + cpus_complement(cpu_default_map, cpu_isolated_map); + cpus_and(cpu_default_map, cpu_default_map, cpu_online_map); + + build_sched_domains(cpu_default_map); + attach_domains(cpu_default_map); } #ifdef CONFIG_HOTPLUG_CPU @@ -5082,9 +5121,7 @@ static int update_sched_domains(struct n switch (action) { case CPU_UP_PREPARE: case CPU_DOWN_PREPARE: - for_each_online_cpu(i) - cpu_attach_domain(NULL, i); - synchronize_kernel(); + detach_domains(cpu_online_map); arch_destroy_sched_domains(); return NOTIFY_OK;