|
@@ -4629,122 +4629,6 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
|
|
|
put_css_set_taskexit(cg);
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * cgroup_clone - clone the cgroup the given subsystem is attached to
|
|
|
- * @tsk: the task to be moved
|
|
|
- * @subsys: the given subsystem
|
|
|
- * @nodename: the name for the new cgroup
|
|
|
- *
|
|
|
- * Duplicate the current cgroup in the hierarchy that the given
|
|
|
- * subsystem is attached to, and move this task into the new
|
|
|
- * child.
|
|
|
- */
|
|
|
-int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys,
|
|
|
- char *nodename)
|
|
|
-{
|
|
|
- struct dentry *dentry;
|
|
|
- int ret = 0;
|
|
|
- struct cgroup *parent, *child;
|
|
|
- struct inode *inode;
|
|
|
- struct css_set *cg;
|
|
|
- struct cgroupfs_root *root;
|
|
|
- struct cgroup_subsys *ss;
|
|
|
-
|
|
|
- /* We shouldn't be called by an unregistered subsystem */
|
|
|
- BUG_ON(!subsys->active);
|
|
|
-
|
|
|
- /* First figure out what hierarchy and cgroup we're dealing
|
|
|
- * with, and pin them so we can drop cgroup_mutex */
|
|
|
- mutex_lock(&cgroup_mutex);
|
|
|
- again:
|
|
|
- root = subsys->root;
|
|
|
- if (root == &rootnode) {
|
|
|
- mutex_unlock(&cgroup_mutex);
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- /* Pin the hierarchy */
|
|
|
- if (!atomic_inc_not_zero(&root->sb->s_active)) {
|
|
|
- /* We race with the final deactivate_super() */
|
|
|
- mutex_unlock(&cgroup_mutex);
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- /* Keep the cgroup alive */
|
|
|
- task_lock(tsk);
|
|
|
- parent = task_cgroup(tsk, subsys->subsys_id);
|
|
|
- cg = tsk->cgroups;
|
|
|
- get_css_set(cg);
|
|
|
- task_unlock(tsk);
|
|
|
-
|
|
|
- mutex_unlock(&cgroup_mutex);
|
|
|
-
|
|
|
- /* Now do the VFS work to create a cgroup */
|
|
|
- inode = parent->dentry->d_inode;
|
|
|
-
|
|
|
- /* Hold the parent directory mutex across this operation to
|
|
|
- * stop anyone else deleting the new cgroup */
|
|
|
- mutex_lock(&inode->i_mutex);
|
|
|
- dentry = lookup_one_len(nodename, parent->dentry, strlen(nodename));
|
|
|
- if (IS_ERR(dentry)) {
|
|
|
- printk(KERN_INFO
|
|
|
- "cgroup: Couldn't allocate dentry for %s: %ld\n", nodename,
|
|
|
- PTR_ERR(dentry));
|
|
|
- ret = PTR_ERR(dentry);
|
|
|
- goto out_release;
|
|
|
- }
|
|
|
-
|
|
|
- /* Create the cgroup directory, which also creates the cgroup */
|
|
|
- ret = vfs_mkdir(inode, dentry, 0755);
|
|
|
- child = __d_cgrp(dentry);
|
|
|
- dput(dentry);
|
|
|
- if (ret) {
|
|
|
- printk(KERN_INFO
|
|
|
- "Failed to create cgroup %s: %d\n", nodename,
|
|
|
- ret);
|
|
|
- goto out_release;
|
|
|
- }
|
|
|
-
|
|
|
- /* The cgroup now exists. Retake cgroup_mutex and check
|
|
|
- * that we're still in the same state that we thought we
|
|
|
- * were. */
|
|
|
- mutex_lock(&cgroup_mutex);
|
|
|
- if ((root != subsys->root) ||
|
|
|
- (parent != task_cgroup(tsk, subsys->subsys_id))) {
|
|
|
- /* Aargh, we raced ... */
|
|
|
- mutex_unlock(&inode->i_mutex);
|
|
|
- put_css_set(cg);
|
|
|
-
|
|
|
- deactivate_super(root->sb);
|
|
|
- /* The cgroup is still accessible in the VFS, but
|
|
|
- * we're not going to try to rmdir() it at this
|
|
|
- * point. */
|
|
|
- printk(KERN_INFO
|
|
|
- "Race in cgroup_clone() - leaking cgroup %s\n",
|
|
|
- nodename);
|
|
|
- goto again;
|
|
|
- }
|
|
|
-
|
|
|
- /* do any required auto-setup */
|
|
|
- for_each_subsys(root, ss) {
|
|
|
- if (ss->post_clone)
|
|
|
- ss->post_clone(ss, child);
|
|
|
- }
|
|
|
-
|
|
|
- /* All seems fine. Finish by moving the task into the new cgroup */
|
|
|
- ret = cgroup_attach_task(child, tsk);
|
|
|
- mutex_unlock(&cgroup_mutex);
|
|
|
-
|
|
|
- out_release:
|
|
|
- mutex_unlock(&inode->i_mutex);
|
|
|
-
|
|
|
- mutex_lock(&cgroup_mutex);
|
|
|
- put_css_set(cg);
|
|
|
- mutex_unlock(&cgroup_mutex);
|
|
|
- deactivate_super(root->sb);
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* cgroup_is_descendant - see if @cgrp is a descendant of @task's cgrp
|
|
|
* @cgrp: the cgroup in question
|