History

mm, thp: fix mlocking THP page with migration enabled

A transparent huge page is represented by a single entry on an LRU list. Therefore, we can only make unevictable an entire compound page, not individual subpages. If a user tries to mlock() part of a huge page, we want the rest of the page to be reclaimable. We handle this by keeping PTE-mapped huge pages on normal LRU lists: the PMD on border of VM_LOCKED VMA will be split into PTE table. Introduction of THP migration breaks[1] the rules around mlocking THP pages. If we had a single PMD mapping of the page in mlocked VMA, the page will get mlocked, regardless of PTE mappings of the page. For tmpfs/shmem it's easy to fix by checking PageDoubleMap() in remove_migration_pmd(). Anon THP pages can only be shared between processes via fork(). Mlocked page can only be shared if parent mlocked it before forking, otherwise CoW will be triggered on mlock(). For Anon-THP, we can fix the issue by munlocking the page on removing PTE migration entry for the page. PTEs for the page will always come after mlocked PMD: rmap walks VMAs from oldest to newest. Test-case: #include <unistd.h> #include <sys/mman.h> #include <sys/wait.h> #include <linux/mempolicy.h> #include <numaif.h> int main(void) { unsigned long nodemask = 4; void *addr; addr = mmap((void *)0x20000000UL, 2UL << 20, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_LOCKED, -1, 0); if (fork()) { wait(NULL); return 0; } mlock(addr, 4UL << 10); mbind(addr, 2UL << 20, MPOL_PREFERRED | MPOL_F_RELATIVE_NODES, &nodemask, 4, MPOL_MF_MOVE); return 0; } [1] https://lkml.kernel.org/r/CAOMGZ=G52R-30rZvhGxEbkTw7rLLwBGadVYeo--iizcD3upL3A@mail.gmail.com

Kirill A. Shutemov committed 8 years ago

Commit e125fe41 parent 69eb7762 files · +4 −1Browse files

Unified · Split

2 files
  1. mm/huge_memory.c +1 −1
  2. mm/migrate.c +3 −0
mm/huge_memory.c+1−1
@@ -2931,7 +2931,7 @@ void remove_migration_pmd(struct page_vma_mapped_walk *pvmw, struct page *new) · 2930 unmodified lines
2931 else2931 else
2932 page_add_file_rmap(new, true);2932 page_add_file_rmap(new, true);
2933 set_pmd_at(mm, mmun_start, pvmw->pmd, pmde);2933 set_pmd_at(mm, mmun_start, pvmw->pmd, pmde);
2934 if (vma->vm_flags & VM_LOCKED)2934 if ((vma->vm_flags & VM_LOCKED) && !PageDoubleMap(new))
2935 mlock_vma_page(new);2935 mlock_vma_page(new);
2936 update_mmu_cache_pmd(vma, address, pvmw->pmd);2936 update_mmu_cache_pmd(vma, address, pvmw->pmd);
2937}2937}
mm/migrate.c+3−0
@@ -275,6 +275,9 @@ static bool remove_migration_pte(struct page *page, struct vm_area_struct *vma, · 274 unmodified lines
275 if (vma->vm_flags & VM_LOCKED && !PageTransCompound(new))275 if (vma->vm_flags & VM_LOCKED && !PageTransCompound(new))
276 mlock_vma_page(new);276 mlock_vma_page(new);
277 277
278 if (PageTransHuge(page) && PageMlocked(page))
279 clear_page_mlock(page);
280
278 /* No need to invalidate - it was non-present before */281 /* No need to invalidate - it was non-present before */
279 update_mmu_cache(vma, pvmw.address, pvmw.pte);282 update_mmu_cache(vma, pvmw.address, pvmw.pte);
280 }283 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t