Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sched: arch_reinit_sched_domains() must destroy domains to force rebuild

What I realized recently is that calling rebuild_sched_domains() in
arch_reinit_sched_domains() by itself is not enough when cpusets are enabled.
partition_sched_domains() code is trying to avoid unnecessary domain rebuilds
and will not actually rebuild anything if new domain masks match the old ones.

What this means is that doing
echo 1 > /sys/devices/system/cpu/sched_mc_power_savings
on a system with cpusets enabled will not take affect untill something changes
in the cpuset setup (ie new sets created or deleted).

This patch fixes restore correct behaviour where domains must be rebuilt in
order to enable MC powersaving flags.

Test on quad-core Core2 box with both CONFIG_CPUSETS and !CONFIG_CPUSETS.
Also tested on dual-core Core2 laptop. Lockdep is happy and things are working
as expected.

Signed-off-by: Max Krasnyansky <maxk@qualcomm.com>
Tested-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

authored by

Max Krasnyansky and committed by
Ingo Molnar
dfb512ec cf417141

+14 -7
+1 -1
include/linux/cpuset.h
··· 160 160 161 161 static inline void rebuild_sched_domains(void) 162 162 { 163 - partition_sched_domains(0, NULL, NULL); 163 + partition_sched_domains(1, NULL, NULL); 164 164 } 165 165 166 166 #endif /* !CONFIG_CPUSETS */
+13 -6
kernel/sched.c
··· 7589 7589 * and partition_sched_domains() will fallback to the single partition 7590 7590 * 'fallback_doms', it also forces the domains to be rebuilt. 7591 7591 * 7592 + * If doms_new==NULL it will be replaced with cpu_online_map. 7593 + * ndoms_new==0 is a special case for destroying existing domains. 7594 + * It will not create the default domain. 7595 + * 7592 7596 * Call with hotplug lock held 7593 7597 */ 7594 7598 void partition_sched_domains(int ndoms_new, cpumask_t *doms_new, 7595 7599 struct sched_domain_attr *dattr_new) 7596 7600 { 7597 - int i, j; 7601 + int i, j, n; 7598 7602 7599 7603 mutex_lock(&sched_domains_mutex); 7600 7604 7601 7605 /* always unregister in case we don't destroy any domains */ 7602 7606 unregister_sched_domain_sysctl(); 7603 7607 7604 - if (doms_new == NULL) 7605 - ndoms_new = 0; 7608 + n = doms_new ? ndoms_new : 0; 7606 7609 7607 7610 /* Destroy deleted domains */ 7608 7611 for (i = 0; i < ndoms_cur; i++) { 7609 - for (j = 0; j < ndoms_new; j++) { 7612 + for (j = 0; j < n; j++) { 7610 7613 if (cpus_equal(doms_cur[i], doms_new[j]) 7611 7614 && dattrs_equal(dattr_cur, i, dattr_new, j)) 7612 7615 goto match1; ··· 7622 7619 7623 7620 if (doms_new == NULL) { 7624 7621 ndoms_cur = 0; 7625 - ndoms_new = 1; 7626 7622 doms_new = &fallback_doms; 7627 7623 cpus_andnot(doms_new[0], cpu_online_map, cpu_isolated_map); 7628 7624 dattr_new = NULL; ··· 7658 7656 int arch_reinit_sched_domains(void) 7659 7657 { 7660 7658 get_online_cpus(); 7659 + 7660 + /* Destroy domains first to force the rebuild */ 7661 + partition_sched_domains(0, NULL, NULL); 7662 + 7661 7663 rebuild_sched_domains(); 7662 7664 put_online_cpus(); 7665 + 7663 7666 return 0; 7664 7667 } 7665 7668 ··· 7748 7741 case CPU_ONLINE_FROZEN: 7749 7742 case CPU_DEAD: 7750 7743 case CPU_DEAD_FROZEN: 7751 - partition_sched_domains(0, NULL, NULL); 7744 + partition_sched_domains(1, NULL, NULL); 7752 7745 return NOTIFY_OK; 7753 7746 7754 7747 default: