diff options
author | Steven Rostedt <srostedt@redhat.com> | 2012-07-06 17:42:32 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2012-07-06 17:42:32 -0400 |
commit | ec8e11d4d67de07e87deed27d59b0fad105853fe (patch) | |
tree | 0a161560b99142c86b46c7ce74c4f96a24ad2d1e /include/asm-generic | |
parent | 0d2f57e8256e6fc4e4d4d9c28f97eff81274fbc9 (diff) | |
parent | 1990855918045c6bd2c8b7ad62917d141eed4332 (diff) |
Merge tag 'v3.2.22' into v3.2-rt
This is the 3.2.22 stable release
Diffstat (limited to 'include/asm-generic')
-rw-r--r-- | include/asm-generic/pgtable.h | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index a03c098b0cce..bc008761cb6c 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -445,6 +445,18 @@ static inline int pmd_write(pmd_t pmd) #endif /* __HAVE_ARCH_PMD_WRITE */ #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ +#ifndef pmd_read_atomic +static inline pmd_t pmd_read_atomic(pmd_t *pmdp) +{ + /* + * Depend on compiler for an atomic pmd read. NOTE: this is + * only going to work, if the pmdval_t isn't larger than + * an unsigned long. + */ + return *pmdp; +} +#endif + /* * This function is meant to be used by sites walking pagetables with * the mmap_sem hold in read mode to protect against MADV_DONTNEED and @@ -458,14 +470,30 @@ static inline int pmd_write(pmd_t pmd) * undefined so behaving like if the pmd was none is safe (because it * can return none anyway). The compiler level barrier() is critically * important to compute the two checks atomically on the same pmdval. + * + * For 32bit kernels with a 64bit large pmd_t this automatically takes + * care of reading the pmd atomically to avoid SMP race conditions + * against pmd_populate() when the mmap_sem is hold for reading by the + * caller (a special atomic read not done by "gcc" as in the generic + * version above, is also needed when THP is disabled because the page + * fault can populate the pmd from under us). */ static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) { - /* depend on compiler for an atomic pmd read */ - pmd_t pmdval = *pmd; + pmd_t pmdval = pmd_read_atomic(pmd); /* * The barrier will stabilize the pmdval in a register or on * the stack so that it will stop changing under the code. + * + * When CONFIG_TRANSPARENT_HUGEPAGE=y on x86 32bit PAE, + * pmd_read_atomic is allowed to return a not atomic pmdval + * (for example pointing to an hugepage that has never been + * mapped in the pmd). The below checks will only care about + * the low part of the pmd with 32bit PAE x86 anyway, with the + * exception of pmd_none(). So the important thing is that if + * the low part of the pmd is found null, the high part will + * be also null or the pmd_none() check below would be + * confused. */ #ifdef CONFIG_TRANSPARENT_HUGEPAGE barrier(); |