@ -1757,11 +1757,85 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
}
EXPORT_SYMBOL_GPL ( cgroup_path ) ;
/*
* Control Group taskset
*/
struct task_and_cgroup {
struct task_struct * task ;
struct cgroup * cgrp ;
} ;
struct cgroup_taskset {
struct task_and_cgroup single ;
struct flex_array * tc_array ;
int tc_array_len ;
int idx ;
struct cgroup * cur_cgrp ;
} ;
/**
* cgroup_taskset_first - reset taskset and return the first task
* @ tset : taskset of interest
*
* @ tset iteration is initialized and the first task is returned .
*/
struct task_struct * cgroup_taskset_first ( struct cgroup_taskset * tset )
{
if ( tset - > tc_array ) {
tset - > idx = 0 ;
return cgroup_taskset_next ( tset ) ;
} else {
tset - > cur_cgrp = tset - > single . cgrp ;
return tset - > single . task ;
}
}
EXPORT_SYMBOL_GPL ( cgroup_taskset_first ) ;
/**
* cgroup_taskset_next - iterate to the next task in taskset
* @ tset : taskset of interest
*
* Return the next task in @ tset . Iteration must have been initialized
* with cgroup_taskset_first ( ) .
*/
struct task_struct * cgroup_taskset_next ( struct cgroup_taskset * tset )
{
struct task_and_cgroup * tc ;
if ( ! tset - > tc_array | | tset - > idx > = tset - > tc_array_len )
return NULL ;
tc = flex_array_get ( tset - > tc_array , tset - > idx + + ) ;
tset - > cur_cgrp = tc - > cgrp ;
return tc - > task ;
}
EXPORT_SYMBOL_GPL ( cgroup_taskset_next ) ;
/**
* cgroup_taskset_cur_cgroup - return the matching cgroup for the current task
* @ tset : taskset of interest
*
* Return the cgroup for the current ( last returned ) task of @ tset . This
* function must be preceded by either cgroup_taskset_first ( ) or
* cgroup_taskset_next ( ) .
*/
struct cgroup * cgroup_taskset_cur_cgroup ( struct cgroup_taskset * tset )
{
return tset - > cur_cgrp ;
}
EXPORT_SYMBOL_GPL ( cgroup_taskset_cur_cgroup ) ;
/**
* cgroup_taskset_size - return the number of tasks in taskset
* @ tset : taskset of interest
*/
int cgroup_taskset_size ( struct cgroup_taskset * tset )
{
return tset - > tc_array ? tset - > tc_array_len : 1 ;
}
EXPORT_SYMBOL_GPL ( cgroup_taskset_size ) ;
/*
* cgroup_task_migrate - move a task from one cgroup to another .
*
@ -1842,6 +1916,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
struct cgroup_subsys * ss , * failed_ss = NULL ;
struct cgroup * oldcgrp ;
struct cgroupfs_root * root = cgrp - > root ;
struct cgroup_taskset tset = { } ;
/* @tsk either already exited or can't exit until the end */
if ( tsk - > flags & PF_EXITING )
@ -1852,9 +1927,12 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
if ( cgrp = = oldcgrp )
return 0 ;
tset . single . task = tsk ;
tset . single . cgrp = oldcgrp ;
for_each_subsys ( root , ss ) {
if ( ss - > can_attach ) {
retval = ss - > can_attach ( ss , cgrp , tsk ) ;
retval = ss - > can_attach ( ss , cgrp , & tset ) ;
if ( retval ) {
/*
* Remember on which subsystem the can_attach ( )
@ -1885,7 +1963,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
if ( ss - > attach_task )
ss - > attach_task ( cgrp , tsk ) ;
if ( ss - > attach )
ss - > attach ( ss , cgrp , oldcgrp , tsk ) ;
ss - > attach ( ss , cgrp , & tset ) ;
}
synchronize_rcu ( ) ;
@ -1907,7 +1985,7 @@ out:
*/
break ;
if ( ss - > cancel_attach )
ss - > cancel_attach ( ss , cgrp , tsk ) ;
ss - > cancel_attach ( ss , cgrp , & tset ) ;
}
}
return retval ;
@ -2023,6 +2101,7 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
struct task_struct * tsk ;
struct task_and_cgroup * tc ;
struct flex_array * group ;
struct cgroup_taskset tset = { } ;
/*
* we need to make sure we have css_sets for all the tasks we ' re
* going to move - before - we actually start moving them , so that in
@ -2089,6 +2168,8 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
} while_each_thread ( leader , tsk ) ;
/* remember the number of threads in the array for later. */
group_size = i ;
tset . tc_array = group ;
tset . tc_array_len = group_size ;
read_unlock ( & tasklist_lock ) ;
/* methods shouldn't be called if no task is actually migrating */
@ -2101,7 +2182,7 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
*/
for_each_subsys ( root , ss ) {
if ( ss - > can_attach ) {
retval = ss - > can_attach ( ss , cgrp , leader ) ;
retval = ss - > can_attach ( ss , cgrp , & tset ) ;
if ( retval ) {
failed_ss = ss ;
goto out_cancel_attach ;
@ -2183,10 +2264,8 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
* being moved , this call will need to be reworked to communicate that .
*/
for_each_subsys ( root , ss ) {
if ( ss - > attach ) {
tc = flex_array_get ( group , 0 ) ;
ss - > attach ( ss , cgrp , tc - > cgrp , tc - > task ) ;
}
if ( ss - > attach )
ss - > attach ( ss , cgrp , & tset ) ;
}
/*
@ -2208,11 +2287,11 @@ out_cancel_attach:
for_each_subsys ( root , ss ) {
if ( ss = = failed_ss ) {
if ( cancel_failed_ss & & ss - > cancel_attach )
ss - > cancel_attach ( ss , cgrp , leader ) ;
ss - > cancel_attach ( ss , cgrp , & tset ) ;
break ;
}
if ( ss - > cancel_attach )
ss - > cancel_attach ( ss , cgrp , leader ) ;
ss - > cancel_attach ( ss , cgrp , & tset ) ;
}
}
out_put_tasks :