cgroup: fix mount failure in a corner case
# cat test.sh #! /bin/bash mount -t cgroup -o cpu xxx /cgroup umount /cgroup mount -t cgroup -o cpu,cpuacct xxx /cgroup umount /cgroup # ./test.sh mount: xxx already mounted or /cgroup busy mount: according to mtab, xxx is already mounted on /cgroup It's because the cgroupfs_root of the first mount was under destruction asynchronously. Fix this by delaying and then retrying mount for this case. v3: - put the refcnt immediately after getting it. (Tejun) v2: - use percpu_ref_tryget_live() rather that introducing percpu_ref_alive(). (Tejun) - adjust comment. tj: Updated the comment a bit. Cc: <stable@vger.kernel.org> # 3.15 Signed-off-by: Li Zefan <lizefan@huawei.com> Signed-off-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
parent
391acf970d
commit
970317aa48
1 changed files with 23 additions and 0 deletions
|
@ -1648,10 +1648,12 @@ 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 cgroup_subsys *ss;
|
||||||
struct cgroup_root *root;
|
struct cgroup_root *root;
|
||||||
struct cgroup_sb_opts opts;
|
struct cgroup_sb_opts opts;
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
int ret;
|
int ret;
|
||||||
|
int i;
|
||||||
bool new_sb;
|
bool new_sb;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1677,6 +1679,27 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destruction of cgroup root is asynchronous, so subsystems may
|
||||||
|
* still be dying after the previous unmount. Let's drain the
|
||||||
|
* dying subsystems. We just need to ensure that the ones
|
||||||
|
* unmounted previously finish dying and don't care about new ones
|
||||||
|
* starting. Testing ref liveliness is good enough.
|
||||||
|
*/
|
||||||
|
for_each_subsys(ss, i) {
|
||||||
|
if (!(opts.subsys_mask & (1 << i)) ||
|
||||||
|
ss->root == &cgrp_dfl_root)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!percpu_ref_tryget_live(&ss->root->cgrp.self.refcnt)) {
|
||||||
|
mutex_unlock(&cgroup_mutex);
|
||||||
|
msleep(10);
|
||||||
|
ret = restart_syscall();
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
cgroup_put(&ss->root->cgrp);
|
||||||
|
}
|
||||||
|
|
||||||
for_each_root(root) {
|
for_each_root(root) {
|
||||||
bool name_match = false;
|
bool name_match = false;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue