]> git.ipfire.org Git - people/ms/linux.git/commit
cgroup: fix a race between cgroup_mount() and cgroup_kill_sb()
authorLi Zefan <lizefan@huawei.com>
Mon, 30 Jun 2014 03:50:59 +0000 (11:50 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 17 Jul 2014 23:23:19 +0000 (16:23 -0700)
commit3fa0637a2a027db4a0d31314b0e9e6bd5526bb17
tree6f7701c65a73348d7e7f18eb9345608842366ebf
parentf5fc1ec5e8d32bfb559a87800633b0a82a37e640
cgroup: fix a race between cgroup_mount() and cgroup_kill_sb()

commit 3a32bd72d77058d768dbb38183ad517f720dd1bc upstream.

We've converted cgroup to kernfs so cgroup won't be intertwined with
vfs objects and locking, but there are dark areas.

Run two instances of this script concurrently:

    for ((; ;))
    {
     mount -t cgroup -o cpuacct xxx /cgroup
     umount /cgroup
    }

After a while, I saw two mount processes were stuck at retrying, because
they were waiting for a subsystem to become free, but the root associated
with this subsystem never got freed.

This can happen, if thread A is in the process of killing superblock but
hasn't called percpu_ref_kill(), and at this time thread B is mounting
the same cgroup root and finds the root in the root list and performs
percpu_ref_try_get().

To fix this, we try to increase both the refcnt of the superblock and the
percpu refcnt of cgroup root.

v2:
- we should try to get both the superblock refcnt and cgroup_root refcnt,
  because cgroup_root may have no superblock assosiated with it.
- adjust/add comments.

tj: Updated comments.  Renamed @sb to @pinned_sb.

Signed-off-by: Li Zefan <lizefan@huawei.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
[lizf: Backported to 3.15:
 - Adjust context
 - s/percpu_tryget_live/atomic_inc_not_zero/]
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
kernel/cgroup.c