Thursday, April 26, 2012

Another kernel patch for fork-exit with cgroups

Back to previous patch, I realize that I must handle move tasks from one group to another (this operation also change tasks file, so we want to take event about this)

Also in the cgroup list I took advice to move it to the fsnotify, bcoz fsnotify works from userspace side so it's very straight full to add this functionality also to take event from kernel side. Let's look on one example. If we write something like echo $$ > /path/to/cgroup/tasks we will take fsnotify FS_MODIFY about this. But when our program will end and kernel delete it from tasks list and tasks cgroup file we won't take FS_MODIFY. So make patch for this.

We must save dentry, because when file open()/read()/write() kernel create struct *file instance for this, and when it event user space with FS_MODIFY it uses inode.
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -179,6 +179,8 @@ struct cgroup {
  struct cgroup *parent;  /* my parent */
  struct dentry __rcu *dentry; /* cgroup fs entry, RCU protected */
 
+ struct dentry *tasks_dentry; /* "tasks" dentry */
+
  /* Private pointers for each registered subsystem */
  struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];

Add function to cgroup.c for notify user space
+static inline void fsnotify_cgroup(struct task_struct *tsk, __u32 mask)
+{
+ struct cgroupfs_root *root;
+ struct inode *d_inode;
+ struct cgroup *cgrp;
+
+ for_each_active_root(root) {
+  cgrp = task_cgroup_from_root(tsk, root);
+  d_inode = cgrp->tasks_dentry->d_inode;
+
+  fsnotify_parent(NULL, cgrp->tasks_dentry, mask);
+  fsnotify(d_inode, mask, d_inode, FSNOTIFY_EVENT_INODE, NULL, 0);
+ }
+}
Send notify when group changed
@@ -1924,6 +1940,9 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
   goto out;
  }
 
+ /* send event to the userspace */
+ fsnotify_cgroup(tsk, FS_MODIFY);
+
  cgroup_task_migrate(cgrp, oldcgrp, tsk, newcg);
 
  for_each_subsys(root, ss) {

Now we need to save dentry for the "tasks" file when kernel create this cgroup. Not so hard modification. You'll see it in the patch. Also we must patch cgroup_fork() and cgroup_exit
@@ -4489,6 +4520,10 @@ void cgroup_fork(struct task_struct *child)
  child->cgroups = current->cgroups;
  get_css_set(child->cgroups);
  INIT_LIST_HEAD(&child->cg_list);
+
+ cgroup_lock();
+ fsnotify_cgroup(child, FS_MODIFY);
+ cgroup_unlock();
 }
 
 /**
@@ -4611,6 +4646,11 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
  /* Reassign the task to the init_css_set. */
  task_lock(tsk);
  cg = tsk->cgroups;
+
+ cgroup_lock();
+ fsnotify_cgroup(tsk, FS_MODIFY);
+ cgroup_unlock();
+
  tsk->cgroups = &init_css_set;

Not so hard))) And complete patch


No comments:

Post a Comment