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/[email protected]/ Fixes: d9770fc ("mm/rmap: fix old bug: munlocking THP missed other mlocks") Reported-by: Kirill A. Shutemov <[email protected]> Signed-off-by: Hugh Dickins <[email protected]> Acked-by: Kirill A. Shutemov <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Alistair Popple <[email protected]> Cc: Jason Gunthorpe <[email protected]> Cc: Ralph Campbell <[email protected]> Cc: Christoph Hellwig <[email protected]> Cc: Yang Shi <[email protected]> Cc: Shakeel Butt <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent e73f0f0 commit efdb672

File tree

1 file changed

+22
-17
lines changed

1 file changed

+22
-17
lines changed

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)