Commit 765ab2f0 authored by Seth Forshee's avatar Seth Forshee Committed by Kamal Mostafa

Revert "UBUNTU: SAUCE: cgroup: Use a new super block when mounting in a cgroup namespace"

BugLink: http://bugs.launchpad.net/bugs/1588056

This reverts commit 794fbce4.
Signed-off-by: default avatarSeth Forshee <seth.forshee@canonical.com>
Acked-by: default avatarTim Gardner <tim.gardner@canonical.com>
Acked-by: default avatarBrad Figg <brad.figg@canonical.com>
Signed-off-by: default avatarKamal Mostafa <kamal@canonical.com>
parent 3988fb70
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <linux/percpu-refcount.h> #include <linux/percpu-refcount.h>
#include <linux/percpu-rwsem.h> #include <linux/percpu-rwsem.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/kref.h>
#ifdef CONFIG_CGROUPS #ifdef CONFIG_CGROUPS
...@@ -305,9 +304,6 @@ struct cgroup { ...@@ -305,9 +304,6 @@ struct cgroup {
struct cgroup_root { struct cgroup_root {
struct kernfs_root *kf_root; struct kernfs_root *kf_root;
/* Reference count for superblocks sharing this cgroup_root */
struct kref kref;
/* The bitmask of subsystems attached to this hierarchy */ /* The bitmask of subsystems attached to this hierarchy */
unsigned int subsys_mask; unsigned int subsys_mask;
......
...@@ -1971,7 +1971,6 @@ static void init_cgroup_root(struct cgroup_root *root, ...@@ -1971,7 +1971,6 @@ static void init_cgroup_root(struct cgroup_root *root,
{ {
struct cgroup *cgrp = &root->cgrp; struct cgroup *cgrp = &root->cgrp;
kref_init(&root->kref);
INIT_LIST_HEAD(&root->root_list); INIT_LIST_HEAD(&root->root_list);
atomic_set(&root->nr_cgrps, 1); atomic_set(&root->nr_cgrps, 1);
cgrp->root = root; cgrp->root = root;
...@@ -2076,28 +2075,11 @@ static int cgroup_setup_root(struct cgroup_root *root, unsigned long ss_mask) ...@@ -2076,28 +2075,11 @@ static int cgroup_setup_root(struct cgroup_root *root, unsigned long ss_mask)
return ret; return ret;
} }
static void cgroup_release_root(struct kref *kref)
{
struct cgroup_root *root = container_of(kref, struct cgroup_root, kref);
/*
* If @root doesn't have any mounts or children, start killing it.
* This prevents new mounts by disabling percpu_ref_tryget_live().
* cgroup_mount() may wait for @root's release.
*
* And don't kill the default root.
*/
if (!list_empty(&root->cgrp.self.children) ||
root == &cgrp_dfl_root)
cgroup_put(&root->cgrp);
else
percpu_ref_kill(&root->cgrp.self.refcnt);
}
static struct dentry *cgroup_mount(struct file_system_type *fs_type, static struct dentry *cgroup_mount(struct file_system_type *fs_type,
int flags, const char *unused_dev_name, int flags, const char *unused_dev_name,
void *data) void *data)
{ {
struct super_block *pinned_sb = NULL;
struct cgroup_namespace *ns = current->nsproxy->cgroup_ns; struct cgroup_namespace *ns = current->nsproxy->cgroup_ns;
struct cgroup_subsys *ss; struct cgroup_subsys *ss;
struct cgroup_root *root; struct cgroup_root *root;
...@@ -2193,12 +2175,22 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, ...@@ -2193,12 +2175,22 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
/* /*
* We want to reuse @root whose lifetime is governed by its * We want to reuse @root whose lifetime is governed by its
* refcnt. If the refcnt is already zero then it's too late; * ->cgrp. Let's check whether @root is alive and keep it
* sleep a bit and retry. Otherwise we get a reference and * that way. As cgroup_kill_sb() can happen anytime, we
* can reuse the root. * want to block it by pinning the sb so that @root doesn't
*/ * get killed before mount is complete.
if (!kref_get_unless_zero(&root->kref)) { *
* With the sb pinned, tryget_live can reliably indicate
* whether @root can be reused. If it's being killed,
* drain it. We can use wait_queue for the wait but this
* path is super cold. Let's just sleep a bit and retry.
*/
pinned_sb = kernfs_pin_sb(root->kf_root, NULL);
if (IS_ERR(pinned_sb) ||
!percpu_ref_tryget_live(&root->cgrp.self.refcnt)) {
mutex_unlock(&cgroup_mutex); mutex_unlock(&cgroup_mutex);
if (!IS_ERR_OR_NULL(pinned_sb))
deactivate_super(pinned_sb);
msleep(10); msleep(10);
ret = restart_syscall(); ret = restart_syscall();
goto out_free; goto out_free;
...@@ -2251,8 +2243,8 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, ...@@ -2251,8 +2243,8 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
return ERR_PTR(ret); return ERR_PTR(ret);
} }
dentry = kernfs_mount_ns(fs_type, flags, root->kf_root, dentry = kernfs_mount(fs_type, flags, root->kf_root,
CGROUP_SUPER_MAGIC, &new_sb, ns); CGROUP_SUPER_MAGIC, &new_sb);
/* /*
* In non-init cgroup namespace, instead of root cgroup's * In non-init cgroup namespace, instead of root cgroup's
...@@ -2276,12 +2268,17 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, ...@@ -2276,12 +2268,17 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
dentry = nsdentry; dentry = nsdentry;
} }
if (IS_ERR(dentry) || !new_sb)
cgroup_put(&root->cgrp);
/* /*
* On failure put the cgroup_root. If this is the last reference * If @pinned_sb, we're reusing an existing root and holding an
* cgroup_release_root will put the cgroup. * extra ref on its sb. Mount is complete. Put the extra ref.
*/ */
if (IS_ERR(dentry)) if (pinned_sb) {
kref_put(&root->kref, cgroup_release_root); WARN_ON(new_sb);
deactivate_super(pinned_sb);
}
put_cgroup_ns(ns); put_cgroup_ns(ns);
return dentry; return dentry;
...@@ -2292,7 +2289,19 @@ static void cgroup_kill_sb(struct super_block *sb) ...@@ -2292,7 +2289,19 @@ static void cgroup_kill_sb(struct super_block *sb)
struct kernfs_root *kf_root = kernfs_root_from_sb(sb); struct kernfs_root *kf_root = kernfs_root_from_sb(sb);
struct cgroup_root *root = cgroup_root_from_kf(kf_root); struct cgroup_root *root = cgroup_root_from_kf(kf_root);
kref_put(&root->kref, cgroup_release_root); /*
* If @root doesn't have any mounts or children, start killing it.
* This prevents new mounts by disabling percpu_ref_tryget_live().
* cgroup_mount() may wait for @root's release.
*
* And don't kill the default root.
*/
if (!list_empty(&root->cgrp.self.children) ||
root == &cgrp_dfl_root)
cgroup_put(&root->cgrp);
else
percpu_ref_kill(&root->cgrp.self.refcnt);
kernfs_kill_sb(sb); kernfs_kill_sb(sb);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment