]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.18.14/mm-thp-fix-mlocking-thp-page-with-migration-enabled.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.18.14 / mm-thp-fix-mlocking-thp-page-with-migration-enabled.patch
CommitLineData
7c34048e
GKH
1From e125fe405abedc1dc8a5b2229b80ee91c1434015 Mon Sep 17 00:00:00 2001
2From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
3Date: Fri, 5 Oct 2018 15:51:41 -0700
4Subject: mm, thp: fix mlocking THP page with migration enabled
5
6From: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
7
8commit e125fe405abedc1dc8a5b2229b80ee91c1434015 upstream.
9
10A transparent huge page is represented by a single entry on an LRU list.
11Therefore, we can only make unevictable an entire compound page, not
12individual subpages.
13
14If a user tries to mlock() part of a huge page, we want the rest of the
15page to be reclaimable.
16
17We handle this by keeping PTE-mapped huge pages on normal LRU lists: the
18PMD on border of VM_LOCKED VMA will be split into PTE table.
19
20Introduction of THP migration breaks[1] the rules around mlocking THP
21pages. If we had a single PMD mapping of the page in mlocked VMA, the
22page will get mlocked, regardless of PTE mappings of the page.
23
24For tmpfs/shmem it's easy to fix by checking PageDoubleMap() in
25remove_migration_pmd().
26
27Anon THP pages can only be shared between processes via fork(). Mlocked
28page can only be shared if parent mlocked it before forking, otherwise CoW
29will be triggered on mlock().
30
31For Anon-THP, we can fix the issue by munlocking the page on removing PTE
32migration entry for the page. PTEs for the page will always come after
33mlocked PMD: rmap walks VMAs from oldest to newest.
34
35Test-case:
36
37 #include <unistd.h>
38 #include <sys/mman.h>
39 #include <sys/wait.h>
40 #include <linux/mempolicy.h>
41 #include <numaif.h>
42
43 int main(void)
44 {
45 unsigned long nodemask = 4;
46 void *addr;
47
48 addr = mmap((void *)0x20000000UL, 2UL << 20, PROT_READ | PROT_WRITE,
49 MAP_PRIVATE | MAP_ANONYMOUS | MAP_LOCKED, -1, 0);
50
51 if (fork()) {
52 wait(NULL);
53 return 0;
54 }
55
56 mlock(addr, 4UL << 10);
57 mbind(addr, 2UL << 20, MPOL_PREFERRED | MPOL_F_RELATIVE_NODES,
58 &nodemask, 4, MPOL_MF_MOVE);
59
60 return 0;
61 }
62
63[1] https://lkml.kernel.org/r/CAOMGZ=G52R-30rZvhGxEbkTw7rLLwBGadVYeo--iizcD3upL3A@mail.gmail.com
64
65Link: http://lkml.kernel.org/r/20180917133816.43995-1-kirill.shutemov@linux.intel.com
66Fixes: 616b8371539a ("mm: thp: enable thp migration in generic path")
67Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
68Reported-by: Vegard Nossum <vegard.nossum@oracle.com>
69Reviewed-by: Zi Yan <zi.yan@cs.rutgers.edu>
70Cc: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
71Cc: Vlastimil Babka <vbabka@suse.cz>
72Cc: Andrea Arcangeli <aarcange@redhat.com>
73Cc: <stable@vger.kernel.org> [4.14+]
74Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
75Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
76
77---
78 mm/huge_memory.c | 2 +-
79 mm/migrate.c | 3 +++
80 2 files changed, 4 insertions(+), 1 deletion(-)
81
82--- a/mm/huge_memory.c
83+++ b/mm/huge_memory.c
84@@ -2929,7 +2929,7 @@ void remove_migration_pmd(struct page_vm
85 else
86 page_add_file_rmap(new, true);
87 set_pmd_at(mm, mmun_start, pvmw->pmd, pmde);
88- if (vma->vm_flags & VM_LOCKED)
89+ if ((vma->vm_flags & VM_LOCKED) && !PageDoubleMap(new))
90 mlock_vma_page(new);
91 update_mmu_cache_pmd(vma, address, pvmw->pmd);
92 }
93--- a/mm/migrate.c
94+++ b/mm/migrate.c
95@@ -275,6 +275,9 @@ static bool remove_migration_pte(struct
96 if (vma->vm_flags & VM_LOCKED && !PageTransCompound(new))
97 mlock_vma_page(new);
98
99+ if (PageTransHuge(page) && PageMlocked(page))
100+ clear_page_mlock(page);
101+
102 /* No need to invalidate - it was non-present before */
103 update_mmu_cache(vma, pvmw.address, pvmw.pte);
104 }