Currently, the only method to detach a task from a cgroup is moving
it to others. It looks not natrual to me.

Inspired by cgroup_subtree_control_write(), this patch introduce allow
user to at-detach a process to/from a cgroup by echo "+/-pid" to
cgroup.procs. In addition, we keep the old method to allow user
echo "pid" without "+/-" to cgroup.procs as a attaching behavior.

Signed-off-by: Dongsheng Yang <[email protected]>
---

>From v1:
        *Sorry for a incorrect comment in v1.

 kernel/cgroup.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 59 insertions(+), 2 deletions(-)

diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 7dc8788..a4bb604 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -2348,6 +2348,43 @@ static int cgroup_attach_task(struct cgroup *dst_cgrp,
        return ret;
 }
 
+/**
+ * cgroup_detach_task - detach a task or a whole threadgroup to a cgroup
+ * @src_cgrp: the cgroup to detach from
+ * @leader: the task or the leader of the threadgroup to be attached
+ * @threadgroup: attach the whole threadgroup?
+ *
+ * Call holding cgroup_mutex and threadgroup_lock of @leader.
+ */
+static int cgroup_detach_task(struct cgroup *src_cgrp __maybe_unused,
+                             struct task_struct *leader, bool threadgroup)
+{
+       LIST_HEAD(preloaded_csets);
+       struct task_struct *task;
+       int ret;
+
+       /* look up all src csets */
+       down_read(&css_set_rwsem);
+       rcu_read_lock();
+       task = leader;
+       do {
+               cgroup_migrate_add_src(task_css_set(task), &cgrp_dfl_root.cgrp,
+                                      &preloaded_csets);
+               if (!threadgroup)
+                       break;
+       } while_each_thread(leader, task);
+       rcu_read_unlock();
+       up_read(&css_set_rwsem);
+
+       /* prepare dst csets and commit */
+       ret = cgroup_migrate_prepare_dst(&cgrp_dfl_root.cgrp, &preloaded_csets);
+       if (!ret)
+               ret = cgroup_migrate(&cgrp_dfl_root.cgrp, leader, threadgroup);
+
+       cgroup_migrate_finish(&preloaded_csets);
+       return ret;
+}
+
 /*
  * Find the task_struct of the task to attach by vpid and pass it along to the
  * function to attach either it or all tasks in its threadgroup. Will lock
@@ -2361,8 +2398,25 @@ static ssize_t __cgroup_procs_write(struct 
kernfs_open_file *of, char *buf,
        struct cgroup *cgrp;
        pid_t pid;
        int ret;
+       bool attach;
 
-       if (kstrtoint(strstrip(buf), 0, &pid) || pid < 0)
+       /*
+        * Parse input - pid prefixed with either + or -.
+        */
+       buf = strstrip(buf);
+       if (*buf == '+') {
+               attach = true;
+               buf++;
+       } else if (*buf == '-') {
+               attach = false;
+               buf++;
+       } else {
+               if (!isdigit(*buf))
+                       return -EINVAL;
+               attach = true;
+       }
+
+       if (kstrtoint(buf, 0, &pid) || pid < 0)
                return -EINVAL;
 
        cgrp = cgroup_kn_lock_live(of->kn);
@@ -2426,7 +2480,10 @@ retry_find_task:
                }
        }
 
-       ret = cgroup_attach_task(cgrp, tsk, threadgroup);
+       if (attach)
+               ret = cgroup_attach_task(cgrp, tsk, threadgroup);
+       else
+               ret = cgroup_detach_task(cgrp, tsk, threadgroup);
 
        threadgroup_unlock(tsk);
 
-- 
1.8.4.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to