Skip to content
  • Naoya Horiguchi's avatar
    mm: hugetlb: fix hugepage memory leak in mincore() · 4f16fc10
    Naoya Horiguchi authored
    
    
    Most callers of pmd_none_or_clear_bad() check whether the target page is
    in a hugepage or not, but mincore() and walk_page_range() do not check it.
     So if we use mincore() on a hugepage on x86 machine, the hugepage memory
    is leaked as shown below.  This patch fixes it by extending mincore()
    system call to support hugepages.
    
    Details
    =======
    My test program (leak_mincore) works as follows:
     - creat() and mmap() a file on hugetlbfs (file size is 200MB == 100 hugepages,)
     - read()/write() something on it,
     - call mincore() for first ten pages and printf() the values of *vec
     - munmap() and unlink() the file on hugetlbfs
    
    Without my patch
    ----------------
    $ cat /proc/meminfo| grep "HugePage"
    HugePages_Total:    1000
    HugePages_Free:     1000
    HugePages_Rsvd:        0
    HugePages_Surp:        0
    $ ./leak_mincore
    vec[0] 0
    vec[1] 0
    vec[2] 0
    vec[3] 0
    vec[4] 0
    vec[5] 0
    vec[6] 0
    vec[7] 0
    vec[8] 0
    vec[9] 0
    $ cat /proc/meminfo |grep "HugePage"
    HugePages_Total:    1000
    HugePages_Free:      999
    HugePages_Rsvd:        0
    HugePages_Surp:        0
    $ ls /hugetlbfs/
    $
    
    Return values in *vec from mincore() are set to 0, while the hugepage
    should be in memory, and 1 hugepage is still accounted as used while
    there is no file on hugetlbfs.
    
    With my patch
    -------------
    $ cat /proc/meminfo| grep "HugePage"
    HugePages_Total:    1000
    HugePages_Free:     1000
    HugePages_Rsvd:        0
    HugePages_Surp:        0
    $ ./leak_mincore
    vec[0] 1
    vec[1] 1
    vec[2] 1
    vec[3] 1
    vec[4] 1
    vec[5] 1
    vec[6] 1
    vec[7] 1
    vec[8] 1
    vec[9] 1
    $ cat /proc/meminfo |grep "HugePage"
    HugePages_Total:    1000
    HugePages_Free:     1000
    HugePages_Rsvd:        0
    HugePages_Surp:        0
    $ ls /hugetlbfs/
    $
    
    Return value in *vec set to 1 and no memory leaks.
    
    [akpm@linux-foundation.org: cleanup]
    [akpm@linux-foundation.org: build fix]
    Signed-off-by: default avatarNaoya Horiguchi <n-horiguchi@ah.jp.nec.com>
    Cc: Andi Kleen <ak@linux.intel.com>
    Cc: Wu Fengguang <fengguang.wu@intel.com>
    Cc: Hugh Dickins <hugh.dickins@tiscali.co.uk>
    Cc: Mel Gorman <mel@csn.ul.ie>
    Cc: Lee Schermerhorn <lee.schermerhorn@hp.com>
    Cc: Andy Whitcroft <apw@canonical.com>
    Cc: David Rientjes <rientjes@google.com>
    Cc: <stable@kernel.org>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    4f16fc10