Patch "thp: fix another corner case of munlock() vs. THPs" has been added to the 4.10-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
thp: fix another corner case of munlock() vs. THPs
to the 4.10-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
thp-fix-another-corner-case-of-munlock-vs.-thps.patch
and it can be found in the queue-4.10 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
6ebb4a1b848fe75323135f93e72c78f8780fd268Mon Sep 17 00:00:00 2001
From: "Kirill A. Shutemov" <[email protected]>
Date: Thu, 9 Mar 2017 16:17:23 -0800
Subject: thp: fix another corner case of munlock() vs. THPs
From: Kirill A. Shutemov <[email protected]>
commit 6ebb4a1b848fe75323135f93e72c78f8780fd268 upstream.
The following test case triggers BUG() in munlock_vma_pages_range():
int main(int argc, char *argv[])
{
int fd;
system("mount -t tmpfs -o huge=always none /mnt");
fd = open("/mnt/test", O_CREAT | O_RDWR);
ftruncate(fd, 4UL << 20);
mmap(NULL, 4UL << 20, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_FIXED | MAP_LOCKED, fd, 0);
mmap(NULL, 4096, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_LOCKED, fd, 0);
munlockall();
return 0;
}The second mmap() create PTE-mapping of the first huge page in file. It makes kernel munlock the page as we never keep PTE-mapped page mlocked.
On munlockall() when we handle vma created by the first mmap(), munlock_vma_page() returns page_mask == 0, as the page is not mlocked anymore. On next iteration follow_page_mask() return tail page, but page_mask is HPAGE_NR_PAGES - 1. It makes us skip to the first tail page of the next huge page and step on VM_BUG_ON_PAGE(PageMlocked(page)).
The fix is not use the page_mask from follow_page_mask() at all. It has no use for us.
--- mm/mlock.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
mm/mlock.c +4 -5
@@ -441,7 +441,7 @@ void munlock_vma_pages_range(struct vm_awhile (start < end) {struct page *page; -unsigned int page_mask; +unsigned int page_mask =0 ;unsigned long page_increm;struct pagevec pvec;struct zone *zone;
@@ -455,8 +455,7 @@ void munlock_vma_pages_range(struct vm_a* suits munlock very well (and if somehow an abnormal page * has sneaked into the range, we won't oops here: great). */ - page =follow_page_mask (vma, start,FOLL_GET |FOLL_DUMP , - &page_mask); + page =follow_page (vma, start,FOLL_GET |FOLL_DUMP );if (page && !IS_ERR (page)) {if (PageTransTail (page)) {
@@ -467,8 +466,8 @@ void munlock_vma_pages_range(struct vm_a/* * Any THP page found by follow_page_mask() may * have gotten split before reaching -* munlock_vma_page(), so we need to recompute -* the page_mask here. +* munlock_vma_page(), so we need to compute +* the page_mask here instead. */ page_mask =munlock_vma_page (page);unlock_page (page);
Patches currently in stable-queue which might be from [email protected] are
queue-4.10/thp-fix-another-corner-case-of-munlock-vs.-thps.patch