• Li Zefan's avatar
    cgroup: fix a race between cgroup_mount() and cgroup_kill_sb() · 3a32bd72
    Li Zefan authored
    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.
    
    Cc: <stable@vger.kernel.org> # 3.15
    Signed-off-by: default avatarLi Zefan <lizefan@huawei.com>
    Signed-off-by: default avatarTejun Heo <tj@kernel.org>
    3a32bd72
cgroup.c 145 KB