aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAndrea Arcangeli <aarcange@redhat.com>2011-01-13 18:46:42 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 20:32:40 -0500
commit64cc6ae001d70bc59e5f854e6b5678f59110df16 (patch)
tree929358dabd522330ea145755ab0d0d7d27ac85b3 /arch
parentdb3eb96f4e6281b84dd33c8980dacc27f2efe177 (diff)
thp: bail out gup_fast on splitting pmd
Force gup_fast to take the slow path and block if the pmd is splitting, not only if it's none. Signed-off-by: Andrea Arcangeli <aarcange@redhat.com> Acked-by: Rik van Riel <riel@redhat.com> Acked-by: Mel Gorman <mel@csn.ul.ie> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/mm/gup.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c
index 06f56fcf9a77..269aa53932e0 100644
--- a/arch/x86/mm/gup.c
+++ b/arch/x86/mm/gup.c
@@ -160,7 +160,18 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
160 pmd_t pmd = *pmdp; 160 pmd_t pmd = *pmdp;
161 161
162 next = pmd_addr_end(addr, end); 162 next = pmd_addr_end(addr, end);
163 if (pmd_none(pmd)) 163 /*
164 * The pmd_trans_splitting() check below explains why
165 * pmdp_splitting_flush has to flush the tlb, to stop
166 * this gup-fast code from running while we set the
167 * splitting bit in the pmd. Returning zero will take
168 * the slow path that will call wait_split_huge_page()
169 * if the pmd is still in splitting state. gup-fast
170 * can't because it has irq disabled and
171 * wait_split_huge_page() would never return as the
172 * tlb flush IPI wouldn't run.
173 */
174 if (pmd_none(pmd) || pmd_trans_splitting(pmd))
164 return 0; 175 return 0;
165 if (unlikely(pmd_large(pmd))) { 176 if (unlikely(pmd_large(pmd))) {
166 if (!gup_huge_pmd(pmd, addr, next, write, pages, nr)) 177 if (!gup_huge_pmd(pmd, addr, next, write, pages, nr))