@@ -1757,11 +1757,85 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
17571757}
17581758EXPORT_SYMBOL_GPL (cgroup_path );
17591759
1760+ /*
1761+ * Control Group taskset
1762+ */
17601763struct task_and_cgroup {
17611764 struct task_struct * task ;
17621765 struct cgroup * cgrp ;
17631766};
17641767
1768+ struct cgroup_taskset {
1769+ struct task_and_cgroup single ;
1770+ struct flex_array * tc_array ;
1771+ int tc_array_len ;
1772+ int idx ;
1773+ struct cgroup * cur_cgrp ;
1774+ };
1775+
1776+ /**
1777+ * cgroup_taskset_first - reset taskset and return the first task
1778+ * @tset: taskset of interest
1779+ *
1780+ * @tset iteration is initialized and the first task is returned.
1781+ */
1782+ struct task_struct * cgroup_taskset_first (struct cgroup_taskset * tset )
1783+ {
1784+ if (tset -> tc_array ) {
1785+ tset -> idx = 0 ;
1786+ return cgroup_taskset_next (tset );
1787+ } else {
1788+ tset -> cur_cgrp = tset -> single .cgrp ;
1789+ return tset -> single .task ;
1790+ }
1791+ }
1792+ EXPORT_SYMBOL_GPL (cgroup_taskset_first );
1793+
1794+ /**
1795+ * cgroup_taskset_next - iterate to the next task in taskset
1796+ * @tset: taskset of interest
1797+ *
1798+ * Return the next task in @tset. Iteration must have been initialized
1799+ * with cgroup_taskset_first().
1800+ */
1801+ struct task_struct * cgroup_taskset_next (struct cgroup_taskset * tset )
1802+ {
1803+ struct task_and_cgroup * tc ;
1804+
1805+ if (!tset -> tc_array || tset -> idx >= tset -> tc_array_len )
1806+ return NULL ;
1807+
1808+ tc = flex_array_get (tset -> tc_array , tset -> idx ++ );
1809+ tset -> cur_cgrp = tc -> cgrp ;
1810+ return tc -> task ;
1811+ }
1812+ EXPORT_SYMBOL_GPL (cgroup_taskset_next );
1813+
1814+ /**
1815+ * cgroup_taskset_cur_cgroup - return the matching cgroup for the current task
1816+ * @tset: taskset of interest
1817+ *
1818+ * Return the cgroup for the current (last returned) task of @tset. This
1819+ * function must be preceded by either cgroup_taskset_first() or
1820+ * cgroup_taskset_next().
1821+ */
1822+ struct cgroup * cgroup_taskset_cur_cgroup (struct cgroup_taskset * tset )
1823+ {
1824+ return tset -> cur_cgrp ;
1825+ }
1826+ EXPORT_SYMBOL_GPL (cgroup_taskset_cur_cgroup );
1827+
1828+ /**
1829+ * cgroup_taskset_size - return the number of tasks in taskset
1830+ * @tset: taskset of interest
1831+ */
1832+ int cgroup_taskset_size (struct cgroup_taskset * tset )
1833+ {
1834+ return tset -> tc_array ? tset -> tc_array_len : 1 ;
1835+ }
1836+ EXPORT_SYMBOL_GPL (cgroup_taskset_size );
1837+
1838+
17651839/*
17661840 * cgroup_task_migrate - move a task from one cgroup to another.
17671841 *
@@ -1842,6 +1916,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
18421916 struct cgroup_subsys * ss , * failed_ss = NULL ;
18431917 struct cgroup * oldcgrp ;
18441918 struct cgroupfs_root * root = cgrp -> root ;
1919+ struct cgroup_taskset tset = { };
18451920
18461921 /* @tsk either already exited or can't exit until the end */
18471922 if (tsk -> flags & PF_EXITING )
@@ -1852,9 +1927,12 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
18521927 if (cgrp == oldcgrp )
18531928 return 0 ;
18541929
1930+ tset .single .task = tsk ;
1931+ tset .single .cgrp = oldcgrp ;
1932+
18551933 for_each_subsys (root , ss ) {
18561934 if (ss -> can_attach ) {
1857- retval = ss -> can_attach (ss , cgrp , tsk );
1935+ retval = ss -> can_attach (ss , cgrp , & tset );
18581936 if (retval ) {
18591937 /*
18601938 * Remember on which subsystem the can_attach()
@@ -1885,7 +1963,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
18851963 if (ss -> attach_task )
18861964 ss -> attach_task (cgrp , tsk );
18871965 if (ss -> attach )
1888- ss -> attach (ss , cgrp , oldcgrp , tsk );
1966+ ss -> attach (ss , cgrp , & tset );
18891967 }
18901968
18911969 synchronize_rcu ();
@@ -1907,7 +1985,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
19071985 */
19081986 break ;
19091987 if (ss -> cancel_attach )
1910- ss -> cancel_attach (ss , cgrp , tsk );
1988+ ss -> cancel_attach (ss , cgrp , & tset );
19111989 }
19121990 }
19131991 return retval ;
@@ -2023,6 +2101,7 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
20232101 struct task_struct * tsk ;
20242102 struct task_and_cgroup * tc ;
20252103 struct flex_array * group ;
2104+ struct cgroup_taskset tset = { };
20262105 /*
20272106 * we need to make sure we have css_sets for all the tasks we're
20282107 * 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)
20892168 } while_each_thread (leader , tsk );
20902169 /* remember the number of threads in the array for later. */
20912170 group_size = i ;
2171+ tset .tc_array = group ;
2172+ tset .tc_array_len = group_size ;
20922173 read_unlock (& tasklist_lock );
20932174
20942175 /* 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)
21012182 */
21022183 for_each_subsys (root , ss ) {
21032184 if (ss -> can_attach ) {
2104- retval = ss -> can_attach (ss , cgrp , leader );
2185+ retval = ss -> can_attach (ss , cgrp , & tset );
21052186 if (retval ) {
21062187 failed_ss = ss ;
21072188 goto out_cancel_attach ;
@@ -2183,10 +2264,8 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
21832264 * being moved, this call will need to be reworked to communicate that.
21842265 */
21852266 for_each_subsys (root , ss ) {
2186- if (ss -> attach ) {
2187- tc = flex_array_get (group , 0 );
2188- ss -> attach (ss , cgrp , tc -> cgrp , tc -> task );
2189- }
2267+ if (ss -> attach )
2268+ ss -> attach (ss , cgrp , & tset );
21902269 }
21912270
21922271 /*
@@ -2208,11 +2287,11 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
22082287 for_each_subsys (root , ss ) {
22092288 if (ss == failed_ss ) {
22102289 if (cancel_failed_ss && ss -> cancel_attach )
2211- ss -> cancel_attach (ss , cgrp , leader );
2290+ ss -> cancel_attach (ss , cgrp , & tset );
22122291 break ;
22132292 }
22142293 if (ss -> cancel_attach )
2215- ss -> cancel_attach (ss , cgrp , leader );
2294+ ss -> cancel_attach (ss , cgrp , & tset );
22162295 }
22172296 }
22182297out_put_tasks :
0 commit comments