@ -595,10 +595,62 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
return 0 ;
}
/*
* For a given cpuset cur , partition the system as follows
* a . All cpus in the parent cpuset ' s cpus_allowed that are not part of any
* exclusive child cpusets
* b . All cpus in the current cpuset ' s cpus_allowed that are not part of any
* exclusive child cpusets
* Build these two partitions by calling partition_sched_domains
*
* Call with cpuset_sem held . May nest a call to the
* lock_cpu_hotplug ( ) / unlock_cpu_hotplug ( ) pair .
*/
static void update_cpu_domains ( struct cpuset * cur )
{
struct cpuset * c , * par = cur - > parent ;
cpumask_t pspan , cspan ;
if ( par = = NULL | | cpus_empty ( cur - > cpus_allowed ) )
return ;
/*
* Get all cpus from parent ' s cpus_allowed not part of exclusive
* children
*/
pspan = par - > cpus_allowed ;
list_for_each_entry ( c , & par - > children , sibling ) {
if ( is_cpu_exclusive ( c ) )
cpus_andnot ( pspan , pspan , c - > cpus_allowed ) ;
}
if ( is_removed ( cur ) | | ! is_cpu_exclusive ( cur ) ) {
cpus_or ( pspan , pspan , cur - > cpus_allowed ) ;
if ( cpus_equal ( pspan , cur - > cpus_allowed ) )
return ;
cspan = CPU_MASK_NONE ;
} else {
if ( cpus_empty ( pspan ) )
return ;
cspan = cur - > cpus_allowed ;
/*
* Get all cpus from current cpuset ' s cpus_allowed not part
* of exclusive children
*/
list_for_each_entry ( c , & cur - > children , sibling ) {
if ( is_cpu_exclusive ( c ) )
cpus_andnot ( cspan , cspan , c - > cpus_allowed ) ;
}
}
lock_cpu_hotplug ( ) ;
partition_sched_domains ( & pspan , & cspan ) ;
unlock_cpu_hotplug ( ) ;
}
static int update_cpumask ( struct cpuset * cs , char * buf )
{
struct cpuset trialcs ;
int retval ;
int retval , cpus_unchanged ;
trialcs = * cs ;
retval = cpulist_parse ( buf , trialcs . cpus_allowed ) ;
@ -608,9 +660,13 @@ static int update_cpumask(struct cpuset *cs, char *buf)
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 ;
cpus_unchanged = cpus_equal ( cs - > cpus_allowed , trialcs . cpus_allowed ) ;
cs - > cpus_allowed = trialcs . cpus_allowed ;
if ( is_cpu_exclusive ( cs ) & & ! cpus_unchanged )
update_cpu_domains ( cs ) ;
return 0 ;
}
static int update_nodemask ( struct cpuset * cs , char * buf )
@ -646,7 +702,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
{
int turning_on ;
struct cpuset trialcs ;
int err ;
int err , cpu_exclusive_changed ;
turning_on = ( simple_strtoul ( buf , NULL , 10 ) ! = 0 ) ;
@ -657,13 +713,18 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
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 ;
cpu_exclusive_changed =
( is_cpu_exclusive ( cs ) ! = is_cpu_exclusive ( & trialcs ) ) ;
if ( turning_on )
set_bit ( bit , & cs - > flags ) ;
else
clear_bit ( bit , & cs - > flags ) ;
if ( cpu_exclusive_changed )
update_cpu_domains ( cs ) ;
return 0 ;
}
static int attach_task ( struct cpuset * cs , char * buf )
@ -1309,12 +1370,14 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
up ( & cpuset_sem ) ;
return - EBUSY ;
}
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 ) ;
spin_lock ( & cs - > dentry - > d_lock ) ;
d = dget ( cs - > dentry ) ;
cs - > dentry = NULL ;
spin_unlock ( & d - > d_lock ) ;