diff options
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/mm/memory.c b/mm/memory.c index 02fc6b1047b0..262e3eb6601a 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -998,19 +998,24 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address, | |||
998 | goto no_page_table; | 998 | goto no_page_table; |
999 | 999 | ||
1000 | pud = pud_offset(pgd, address); | 1000 | pud = pud_offset(pgd, address); |
1001 | if (pud_none(*pud) || unlikely(pud_bad(*pud))) | 1001 | if (pud_none(*pud)) |
1002 | goto no_page_table; | ||
1003 | if (pud_huge(*pud)) { | ||
1004 | BUG_ON(flags & FOLL_GET); | ||
1005 | page = follow_huge_pud(mm, address, pud, flags & FOLL_WRITE); | ||
1006 | goto out; | ||
1007 | } | ||
1008 | if (unlikely(pud_bad(*pud))) | ||
1002 | goto no_page_table; | 1009 | goto no_page_table; |
1003 | 1010 | ||
1004 | pmd = pmd_offset(pud, address); | 1011 | pmd = pmd_offset(pud, address); |
1005 | if (pmd_none(*pmd)) | 1012 | if (pmd_none(*pmd)) |
1006 | goto no_page_table; | 1013 | goto no_page_table; |
1007 | |||
1008 | if (pmd_huge(*pmd)) { | 1014 | if (pmd_huge(*pmd)) { |
1009 | BUG_ON(flags & FOLL_GET); | 1015 | BUG_ON(flags & FOLL_GET); |
1010 | page = follow_huge_pmd(mm, address, pmd, flags & FOLL_WRITE); | 1016 | page = follow_huge_pmd(mm, address, pmd, flags & FOLL_WRITE); |
1011 | goto out; | 1017 | goto out; |
1012 | } | 1018 | } |
1013 | |||
1014 | if (unlikely(pmd_bad(*pmd))) | 1019 | if (unlikely(pmd_bad(*pmd))) |
1015 | goto no_page_table; | 1020 | goto no_page_table; |
1016 | 1021 | ||
@@ -1567,6 +1572,8 @@ static int apply_to_pmd_range(struct mm_struct *mm, pud_t *pud, | |||
1567 | unsigned long next; | 1572 | unsigned long next; |
1568 | int err; | 1573 | int err; |
1569 | 1574 | ||
1575 | BUG_ON(pud_huge(*pud)); | ||
1576 | |||
1570 | pmd = pmd_alloc(mm, pud, addr); | 1577 | pmd = pmd_alloc(mm, pud, addr); |
1571 | if (!pmd) | 1578 | if (!pmd) |
1572 | return -ENOMEM; | 1579 | return -ENOMEM; |