• Miaohe Lin's avatar
    hugetlb_cgroup: fix imbalanced css_get and css_put pair for shared mappings · d85aecf2
    Miaohe Lin authored
    The current implementation of hugetlb_cgroup for shared mappings could
    have different behavior.  Consider the following two scenarios:
    
     1.Assume initial css reference count of hugetlb_cgroup is 1:
      1.1 Call hugetlb_reserve_pages with from = 1, to = 2. So css reference
          count is 2 associated with 1 file_region.
      1.2 Call hugetlb_reserve_pages with from = 2, to = 3. So css reference
          count is 3 associated with 2 file_region.
      1.3 coalesce_file_region will coalesce these two file_regions into
          one. So css reference count is 3 associated with 1 file_region
          now.
    
     2.Assume initial css reference count of hugetlb_cgroup is 1 again:
      2.1 Call hugetlb_reserve_pages with from = 1, to = 3. So css reference
          count is 2 associated with 1 file_region.
    
    Therefore, we might have one file_region while holding one or more css
    reference counts. This inconsistency could lead to imbalanced css_get()
    and css_put() pair. If we do css_put one by one (i.g. hole punch case),
    scenario 2 would put one more css reference. If we do css_put all
    together (i.g. truncate case), scenario 1 will leak one css reference.
    
    The imbalanced css_get() and css_put() pair would result in a non-zero
    reference when we try to destroy the hugetlb cgroup. The hugetlb cgroup
    directory is removed __but__ associated resource is not freed. This
    might result in OOM or can not create a new hugetlb cgroup in a busy
    workload ultimately.
    
    In order to fix this, we have to make sure that one file_region must
    hold exactly one css reference. So in coalesce_file_region case, we
    should release one css reference before coalescence. Also only put css
    reference when the entire file_region is removed.
    
    The last thing to note is that the caller of region_add() will only hold
    one reference to h_cg->css for the whole contiguous reservation region.
    But this area might be scattered when there are already some
    file_regions reside in it. As a result, many file_regions may share only
    one h_cg->css reference. In order to ensure that one file_region must
    hold exactly one css reference, we should do css_get() for each
    file_region and release the reference held by caller when they are done.
    
    [linmiaohe@huawei.com: fix imbalanced css_get and css_put pair for shared mappings]
      Link: https://lkml.kernel.org/r/20210316023002.53921-1-linmiaohe@huawei.com
    
    Link: https://lkml.kernel.org/r/20210301120540.37076-1-linmiaohe@huawei.com
    Fixes: 075a61d0 ("hugetlb_cgroup: add accounting for shared mappings")
    Reported-by: kernel test robot <lkp@intel.com> (auto build test ERROR)
    Signed-off-by: default avatarMiaohe Lin <linmiaohe@huawei.com>
    Reviewed-by: default avatarMike Kravetz <mike.kravetz@oracle.com>
    Cc: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
    Cc: Wanpeng Li <liwp.linux@gmail.com>
    Cc: Mina Almasry <almasrymina@google.com>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    d85aecf2
hugetlb_cgroup.c 21.5 KB