Skip to content
  • Mike Kravetz's avatar
    hugetlb: use same fault hash key for shared and private mappings · c20f6d01
    Mike Kravetz authored
    commit 1b426bac upstream.
    
    hugetlb uses a fault mutex hash table to prevent page faults of the
    same pages concurrently.  The key for shared and private mappings is
    different.  Shared keys off address_space and file index.  Private keys
    off mm and virtual address.  Consider a private mappings of a populated
    hugetlbfs file.  A fault will map the page from the file and if needed
    do a COW to map a writable page.
    
    Hugetlbfs hole punch uses the fault mutex to prevent mappings of file
    pages.  It uses the address_space file index key.  However, private
    mappings will use a different key and could race with this code to map
    the file page.  This causes problems (BUG) for the page cache remove
    code as it expects the page to be unmapped.  A sample stack is:
    
    page dumped because: VM_BUG_ON_PAGE(page_mapped(page))
    kernel BUG at mm/filemap.c:169!
    ...
    RIP: 0010:unaccount_page_cache_page+0x1b8/0x200
    ...
    Call Trace:
    __delete_from_page_cache+0x39/0x220
    delete_from_page_cache+0x45/0x70
    remove_inode_hugepages+0x13c/0x380
    ? __add_to_page_cache_locked+0x162/0x380
    hugetlbfs_fallocate+0x403/0x540
    ? _cond_resched+0x15/0x30
    ? __inode_security_revalidate+0x5d/0x70
    ? selinux_file_permission+0x100/0x130
    vfs_fallocate+0x13f/0x270
    ksys_fallocate+0x3c/0x80
    __x64_sys_fallocate+0x1a/0x20
    do_syscall_64+0x5b/0x180
    entry_SYSCALL_64_after_hwframe+0x44/0xa9
    
    There seems to be another potential COW issue/race with this approach
    of different private and shared keys as noted in commit 8382d914
    ("mm, hugetlb: improve page-fault scalability").
    
    Since every hugetlb mapping (even anon and private) is actually a file
    mapping, just use the address_space index key for all mappings.  This
    results in potentially more hash collisions.  However, this should not
    be the common case.
    
    Link: http://lkml.kernel.org/r/20190328234704.27083-3-mike.kravetz@oracle.com
    Link: http://lkml.kernel.org/r/20190412165235.t4sscoujczfhuiyt@linux-r8p5
    Fixes: b5cec28d
    
     ("hugetlbfs: truncate_hugepages() takes a range of pages")
    Signed-off-by: default avatarMike Kravetz <mike.kravetz@oracle.com>
    Reviewed-by: default avatarNaoya Horiguchi <n-horiguchi@ah.jp.nec.com>
    Reviewed-by: default avatarDavidlohr Bueso <dbueso@suse.de>
    Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
    Cc: "Kirill A . Shutemov" <kirill.shutemov@linux.intel.com>
    Cc: Michal Hocko <mhocko@kernel.org>
    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>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    c20f6d01