Skip to content

Commit efdb672

Browse files
Hugh Dickinstorvalds
authored andcommitted
mm/rmap: fix munlocking Anon THP with mlocked ptes
Many thanks to Kirill for reminding that PageDoubleMap cannot be relied on to warn of pte mappings in the Anon THP case; and a scan of subpages does not seem appropriate here. Note how follow_trans_huge_pmd() does not even mark an Anon THP as mlocked when compound_mapcount != 1: multiple mlocking of Anon THP is avoided, so simply return from page_mlock() in this case. Link: https://lore.kernel.org/lkml/cfa154c-d595-406-eb7d-eb9df730f944@google.com/ Fixes: d9770fc ("mm/rmap: fix old bug: munlocking THP missed other mlocks") Reported-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Signed-off-by: Hugh Dickins <hughd@google.com> Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Alistair Popple <apopple@nvidia.com> Cc: Jason Gunthorpe <jgg@nvidia.com> Cc: Ralph Campbell <rcampbell@nvidia.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Yang Shi <shy828301@gmail.com> Cc: Shakeel Butt <shakeelb@google.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent e73f0f0 commit efdb672

1 file changed

Lines changed: 22 additions & 17 deletions

File tree

mm/rmap.c

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,21 +1440,20 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
14401440
/*
14411441
* If the page is mlock()d, we cannot swap it out.
14421442
*/
1443-
if (!(flags & TTU_IGNORE_MLOCK)) {
1444-
if (vma->vm_flags & VM_LOCKED) {
1445-
/* PTE-mapped THP are never marked as mlocked */
1446-
if (!PageTransCompound(page) ||
1447-
(PageHead(page) && !PageDoubleMap(page))) {
1448-
/*
1449-
* Holding pte lock, we do *not* need
1450-
* mmap_lock here
1451-
*/
1452-
mlock_vma_page(page);
1453-
}
1454-
ret = false;
1455-
page_vma_mapped_walk_done(&pvmw);
1456-
break;
1457-
}
1443+
if (!(flags & TTU_IGNORE_MLOCK) &&
1444+
(vma->vm_flags & VM_LOCKED)) {
1445+
/*
1446+
* PTE-mapped THP are never marked as mlocked: so do
1447+
* not set it on a DoubleMap THP, nor on an Anon THP
1448+
* (which may still be PTE-mapped after DoubleMap was
1449+
* cleared). But stop unmapping even in those cases.
1450+
*/
1451+
if (!PageTransCompound(page) || (PageHead(page) &&
1452+
!PageDoubleMap(page) && !PageAnon(page)))
1453+
mlock_vma_page(page);
1454+
page_vma_mapped_walk_done(&pvmw);
1455+
ret = false;
1456+
break;
14581457
}
14591458

14601459
/* Unexpected PMD-mapped THP? */
@@ -1986,8 +1985,10 @@ static bool page_mlock_one(struct page *page, struct vm_area_struct *vma,
19861985
*/
19871986
if (vma->vm_flags & VM_LOCKED) {
19881987
/*
1989-
* PTE-mapped THP are never marked as mlocked, but
1990-
* this function is never called when PageDoubleMap().
1988+
* PTE-mapped THP are never marked as mlocked; but
1989+
* this function is never called on a DoubleMap THP,
1990+
* nor on an Anon THP (which may still be PTE-mapped
1991+
* after DoubleMap was cleared).
19911992
*/
19921993
mlock_vma_page(page);
19931994
/*
@@ -2022,6 +2023,10 @@ void page_mlock(struct page *page)
20222023
VM_BUG_ON_PAGE(!PageLocked(page) || PageLRU(page), page);
20232024
VM_BUG_ON_PAGE(PageCompound(page) && PageDoubleMap(page), page);
20242025

2026+
/* Anon THP are only marked as mlocked when singly mapped */
2027+
if (PageTransCompound(page) && PageAnon(page))
2028+
return;
2029+
20252030
rmap_walk(page, &rwc);
20262031
}
20272032

0 commit comments

Comments
 (0)