Skip to content

Commit

Permalink
x86: ignore VM_LOCKED when determining if hugetlb-backed page tables …
Browse files Browse the repository at this point in the history
…can be shared or not

Addresses http://bugzilla.kernel.org/show_bug.cgi?id=13302

On x86 and x86-64, it is possible that page tables are shared beween
shared mappings backed by hugetlbfs.  As part of this,
page_table_shareable() checks a pair of vma->vm_flags and they must match
if they are to be shared.  All VMA flags are taken into account, including
VM_LOCKED.

The problem is that VM_LOCKED is cleared on fork().  When a process with a
shared memory segment forks() to exec() a helper, there will be shared
VMAs with different flags.  The impact is that the shared segment is
sometimes considered shareable and other times not, depending on what
process is checking.

What happens is that the segment page tables are being shared but the
count is inaccurate depending on the ordering of events.  As the page
tables are freed with put_page(), bad pmd's are found when some of the
children exit.  The hugepage counters also get corrupted and the Total and
Free count will no longer match even when all the hugepage-backed regions
are freed.  This requires a reboot of the machine to "fix".

This patch addresses the problem by comparing all flags except VM_LOCKED
when deciding if pagetables should be shared or not for hugetlbfs-backed
mapping.

Signed-off-by: Mel Gorman <[email protected]>
Acked-by: Hugh Dickins <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: <[email protected]>
Cc: Lee Schermerhorn <[email protected]>
Cc: KOSAKI Motohiro <[email protected]>
Cc: <[email protected]>
Cc: Eric B Munson <[email protected]>
Cc: Adam Litke <[email protected]>
Cc: Andy Whitcroft <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
gormanm authored and torvalds committed May 29, 2009
1 parent 53b7479 commit 32b154c
Showing 1 changed file with 5 additions and 1 deletion.
6 changes: 5 additions & 1 deletion arch/x86/mm/hugetlbpage.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@ static unsigned long page_table_shareable(struct vm_area_struct *svma,
unsigned long sbase = saddr & PUD_MASK;
unsigned long s_end = sbase + PUD_SIZE;

/* Allow segments to share if only one is marked locked */
unsigned long vm_flags = vma->vm_flags & ~VM_LOCKED;
unsigned long svm_flags = svma->vm_flags & ~VM_LOCKED;

/*
* match the virtual addresses, permission and the alignment of the
* page table page.
*/
if (pmd_index(addr) != pmd_index(saddr) ||
vma->vm_flags != svma->vm_flags ||
vm_flags != svm_flags ||
sbase < svma->vm_start || svma->vm_end < s_end)
return 0;

Expand Down

0 comments on commit 32b154c

Please sign in to comment.