aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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))