Skip to content

Commit

Permalink
mm/rmap: fix munlocking Anon THP with mlocked ptes
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Hugh Dickins authored and Linus Torvalds committed Jul 12, 2021
1 parent e73f0f0 commit efdb672
Showing 1 changed file with 22 additions and 17 deletions.
39 changes: 22 additions & 17 deletions mm/rmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1440,21 +1440,20 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
/*
* If the page is mlock()d, we cannot swap it out.
*/
if (!(flags & TTU_IGNORE_MLOCK)) {
if (vma->vm_flags & VM_LOCKED) {
/* PTE-mapped THP are never marked as mlocked */
if (!PageTransCompound(page) ||
(PageHead(page) && !PageDoubleMap(page))) {
/*
* Holding pte lock, we do *not* need
* mmap_lock here
*/
mlock_vma_page(page);
}
ret = false;
page_vma_mapped_walk_done(&pvmw);
break;
}
if (!(flags & TTU_IGNORE_MLOCK) &&
(vma->vm_flags & VM_LOCKED)) {
/*
* PTE-mapped THP are never marked as mlocked: so do
* not set it on a DoubleMap THP, nor on an Anon THP
* (which may still be PTE-mapped after DoubleMap was
* cleared). But stop unmapping even in those cases.
*/
if (!PageTransCompound(page) || (PageHead(page) &&
!PageDoubleMap(page) && !PageAnon(page)))
mlock_vma_page(page);
page_vma_mapped_walk_done(&pvmw);
ret = false;
break;
}

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

/* Anon THP are only marked as mlocked when singly mapped */
if (PageTransCompound(page) && PageAnon(page))
return;

rmap_walk(page, &rwc);
}

Expand Down

0 comments on commit efdb672

Please sign in to comment.