diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2008-07-18 15:55:49 +1000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-08-01 11:51:01 -0700 |
commit | 482780d80ba2ab6e6bcbb4ec2bf868d2f9bd4628 (patch) | |
tree | 25fcca7c0613f132d0d7affe435cce3fb597c8a6 /include | |
parent | 620f2f722008f4cb95d7e2282aafc89253119627 (diff) |
Correct hash flushing from huge_ptep_set_wrprotect()
Correct hash flushing from huge_ptep_set_wrprotect() [stable tree version]
A fix for incorrect flushing of the hash page table at fork() for
hugepages was recently committed as
86df86424939d316b1f6cfac1b6204f0c7dee317. Without this fix, a process
can make a MAP_PRIVATE hugepage mapping, then fork() and have writes
to the mapping after the fork() pollute the child's version.
Unfortunately this bug also exists in the stable branch. In fact in
that case copy_hugetlb_page_range() from mm/hugetlb.c calls
ptep_set_wrprotect() directly, the hugepage variant hook
huge_ptep_set_wrprotect() doesn't even exist.
The patch below is a port of the fix to the stable25/master branch.
It introduces a huge_ptep_set_wrprotect() call, but this is #defined
to be equal to ptep_set_wrprotect() unless the arch defines its own
version and sets __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT.
This arch preprocessor flag is kind of nasty, but it seems the sanest
way to introduce this fix with minimum risk of breaking other archs
for whom prep_set_wprotect() is suitable for hugepages.
Signed-off-by: Andy Whitcroft <apw@shadowen.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-powerpc/pgtable-ppc64.h | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/include/asm-powerpc/pgtable-ppc64.h b/include/asm-powerpc/pgtable-ppc64.h index dd4c26dc57d..8e35c28462a 100644 --- a/include/asm-powerpc/pgtable-ppc64.h +++ b/include/asm-powerpc/pgtable-ppc64.h @@ -311,6 +311,17 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, old = pte_update(mm, addr, ptep, _PAGE_RW, 0); } +#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT +static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) +{ + unsigned long old; + + if ((pte_val(*ptep) & _PAGE_RW) == 0) + return; + old = pte_update(mm, addr, ptep, _PAGE_RW, 1); +} + /* * We currently remove entries from the hashtable regardless of whether * the entry was young or dirty. The generic routines only flush if the |