cgroup: don't use subsys->can_attach_task() or ->attach_task()
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / kernel / cpuset.c
index 10131fdaff70c36dc9fb181ace777015296891e3..9a8a613015246b6f90da9d81a6fc6279a8e26667 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/mempolicy.h>
 #include <linux/mm.h>
 #include <linux/memory.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/pagemap.h>
@@ -949,6 +949,8 @@ static void cpuset_migrate_mm(struct mm_struct *mm, const nodemask_t *from,
 static void cpuset_change_task_nodemask(struct task_struct *tsk,
                                        nodemask_t *newmems)
 {
+       bool masks_disjoint = !nodes_intersects(*newmems, tsk->mems_allowed);
+
 repeat:
        /*
         * Allow tasks that have access to memory reserves because they have
@@ -963,7 +965,6 @@ repeat:
        nodes_or(tsk->mems_allowed, tsk->mems_allowed, *newmems);
        mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP1);
 
-
        /*
         * ensure checking ->mems_allowed_change_disable after setting all new
         * allowed nodes.
@@ -980,9 +981,11 @@ repeat:
 
        /*
         * Allocation of memory is very fast, we needn't sleep when waiting
-        * for the read-side.
+        * for the read-side.  No wait is necessary, however, if at least one
+        * node remains unchanged.
         */
-       while (ACCESS_ONCE(tsk->mems_allowed_change_disable)) {
+       while (masks_disjoint &&
+                       ACCESS_ONCE(tsk->mems_allowed_change_disable)) {
                task_unlock(tsk);
                if (!task_curr(tsk))
                        yield();
@@ -1368,37 +1371,38 @@ static int fmeter_getrate(struct fmeter *fmp)
 }
 
 /* Called by cgroups to determine if a cpuset is usable; cgroup_mutex held */
-static int cpuset_can_attach(struct cgroup_subsys *ss, struct cgroup *cont,
-                            struct task_struct *tsk)
+static int cpuset_can_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+                            struct cgroup_taskset *tset)
 {
-       struct cpuset *cs = cgroup_cs(cont);
+       struct cpuset *cs = cgroup_cs(cgrp);
+       struct task_struct *task;
+       int ret;
 
        if (cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed))
                return -ENOSPC;
 
-       /*
-        * Kthreads bound to specific cpus cannot be moved to a new cpuset; we
-        * cannot change their cpu affinity and isolating such threads by their
-        * set of allowed nodes is unnecessary.  Thus, cpusets are not
-        * applicable for such threads.  This prevents checking for success of
-        * set_cpus_allowed_ptr() on all attached tasks before cpus_allowed may
-        * be changed.
-        */
-       if (tsk->flags & PF_THREAD_BOUND)
-               return -EINVAL;
-
+       cgroup_taskset_for_each(task, cgrp, tset) {
+               /*
+                * Kthreads bound to specific cpus cannot be moved to a new
+                * cpuset; we cannot change their cpu affinity and
+                * isolating such threads by their set of allowed nodes is
+                * unnecessary.  Thus, cpusets are not applicable for such
+                * threads.  This prevents checking for success of
+                * set_cpus_allowed_ptr() on all attached tasks before
+                * cpus_allowed may be changed.
+                */
+               if (task->flags & PF_THREAD_BOUND)
+                       return -EINVAL;
+               if ((ret = security_task_setscheduler(task)))
+                       return ret;
+       }
        return 0;
 }
 
-static int cpuset_can_attach_task(struct cgroup *cgrp, struct task_struct *task)
-{
-       return security_task_setscheduler(task);
-}
-
 /*
  * Protected by cgroup_lock. The nodemasks must be stored globally because
  * dynamically allocating them is not allowed in pre_attach, and they must
- * persist among pre_attach, attach_task, and attach.
+ * persist among pre_attach, and attach.
  */
 static cpumask_var_t cpus_attach;
 static nodemask_t cpuset_attach_nodemask_from;
@@ -1417,29 +1421,26 @@ static void cpuset_pre_attach(struct cgroup *cont)
        guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
 }
 
-/* Per-thread attachment work. */
-static void cpuset_attach_task(struct cgroup *cont, struct task_struct *tsk)
+static void cpuset_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+                         struct cgroup_taskset *tset)
 {
-       int err;
-       struct cpuset *cs = cgroup_cs(cont);
-
-       /*
-        * can_attach beforehand should guarantee that this doesn't fail.
-        * TODO: have a better way to handle failure here
-        */
-       err = set_cpus_allowed_ptr(tsk, cpus_attach);
-       WARN_ON_ONCE(err);
+       struct mm_struct *mm;
+       struct task_struct *task;
+       struct task_struct *leader = cgroup_taskset_first(tset);
+       struct cgroup *oldcgrp = cgroup_taskset_cur_cgroup(tset);
+       struct cpuset *cs = cgroup_cs(cgrp);
+       struct cpuset *oldcs = cgroup_cs(oldcgrp);
 
-       cpuset_change_task_nodemask(tsk, &cpuset_attach_nodemask_to);
-       cpuset_update_task_spread_flag(cs, tsk);
-}
+       cgroup_taskset_for_each(task, cgrp, tset) {
+               /*
+                * can_attach beforehand should guarantee that this doesn't
+                * fail.  TODO: have a better way to handle failure here
+                */
+               WARN_ON_ONCE(set_cpus_allowed_ptr(task, cpus_attach));
 
-static void cpuset_attach(struct cgroup_subsys *ss, struct cgroup *cont,
-                         struct cgroup *oldcont, struct task_struct *tsk)
-{
-       struct mm_struct *mm;
-       struct cpuset *cs = cgroup_cs(cont);
-       struct cpuset *oldcs = cgroup_cs(oldcont);
+               cpuset_change_task_nodemask(task, &cpuset_attach_nodemask_to);
+               cpuset_update_task_spread_flag(cs, task);
+       }
 
        /*
         * Change mm, possibly for multiple threads in a threadgroup. This is
@@ -1447,7 +1448,7 @@ static void cpuset_attach(struct cgroup_subsys *ss, struct cgroup *cont,
         */
        cpuset_attach_nodemask_from = oldcs->mems_allowed;
        cpuset_attach_nodemask_to = cs->mems_allowed;
-       mm = get_task_mm(tsk);
+       mm = get_task_mm(leader);
        if (mm) {
                mpol_rebind_mm(mm, &cpuset_attach_nodemask_to);
                if (is_memory_migrate(cs))
@@ -1903,9 +1904,7 @@ struct cgroup_subsys cpuset_subsys = {
        .create = cpuset_create,
        .destroy = cpuset_destroy,
        .can_attach = cpuset_can_attach,
-       .can_attach_task = cpuset_can_attach_task,
        .pre_attach = cpuset_pre_attach,
-       .attach_task = cpuset_attach_task,
        .attach = cpuset_attach,
        .populate = cpuset_populate,
        .post_clone = cpuset_post_clone,