diff options
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 32 |
1 files changed, 15 insertions, 17 deletions
diff --git a/mm/memory.c b/mm/memory.c index 153a54b2013c..e5628a5fd678 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -134,11 +134,9 @@ void pmd_clear_bad(pmd_t *pmd) | |||
134 | */ | 134 | */ |
135 | static void free_pte_range(struct mmu_gather *tlb, pmd_t *pmd) | 135 | static void free_pte_range(struct mmu_gather *tlb, pmd_t *pmd) |
136 | { | 136 | { |
137 | struct page *page = pmd_page(*pmd); | 137 | pgtable_t token = pmd_pgtable(*pmd); |
138 | pmd_clear(pmd); | 138 | pmd_clear(pmd); |
139 | pte_lock_deinit(page); | 139 | pte_free_tlb(tlb, token); |
140 | pte_free_tlb(tlb, page); | ||
141 | dec_zone_page_state(page, NR_PAGETABLE); | ||
142 | tlb->mm->nr_ptes--; | 140 | tlb->mm->nr_ptes--; |
143 | } | 141 | } |
144 | 142 | ||
@@ -309,21 +307,19 @@ void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *vma, | |||
309 | 307 | ||
310 | int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address) | 308 | int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address) |
311 | { | 309 | { |
312 | struct page *new = pte_alloc_one(mm, address); | 310 | pgtable_t new = pte_alloc_one(mm, address); |
313 | if (!new) | 311 | if (!new) |
314 | return -ENOMEM; | 312 | return -ENOMEM; |
315 | 313 | ||
316 | pte_lock_init(new); | ||
317 | spin_lock(&mm->page_table_lock); | 314 | spin_lock(&mm->page_table_lock); |
318 | if (pmd_present(*pmd)) { /* Another has populated it */ | 315 | if (!pmd_present(*pmd)) { /* Has another populated it ? */ |
319 | pte_lock_deinit(new); | ||
320 | pte_free(mm, new); | ||
321 | } else { | ||
322 | mm->nr_ptes++; | 316 | mm->nr_ptes++; |
323 | inc_zone_page_state(new, NR_PAGETABLE); | ||
324 | pmd_populate(mm, pmd, new); | 317 | pmd_populate(mm, pmd, new); |
318 | new = NULL; | ||
325 | } | 319 | } |
326 | spin_unlock(&mm->page_table_lock); | 320 | spin_unlock(&mm->page_table_lock); |
321 | if (new) | ||
322 | pte_free(mm, new); | ||
327 | return 0; | 323 | return 0; |
328 | } | 324 | } |
329 | 325 | ||
@@ -334,11 +330,13 @@ int __pte_alloc_kernel(pmd_t *pmd, unsigned long address) | |||
334 | return -ENOMEM; | 330 | return -ENOMEM; |
335 | 331 | ||
336 | spin_lock(&init_mm.page_table_lock); | 332 | spin_lock(&init_mm.page_table_lock); |
337 | if (pmd_present(*pmd)) /* Another has populated it */ | 333 | if (!pmd_present(*pmd)) { /* Has another populated it ? */ |
338 | pte_free_kernel(&init_mm, new); | ||
339 | else | ||
340 | pmd_populate_kernel(&init_mm, pmd, new); | 334 | pmd_populate_kernel(&init_mm, pmd, new); |
335 | new = NULL; | ||
336 | } | ||
341 | spin_unlock(&init_mm.page_table_lock); | 337 | spin_unlock(&init_mm.page_table_lock); |
338 | if (new) | ||
339 | pte_free_kernel(&init_mm, new); | ||
342 | return 0; | 340 | return 0; |
343 | } | 341 | } |
344 | 342 | ||
@@ -1390,7 +1388,7 @@ static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd, | |||
1390 | { | 1388 | { |
1391 | pte_t *pte; | 1389 | pte_t *pte; |
1392 | int err; | 1390 | int err; |
1393 | struct page *pmd_page; | 1391 | pgtable_t token; |
1394 | spinlock_t *uninitialized_var(ptl); | 1392 | spinlock_t *uninitialized_var(ptl); |
1395 | 1393 | ||
1396 | pte = (mm == &init_mm) ? | 1394 | pte = (mm == &init_mm) ? |
@@ -1401,10 +1399,10 @@ static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd, | |||
1401 | 1399 | ||
1402 | BUG_ON(pmd_huge(*pmd)); | 1400 | BUG_ON(pmd_huge(*pmd)); |
1403 | 1401 | ||
1404 | pmd_page = pmd_page(*pmd); | 1402 | token = pmd_pgtable(*pmd); |
1405 | 1403 | ||
1406 | do { | 1404 | do { |
1407 | err = fn(pte, pmd_page, addr, data); | 1405 | err = fn(pte, token, addr, data); |
1408 | if (err) | 1406 | if (err) |
1409 | break; | 1407 | break; |
1410 | } while (pte++, addr += PAGE_SIZE, addr != end); | 1408 | } while (pte++, addr += PAGE_SIZE, addr != end); |