cgroup: move migration destination verification out of cgroup_migrate_prepare_dst()
authorTejun Heo <tj@kernel.org>
Tue, 8 Mar 2016 16:51:25 +0000 (11:51 -0500)
committerTejun Heo <tj@kernel.org>
Tue, 8 Mar 2016 16:51:25 +0000 (11:51 -0500)
cgroup_migrate_prepare_dst() verifies whether the destination cgroup
is allowable; however, the test doesn't really belong there.  It's too
deep and common in the stack and as a result the test itself is gated
by another test.

Separate the test out into cgroup_may_migrate_to() and update
cgroup_attach_task() and cgroup_transfer_tasks() to perform the test
directly.  This doesn't cause any behavior differences.

Signed-off-by: Tejun Heo <tj@kernel.org>
kernel/cgroup.c

index 50879aadcbd0e2c6dcabe9ae64c73dc67ac7405a..8a02076d4317ac2800bd816824fcfbfe025bc9b0 100644 (file)
@@ -2443,6 +2443,20 @@ out_release_tset:
        return ret;
 }
 
+/**
+ * cgroup_may_migrate_to - verify whether a cgroup can be migration destination
+ * @dst_cgrp: destination cgroup to test
+ *
+ * On the default hierarchy, except for the root, subtree_control must be
+ * zero for migration destination cgroups with tasks so that child cgroups
+ * don't compete against tasks.
+ */
+static bool cgroup_may_migrate_to(struct cgroup *dst_cgrp)
+{
+       return !cgroup_on_dfl(dst_cgrp) || !cgroup_parent(dst_cgrp) ||
+               !dst_cgrp->subtree_control;
+}
+
 /**
  * cgroup_migrate_finish - cleanup after attach
  * @preloaded_csets: list of preloaded css_sets
@@ -2529,14 +2543,6 @@ static int cgroup_migrate_prepare_dst(struct cgroup *dst_cgrp,
 
        lockdep_assert_held(&cgroup_mutex);
 
-       /*
-        * Except for the root, subtree_control must be zero for a cgroup
-        * with tasks so that child cgroups don't compete against tasks.
-        */
-       if (dst_cgrp && cgroup_on_dfl(dst_cgrp) && cgroup_parent(dst_cgrp) &&
-           dst_cgrp->subtree_control)
-               return -EBUSY;
-
        /* look up the dst cset for each src cset and link it to src */
        list_for_each_entry_safe(src_cset, tmp_cset, preloaded_csets, mg_preload_node) {
                struct css_set *dst_cset;
@@ -2634,6 +2640,9 @@ static int cgroup_attach_task(struct cgroup *dst_cgrp,
        struct task_struct *task;
        int ret;
 
+       if (!cgroup_may_migrate_to(dst_cgrp))
+               return -EBUSY;
+
        /* look up all src csets */
        spin_lock_bh(&css_set_lock);
        rcu_read_lock();
@@ -4136,6 +4145,9 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
        struct task_struct *task;
        int ret;
 
+       if (!cgroup_may_migrate_to(to))
+               return -EBUSY;
+
        mutex_lock(&cgroup_mutex);
 
        /* all tasks in @from are being moved, all csets are source */