diff options
| -rw-r--r-- | arch/arm/mm/pgd.c | 2 | ||||
| -rw-r--r-- | arch/ia64/mm/hugetlbpage.c | 2 | ||||
| -rw-r--r-- | arch/sh/mm/hugetlbpage.c | 2 | ||||
| -rw-r--r-- | arch/sparc/mm/generic_32.c | 2 | ||||
| -rw-r--r-- | arch/sparc/mm/generic_64.c | 2 | ||||
| -rw-r--r-- | arch/sparc/mm/hugetlbpage.c | 2 | ||||
| -rw-r--r-- | arch/um/kernel/skas/mmu.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/tboot.c | 2 | ||||
| -rw-r--r-- | include/linux/mm.h | 15 | ||||
| -rw-r--r-- | mm/memory.c | 19 | ||||
| -rw-r--r-- | mm/mremap.c | 8 |
11 files changed, 35 insertions, 23 deletions
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c index 93292a18cf77..709244c66fa3 100644 --- a/arch/arm/mm/pgd.c +++ b/arch/arm/mm/pgd.c | |||
| @@ -50,7 +50,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm) | |||
| 50 | if (!new_pmd) | 50 | if (!new_pmd) |
| 51 | goto no_pmd; | 51 | goto no_pmd; |
| 52 | 52 | ||
| 53 | new_pte = pte_alloc_map(mm, new_pmd, 0); | 53 | new_pte = pte_alloc_map(mm, NULL, new_pmd, 0); |
| 54 | if (!new_pte) | 54 | if (!new_pte) |
| 55 | goto no_pte; | 55 | goto no_pte; |
| 56 | 56 | ||
diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c index 1841ee7e65f9..5ca674b74737 100644 --- a/arch/ia64/mm/hugetlbpage.c +++ b/arch/ia64/mm/hugetlbpage.c | |||
| @@ -38,7 +38,7 @@ huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz) | |||
| 38 | if (pud) { | 38 | if (pud) { |
| 39 | pmd = pmd_alloc(mm, pud, taddr); | 39 | pmd = pmd_alloc(mm, pud, taddr); |
| 40 | if (pmd) | 40 | if (pmd) |
| 41 | pte = pte_alloc_map(mm, pmd, taddr); | 41 | pte = pte_alloc_map(mm, NULL, pmd, taddr); |
| 42 | } | 42 | } |
| 43 | return pte; | 43 | return pte; |
| 44 | } | 44 | } |
diff --git a/arch/sh/mm/hugetlbpage.c b/arch/sh/mm/hugetlbpage.c index 9163db3e8d15..d7762349ea48 100644 --- a/arch/sh/mm/hugetlbpage.c +++ b/arch/sh/mm/hugetlbpage.c | |||
| @@ -35,7 +35,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, | |||
| 35 | if (pud) { | 35 | if (pud) { |
| 36 | pmd = pmd_alloc(mm, pud, addr); | 36 | pmd = pmd_alloc(mm, pud, addr); |
| 37 | if (pmd) | 37 | if (pmd) |
| 38 | pte = pte_alloc_map(mm, pmd, addr); | 38 | pte = pte_alloc_map(mm, NULL, pmd, addr); |
| 39 | } | 39 | } |
| 40 | } | 40 | } |
| 41 | 41 | ||
diff --git a/arch/sparc/mm/generic_32.c b/arch/sparc/mm/generic_32.c index 5edcac184eaf..e6067b75f11c 100644 --- a/arch/sparc/mm/generic_32.c +++ b/arch/sparc/mm/generic_32.c | |||
| @@ -50,7 +50,7 @@ static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned | |||
| 50 | end = PGDIR_SIZE; | 50 | end = PGDIR_SIZE; |
| 51 | offset -= address; | 51 | offset -= address; |
| 52 | do { | 52 | do { |
| 53 | pte_t * pte = pte_alloc_map(mm, pmd, address); | 53 | pte_t *pte = pte_alloc_map(mm, NULL, pmd, address); |
| 54 | if (!pte) | 54 | if (!pte) |
| 55 | return -ENOMEM; | 55 | return -ENOMEM; |
| 56 | io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space); | 56 | io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space); |
diff --git a/arch/sparc/mm/generic_64.c b/arch/sparc/mm/generic_64.c index 04f2bf4cd571..3cb00dfd4bd6 100644 --- a/arch/sparc/mm/generic_64.c +++ b/arch/sparc/mm/generic_64.c | |||
| @@ -92,7 +92,7 @@ static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned | |||
| 92 | end = PGDIR_SIZE; | 92 | end = PGDIR_SIZE; |
| 93 | offset -= address; | 93 | offset -= address; |
| 94 | do { | 94 | do { |
| 95 | pte_t * pte = pte_alloc_map(mm, pmd, address); | 95 | pte_t *pte = pte_alloc_map(mm, NULL, pmd, address); |
| 96 | if (!pte) | 96 | if (!pte) |
| 97 | return -ENOMEM; | 97 | return -ENOMEM; |
| 98 | io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space); | 98 | io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space); |
diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c index 5fdddf134caa..f4e97646ce23 100644 --- a/arch/sparc/mm/hugetlbpage.c +++ b/arch/sparc/mm/hugetlbpage.c | |||
| @@ -214,7 +214,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, | |||
| 214 | if (pud) { | 214 | if (pud) { |
| 215 | pmd = pmd_alloc(mm, pud, addr); | 215 | pmd = pmd_alloc(mm, pud, addr); |
| 216 | if (pmd) | 216 | if (pmd) |
| 217 | pte = pte_alloc_map(mm, pmd, addr); | 217 | pte = pte_alloc_map(mm, NULL, pmd, addr); |
| 218 | } | 218 | } |
| 219 | return pte; | 219 | return pte; |
| 220 | } | 220 | } |
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 3d099f974785..1aee587e9c5d 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c | |||
| @@ -31,7 +31,7 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, | |||
| 31 | if (!pmd) | 31 | if (!pmd) |
| 32 | goto out_pmd; | 32 | goto out_pmd; |
| 33 | 33 | ||
| 34 | pte = pte_alloc_map(mm, pmd, proc); | 34 | pte = pte_alloc_map(mm, NULL, pmd, proc); |
| 35 | if (!pte) | 35 | if (!pte) |
| 36 | goto out_pte; | 36 | goto out_pte; |
| 37 | 37 | ||
diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c index c2f1b26141e2..998e972f3b1a 100644 --- a/arch/x86/kernel/tboot.c +++ b/arch/x86/kernel/tboot.c | |||
| @@ -133,7 +133,7 @@ static int map_tboot_page(unsigned long vaddr, unsigned long pfn, | |||
| 133 | pmd = pmd_alloc(&tboot_mm, pud, vaddr); | 133 | pmd = pmd_alloc(&tboot_mm, pud, vaddr); |
| 134 | if (!pmd) | 134 | if (!pmd) |
| 135 | return -1; | 135 | return -1; |
| 136 | pte = pte_alloc_map(&tboot_mm, pmd, vaddr); | 136 | pte = pte_alloc_map(&tboot_mm, NULL, pmd, vaddr); |
| 137 | if (!pte) | 137 | if (!pte) |
| 138 | return -1; | 138 | return -1; |
| 139 | set_pte_at(&tboot_mm, vaddr, pte, pfn_pte(pfn, prot)); | 139 | set_pte_at(&tboot_mm, vaddr, pte, pfn_pte(pfn, prot)); |
diff --git a/include/linux/mm.h b/include/linux/mm.h index 6bef67d74adf..14ddd98b063f 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -1131,7 +1131,8 @@ static inline int __pmd_alloc(struct mm_struct *mm, pud_t *pud, | |||
| 1131 | int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address); | 1131 | int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address); |
| 1132 | #endif | 1132 | #endif |
| 1133 | 1133 | ||
| 1134 | int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address); | 1134 | int __pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma, |
| 1135 | pmd_t *pmd, unsigned long address); | ||
| 1135 | int __pte_alloc_kernel(pmd_t *pmd, unsigned long address); | 1136 | int __pte_alloc_kernel(pmd_t *pmd, unsigned long address); |
| 1136 | 1137 | ||
| 1137 | /* | 1138 | /* |
| @@ -1200,16 +1201,18 @@ static inline void pgtable_page_dtor(struct page *page) | |||
| 1200 | pte_unmap(pte); \ | 1201 | pte_unmap(pte); \ |
| 1201 | } while (0) | 1202 | } while (0) |
| 1202 | 1203 | ||
| 1203 | #define pte_alloc_map(mm, pmd, address) \ | 1204 | #define pte_alloc_map(mm, vma, pmd, address) \ |
| 1204 | ((unlikely(!pmd_present(*(pmd))) && __pte_alloc(mm, pmd, address))? \ | 1205 | ((unlikely(pmd_none(*(pmd))) && __pte_alloc(mm, vma, \ |
| 1205 | NULL: pte_offset_map(pmd, address)) | 1206 | pmd, address))? \ |
| 1207 | NULL: pte_offset_map(pmd, address)) | ||
| 1206 | 1208 | ||
| 1207 | #define pte_alloc_map_lock(mm, pmd, address, ptlp) \ | 1209 | #define pte_alloc_map_lock(mm, pmd, address, ptlp) \ |
| 1208 | ((unlikely(!pmd_present(*(pmd))) && __pte_alloc(mm, pmd, address))? \ | 1210 | ((unlikely(pmd_none(*(pmd))) && __pte_alloc(mm, NULL, \ |
| 1211 | pmd, address))? \ | ||
| 1209 | NULL: pte_offset_map_lock(mm, pmd, address, ptlp)) | 1212 | NULL: pte_offset_map_lock(mm, pmd, address, ptlp)) |
| 1210 | 1213 | ||
| 1211 | #define pte_alloc_kernel(pmd, address) \ | 1214 | #define pte_alloc_kernel(pmd, address) \ |
| 1212 | ((unlikely(!pmd_present(*(pmd))) && __pte_alloc_kernel(pmd, address))? \ | 1215 | ((unlikely(pmd_none(*(pmd))) && __pte_alloc_kernel(pmd, address))? \ |
| 1213 | NULL: pte_offset_kernel(pmd, address)) | 1216 | NULL: pte_offset_kernel(pmd, address)) |
| 1214 | 1217 | ||
| 1215 | extern void free_area_init(unsigned long * zones_size); | 1218 | extern void free_area_init(unsigned long * zones_size); |
diff --git a/mm/memory.c b/mm/memory.c index bdf19366b705..567bca80ea53 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
| @@ -394,9 +394,11 @@ void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *vma, | |||
| 394 | } | 394 | } |
| 395 | } | 395 | } |
| 396 | 396 | ||
| 397 | int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address) | 397 | int __pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma, |
| 398 | pmd_t *pmd, unsigned long address) | ||
| 398 | { | 399 | { |
| 399 | pgtable_t new = pte_alloc_one(mm, address); | 400 | pgtable_t new = pte_alloc_one(mm, address); |
| 401 | int wait_split_huge_page; | ||
| 400 | if (!new) | 402 | if (!new) |
| 401 | return -ENOMEM; | 403 | return -ENOMEM; |
| 402 | 404 | ||
| @@ -416,14 +418,18 @@ int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address) | |||
| 416 | smp_wmb(); /* Could be smp_wmb__xxx(before|after)_spin_lock */ | 418 | smp_wmb(); /* Could be smp_wmb__xxx(before|after)_spin_lock */ |
| 417 | 419 | ||
| 418 | spin_lock(&mm->page_table_lock); | 420 | spin_lock(&mm->page_table_lock); |
| 419 | if (!pmd_present(*pmd)) { /* Has another populated it ? */ | 421 | wait_split_huge_page = 0; |
| 422 | if (likely(pmd_none(*pmd))) { /* Has another populated it ? */ | ||
| 420 | mm->nr_ptes++; | 423 | mm->nr_ptes++; |
| 421 | pmd_populate(mm, pmd, new); | 424 | pmd_populate(mm, pmd, new); |
| 422 | new = NULL; | 425 | new = NULL; |
| 423 | } | 426 | } else if (unlikely(pmd_trans_splitting(*pmd))) |
| 427 | wait_split_huge_page = 1; | ||
| 424 | spin_unlock(&mm->page_table_lock); | 428 | spin_unlock(&mm->page_table_lock); |
| 425 | if (new) | 429 | if (new) |
| 426 | pte_free(mm, new); | 430 | pte_free(mm, new); |
| 431 | if (wait_split_huge_page) | ||
| 432 | wait_split_huge_page(vma->anon_vma, pmd); | ||
| 427 | return 0; | 433 | return 0; |
| 428 | } | 434 | } |
| 429 | 435 | ||
| @@ -436,10 +442,11 @@ int __pte_alloc_kernel(pmd_t *pmd, unsigned long address) | |||
| 436 | smp_wmb(); /* See comment in __pte_alloc */ | 442 | smp_wmb(); /* See comment in __pte_alloc */ |
| 437 | 443 | ||
| 438 | spin_lock(&init_mm.page_table_lock); | 444 | spin_lock(&init_mm.page_table_lock); |
| 439 | if (!pmd_present(*pmd)) { /* Has another populated it ? */ | 445 | if (likely(pmd_none(*pmd))) { /* Has another populated it ? */ |
| 440 | pmd_populate_kernel(&init_mm, pmd, new); | 446 | pmd_populate_kernel(&init_mm, pmd, new); |
| 441 | new = NULL; | 447 | new = NULL; |
| 442 | } | 448 | } else |
| 449 | VM_BUG_ON(pmd_trans_splitting(*pmd)); | ||
| 443 | spin_unlock(&init_mm.page_table_lock); | 450 | spin_unlock(&init_mm.page_table_lock); |
| 444 | if (new) | 451 | if (new) |
| 445 | pte_free_kernel(&init_mm, new); | 452 | pte_free_kernel(&init_mm, new); |
| @@ -3253,7 +3260,7 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 3253 | pmd = pmd_alloc(mm, pud, address); | 3260 | pmd = pmd_alloc(mm, pud, address); |
| 3254 | if (!pmd) | 3261 | if (!pmd) |
| 3255 | return VM_FAULT_OOM; | 3262 | return VM_FAULT_OOM; |
| 3256 | pte = pte_alloc_map(mm, pmd, address); | 3263 | pte = pte_alloc_map(mm, vma, pmd, address); |
| 3257 | if (!pte) | 3264 | if (!pte) |
| 3258 | return VM_FAULT_OOM; | 3265 | return VM_FAULT_OOM; |
| 3259 | 3266 | ||
diff --git a/mm/mremap.c b/mm/mremap.c index 563fbdd6293a..b09eefaea0b8 100644 --- a/mm/mremap.c +++ b/mm/mremap.c | |||
| @@ -47,7 +47,8 @@ static pmd_t *get_old_pmd(struct mm_struct *mm, unsigned long addr) | |||
| 47 | return pmd; | 47 | return pmd; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | static pmd_t *alloc_new_pmd(struct mm_struct *mm, unsigned long addr) | 50 | static pmd_t *alloc_new_pmd(struct mm_struct *mm, struct vm_area_struct *vma, |
| 51 | unsigned long addr) | ||
| 51 | { | 52 | { |
| 52 | pgd_t *pgd; | 53 | pgd_t *pgd; |
| 53 | pud_t *pud; | 54 | pud_t *pud; |
| @@ -62,7 +63,8 @@ static pmd_t *alloc_new_pmd(struct mm_struct *mm, unsigned long addr) | |||
| 62 | if (!pmd) | 63 | if (!pmd) |
| 63 | return NULL; | 64 | return NULL; |
| 64 | 65 | ||
| 65 | if (!pmd_present(*pmd) && __pte_alloc(mm, pmd, addr)) | 66 | VM_BUG_ON(pmd_trans_huge(*pmd)); |
| 67 | if (pmd_none(*pmd) && __pte_alloc(mm, vma, pmd, addr)) | ||
| 66 | return NULL; | 68 | return NULL; |
| 67 | 69 | ||
| 68 | return pmd; | 70 | return pmd; |
| @@ -147,7 +149,7 @@ unsigned long move_page_tables(struct vm_area_struct *vma, | |||
| 147 | old_pmd = get_old_pmd(vma->vm_mm, old_addr); | 149 | old_pmd = get_old_pmd(vma->vm_mm, old_addr); |
| 148 | if (!old_pmd) | 150 | if (!old_pmd) |
| 149 | continue; | 151 | continue; |
| 150 | new_pmd = alloc_new_pmd(vma->vm_mm, new_addr); | 152 | new_pmd = alloc_new_pmd(vma->vm_mm, vma, new_addr); |
| 151 | if (!new_pmd) | 153 | if (!new_pmd) |
| 152 | break; | 154 | break; |
| 153 | next = (new_addr + PMD_SIZE) & PMD_MASK; | 155 | next = (new_addr + PMD_SIZE) & PMD_MASK; |
