]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
cgroup: consolidate cgroup_attach_task() and cgroup_attach_proc()
authorLi Zefan <lizefan@huawei.com>
Wed, 13 Mar 2013 01:17:09 +0000 (09:17 +0800)
committerTejun Heo <tj@kernel.org>
Wed, 20 Mar 2013 14:50:25 +0000 (07:50 -0700)
These two functions share most of the code.

Signed-off-by: Li Zefan <lizefan@huawei.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
include/linux/cgroup.h
kernel/cgroup.c
kernel/cpuset.c

index 7e818a3ef60a11e36d594a7c32c07cc9f548acbb..01c48c6806d62817e6baf8f91eecb640f251f101 100644 (file)
@@ -693,7 +693,8 @@ struct task_struct *cgroup_iter_next(struct cgroup *cgrp,
                                        struct cgroup_iter *it);
 void cgroup_iter_end(struct cgroup *cgrp, struct cgroup_iter *it);
 int cgroup_scan_tasks(struct cgroup_scanner *scan);
-int cgroup_attach_task(struct cgroup *, struct task_struct *);
+int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
+                      bool threadgroup);
 int cgroup_attach_task_all(struct task_struct *from, struct task_struct *);
 
 /*
index 54689fc008f654eb45034773b13949a91a2af126..04fa2abf94b25f58c090eff54d9b599f468fe15d 100644 (file)
@@ -59,7 +59,7 @@
 #include <linux/vmalloc.h> /* TODO: replace with more sophisticated array */
 #include <linux/eventfd.h>
 #include <linux/poll.h>
-#include <linux/flex_array.h> /* used in cgroup_attach_proc */
+#include <linux/flex_array.h> /* used in cgroup_attach_task */
 #include <linux/kthread.h>
 
 #include <linux/atomic.h>
@@ -1943,82 +1943,6 @@ static void cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp,
        put_css_set(oldcg);
 }
 
-/**
- * cgroup_attach_task - attach task 'tsk' to cgroup 'cgrp'
- * @cgrp: the cgroup the task is attaching to
- * @tsk: the task to be attached
- *
- * Call with cgroup_mutex and threadgroup locked. May take task_lock of
- * @tsk during call.
- */
-int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
-{
-       int retval = 0;
-       struct cgroup_subsys *ss, *failed_ss = NULL;
-       struct cgroup *oldcgrp;
-       struct cgroupfs_root *root = cgrp->root;
-       struct cgroup_taskset tset = { };
-       struct css_set *newcg;
-
-       /* @tsk either already exited or can't exit until the end */
-       if (tsk->flags & PF_EXITING)
-               return -ESRCH;
-
-       /* Nothing to do if the task is already in that cgroup */
-       oldcgrp = task_cgroup_from_root(tsk, root);
-       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(cgrp, &tset);
-                       if (retval) {
-                               /*
-                                * Remember on which subsystem the can_attach()
-                                * failed, so that we only call cancel_attach()
-                                * against the subsystems whose can_attach()
-                                * succeeded. (See below)
-                                */
-                               failed_ss = ss;
-                               goto out;
-                       }
-               }
-       }
-
-       newcg = find_css_set(tsk->cgroups, cgrp);
-       if (!newcg) {
-               retval = -ENOMEM;
-               goto out;
-       }
-
-       cgroup_task_migrate(cgrp, oldcgrp, tsk, newcg);
-
-       for_each_subsys(root, ss) {
-               if (ss->attach)
-                       ss->attach(cgrp, &tset);
-       }
-
-out:
-       if (retval) {
-               for_each_subsys(root, ss) {
-                       if (ss == failed_ss)
-                               /*
-                                * This subsystem was the one that failed the
-                                * can_attach() check earlier, so we don't need
-                                * to call cancel_attach() against it or any
-                                * remaining subsystems.
-                                */
-                               break;
-                       if (ss->cancel_attach)
-                               ss->cancel_attach(cgrp, &tset);
-               }
-       }
-       return retval;
-}
-
 /**
  * cgroup_attach_task_all - attach task 'tsk' to all cgroups of task 'from'
  * @from: attach to all cgroups of a given task
@@ -2033,7 +1957,7 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
        for_each_active_root(root) {
                struct cgroup *from_cg = task_cgroup_from_root(from, root);
 
-               retval = cgroup_attach_task(from_cg, tsk);
+               retval = cgroup_attach_task(from_cg, tsk, false);
                if (retval)
                        break;
        }
@@ -2044,21 +1968,22 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
 EXPORT_SYMBOL_GPL(cgroup_attach_task_all);
 
 /**
- * cgroup_attach_proc - attach all threads in a threadgroup to a cgroup
+ * cgroup_attach_task - attach a task or a whole threadgroup to a cgroup
  * @cgrp: the cgroup to attach to
- * @leader: the threadgroup leader task_struct of the group to be attached
+ * @tsk: the task or the leader of the threadgroup to be attached
+ * @threadgroup: attach the whole threadgroup?
  *
  * Call holding cgroup_mutex and the group_rwsem of the leader. Will take
- * task_lock of each thread in leader's threadgroup individually in turn.
+ * task_lock of @tsk or each thread in the threadgroup individually in turn.
  */
-static int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
+int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
+                      bool threadgroup)
 {
        int retval, i, group_size;
        struct cgroup_subsys *ss, *failed_ss = NULL;
-       /* guaranteed to be initialized later, but the compiler needs this */
        struct cgroupfs_root *root = cgrp->root;
        /* threadgroup list cursor and array */
-       struct task_struct *tsk;
+       struct task_struct *leader = tsk;
        struct task_and_cgroup *tc;
        struct flex_array *group;
        struct cgroup_taskset tset = { };
@@ -2070,7 +1995,10 @@ static int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
         * group - group_rwsem prevents new threads from appearing, and if
         * threads exit, this will just be an over-estimate.
         */
-       group_size = get_nr_threads(leader);
+       if (threadgroup)
+               group_size = get_nr_threads(tsk);
+       else
+               group_size = 1;
        /* flex_array supports very large thread-groups better than kmalloc. */
        group = flex_array_alloc(sizeof(*tc), group_size, GFP_KERNEL);
        if (!group)
@@ -2080,7 +2008,6 @@ static int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
        if (retval)
                goto out_free_group_list;
 
-       tsk = leader;
        i = 0;
        /*
         * Prevent freeing of tasks while we take a snapshot. Tasks that are
@@ -2109,6 +2036,9 @@ static int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
                retval = flex_array_put(group, i, &ent, GFP_ATOMIC);
                BUG_ON(retval != 0);
                i++;
+
+               if (!threadgroup)
+                       break;
        } while_each_thread(leader, tsk);
        rcu_read_unlock();
        /* remember the number of threads in the array for later. */
@@ -2262,9 +2192,10 @@ retry_find_task:
                        put_task_struct(tsk);
                        goto retry_find_task;
                }
-               ret = cgroup_attach_proc(cgrp, tsk);
-       } else
-               ret = cgroup_attach_task(cgrp, tsk);
+       }
+
+       ret = cgroup_attach_task(cgrp, tsk, threadgroup);
+
        threadgroup_unlock(tsk);
 
        put_task_struct(tsk);
index efbfca7a33e483787a744a1545f3f1d6b100dcbe..98d458aad78971ffd6450b8ac666fe76979a48ae 100644 (file)
@@ -2008,7 +2008,7 @@ static void cpuset_do_move_task(struct task_struct *tsk,
        struct cgroup *new_cgroup = scan->data;
 
        cgroup_lock();
-       cgroup_attach_task(new_cgroup, tsk);
+       cgroup_attach_task(new_cgroup, tsk, false);
        cgroup_unlock();
 }